如何验证Google身份验证API访问令牌?

时间:2008-12-11 14:11:04

标签: web-services api oauth google-oauth google-authentication

如何验证Google身份验证访问令牌?

我需要以某种方式查询Google并询问:[给定访问令牌]是否对[example@example.com] Google帐户有效?

短版
很明显,如何通过Google Authentication Api :: OAuth Authentication for Web Applications提供的访问令牌可用于从一系列Google服务中请求数据。目前尚不清楚如何检查给定的访问令牌是否对给定的Google帐户有效。我想知道怎么做。

长版
我正在开发一个使用基于令牌的身份验证的API。在提供有效的用户名+密码或从任何一个 N 可验证服务提供第三方令牌时,将返回令牌。

其中一项第三方服务是Google,允许用户使用其Google帐户对我的服务进行身份验证。稍后将扩展到包括雅虎帐户,可信赖的OpenID提供商等。

基于Google的访问的示意图:

alt text http://webignition.net/images/figures/auth_figure002.png

“API”实体完全由我完全控制。 “公共接口”实体是任何基于Web或桌面的应用程序。一些公共界面在我的控制之下,其他的则不在,而其他公共界面我甚至都不知道。

因此,我不相信在步骤3中提供给API的令牌。这将与相应的Google帐户电子邮件地址一起提供。

我需要以某种方式查询Google并询问:此访问令牌是否适用于example@example.com

在这种情况下,example @ example.com是Google帐户的唯一标识符 - 用户登录其Google帐户时使用的电子邮件地址。这不能被视为Gmail地址 - 有人可以在没有Gmail帐户的情况下拥有Google帐户。

Google文档明确说明了如何通过访问令牌从多个Google服务中检索数据。似乎没有说明如何在一开始就检查给定的访问令牌是否有效。

更新 该令牌对N Google服务有效。我不能尝试使用Google服务的令牌来验证它,因为我不知道给定用户实际使用的所有Google服务的哪个子集。

此外,我永远不会使用Google身份验证访问令牌来访问任何Google服务,仅仅是为了验证所谓的Google用户实际上是他们所说的人。如果还有另一种方法,我很乐意尝试。

12 个答案:

答案 0 :(得分:105)

对于用户检查,只需发布 获取访问令牌作为accessToken并发布并获得响应

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=accessToken

您也可以在浏览器的地址栏中尝试,也可以在java中使用httppost和响应

响应就像

{
     "issued_to": "xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
     "audience": "xxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
     "user_id": "xxxxxxxxxxxxxxxxxxxxxxx",
     "scope": "https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com",
     "expires_in": 3340,
     "access_type": "offline"
    }

范围是accessToken的给定权限。您可以在this link

中查看范围ID

答案 1 :(得分:19)

function authenticate_google_OAuthtoken($user_id)
{
    $access_token   = google_get_user_token($user_id); // get existing token from DB
    $redirecturl    = $Google_Permissions->redirecturl;
    $client_id      = $Google_Permissions->client_id;
    $client_secret  = $Google_Permissions->client_secret;
    $redirect_uri   = $Google_Permissions->redirect_uri;
    $max_results    = $Google_Permissions->max_results;

    $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$access_token;
    $response_contacts  =  curl_get_responce_contents($url);
    $response   =   (json_decode($response_contacts));

    if(isset($response->issued_to))
    {
        return true;
    }
    else if(isset($response->error))
    {
        return false;
    }
}

答案 2 :(得分:17)

您可以使用此终端验证Google身份验证访问令牌:

https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<access_token>

这是Google V3 OAuth AccessToken验证端点,您可以参考下面的google文档:(在OAUTH 2.0 ENDPOINTS标签中)

https://developers.google.com/identity/protocols/OAuth2UserAgent#validate-access-token

答案 3 :(得分:4)

好的,大多数答案都有效但不太正确。 JWT的想法是您可以验证令牌,而无需每次都与发卡机构联系。您必须检查ID并使用用于签署令牌的证书谷歌的已知公钥验证令牌的签名。

请参阅下一篇文章,了解为何以及如何执行此操作。

http://ncona.com/2015/02/consuming-a-google-id-token-from-a-server/

答案 4 :(得分:3)

access_token之外,

Google oauth code flow response还会返回id_token,其中包含对加密形式的验证信息有用的内容。

  

使ID令牌有用的一件事是你可以通过的事实   它们围绕您应用的不同组件。这些组件可以使用   ID令牌作为轻量级身份验证机制进行身份验证   应用和用户。但在您可以使用ID中的信息之前   令牌或依赖它作为用户已经过身份验证的断言,   你必须验证它。

     

验证ID令牌需要几个步骤:

  • 验证ID令牌是否是使用适当的Google公钥正确签名的JWT。
  • 验证ID令牌中的aud值是否等于应用的客户端ID。
  • 验证ID令牌中的iss值是否等于accounts.google.com或https://accounts.google.com
  • 验证ID令牌的到期时间(exp)是否未通过。
  • 如果您在请求中传递了hd参数,请验证ID令牌是否具有与您的Google Apps托管域匹配的高清版权声明。

https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken链接包含用于验证ID令牌的代码示例。

另见https://security.stackexchange.com/questions/37818/why-use-openid-connect-instead-of-plain-oauth

答案 5 :(得分:1)

  

我需要以某种方式查询Google并询问:此访问令牌是否对example@example.com有效?

没有。您所需要的只是通过API域中的Federated Login for Google Account Users请求标准登录。只有在此之后,您才能将“持久用户ID”与“公共接口”中的“持久用户ID”进行比较。

  

在Google联合登录页面上使用领域的价值来识别用户的请求站点。它还用于确定Google返回的持久用户ID的值。

因此,您需要来自与“公共接口”相同的域名。

并且不要忘记用户需要确保您的API可以信任;)因此Google会询问用户是否允许您检查他的身份。

答案 6 :(得分:1)

  1. 根据Google的documentation,您应该使用Google的AP客户端库,这比编写自己的自定义代码要容易得多(令牌验证,索赔提取等)。

  2. 从性能的角度来看,应该在本地解析令牌,而无需再次致电Google。需要偏离路线的Google公钥,并且使用缓存策略来检索该公钥,该策略在上述#1的Google客户端库中实现。

  3. 仅供参考。 Google还使用JWT令牌。参见下图以供参考。

enter image description here

答案 7 :(得分:1)

使用以下代码获取用户信息,例如姓名、电子邮件、照片等。

https://www.googleapis.com/oauth2/v3/userinfo?access_token=<access token>

使用以下代码获取令牌信息,例如到期时间、令牌范围等

https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<access token>

答案 8 :(得分:0)

尝试使用您的令牌向https://www.google.com/accounts/AuthSubTokenInfo发出经过OAuth身份验证的请求。这仅记录为适用于AuthSub,但它也适用于OAuth。它不会告诉您令牌是哪个用户,但它会告诉您哪些服务有效,如果令牌无效或已被撤销,请求将失败。

答案 9 :(得分:0)

任意OAuth访问令牌都不能用于身份验证,因为令牌的含义超出了OAuth Core规范。它可以用于单个用途或窄到期窗口,或者它可以提供用户不想提供的访问。它也是不透明的,获得它的OAuth使用者可能永远不会看到任何类型的用户标识符。

OAuth服务提供商和一个或多个消费者可以轻松使用OAuth提供可验证的身份验证令牌,并且有提案和想法可以实现此目的,但是只说OAuth Core的任意服务提供商无法提供此功能与消费者的其他协调。特定于Google的AuthSubTokenInfo REST方法以及用户的标识符已关闭,但它也不合适,因为它可能使令牌无效,或者令牌可能已过期。

如果您的Google ID是OpenId标识符,并且您的“公共界面”是网络应用或可以调用用户的浏览器,那么您应该使用Google的OpenID OP。

OpenID只是将用户发送到OP并获得签名断言。这种互动仅仅是为了RP的利益。没有长期令牌或其他特定于用户的句柄,可用于指示RP已成功通过OP验证用户。

根据OpenID标识符验证先前的身份验证的一种方法是再次执行身份验证,假设使用了相同的用户代理。 OP应该能够在没有用户交互的情况下返回肯定断言(例如,通过验证cookie或客户端证书)。 OP可以自由地要求另一个用户交互,如果身份验证请求来自另一个域,可能会这样做(我的OP让我可以选择重新验证这个特定的RP,而不会在将来进行交互)。在谷歌的情况下,用户通过获取OAuth令牌的UI可能不会使用相同的会话标识符,因此用户必须重新进行身份验证。但无论如何,你将能够断言身份。

答案 10 :(得分:0)

以下是使用Guzzle的示例:

/**
 * @param string $accessToken JSON-encoded access token as returned by \Google_Client->getAccessToken() or raw access token
 * @return array|false False if token is invalid or array in the form
 * 
 * array (
 *   'issued_to' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
 *   'audience' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
 *   'scope' => 'https://www.googleapis.com/auth/calendar',
 *   'expires_in' => 3350,
 *   'access_type' => 'offline',
 * )
 */
public static function tokenInfo($accessToken) {
    if(!strlen($accessToken)) {
        return false;
    }

    if($accessToken[0] === '{') {
        $accessToken = json_decode($accessToken)->access_token;
    }

    $guzzle = new \GuzzleHttp\Client();

    try {
        $resp = $guzzle->get('https://www.googleapis.com/oauth2/v1/tokeninfo', [
            'query' => ['access_token' => $accessToken],
        ]);
    } catch(ClientException $ex) {
        return false;
    }

    return $resp->json();
}

答案 11 :(得分:-2)

谷歌永远无法回答你的问题,因为它不是“这个访问令牌有效吗?”这是令牌+秘密。