165

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

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

精简版

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

长版

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

其中一项第三方服务将是 Google,它允许用户使用他们的 Google 帐户对我的服务进行身份验证。稍后将扩展到包括 Yahoo 帐户、受信任的 OpenID 提供商等。

基于 Google 的访问的示意图示例:

替代文字

“API”实体在我的完全控制之下。“公共界面”实体是任何基于 Web 或桌面的应用程序。一些公共接口在我的控制之下,其他的不会,还有一些我可能永远都不知道。

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

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

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

Google 文档清楚地说明了如何使用访问令牌从许多 Google 服务中检索数据。似乎没有任何说明如何首先检查给定的访问令牌是否有效。

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

此外,我永远不会使用 Google 身份验证访问令牌来访问任何 Google 服务,只是作为一种验证假定的 Google 用户实际上是他们所说的人的手段。如果有另一种方法可以做到这一点,我很乐意尝试。

4

12 回答 12

167

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

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

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

反应会像

{
     "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 的给定权限。您可以在此链接中检查范围 ID

更新: 新的 API 帖子如下

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

响应将是

 {
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

欲了解更多信息,https://developers.google.com/identity/sign-in/android/backend-auth

于 2014-07-09T06:01:59.820 回答
67

好的,大多数答案都是有效的,但并不完全正确。JWT 的想法是您可以验证令牌,而无需每次都联系颁发者。您必须检查 id 并使用用于签署令牌的证书的已知公钥验证令牌的签名。

请参阅下一篇文章为什么以及如何做到这一点。

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

于 2016-08-02T11:20:52.863 回答
40

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

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

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

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

于 2017-05-26T02:21:57.030 回答
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;
    }
}
于 2012-05-08T12:35:22.083 回答
10

Google oauth 代码流响应access_token返回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 托管域匹配的 hd 声明。

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

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

于 2015-07-23T20:03:38.757 回答
7

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

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

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

https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<access token>
于 2021-04-05T18:01:20.967 回答
3
  1. 根据 Google 的文档,您应该使用 Google 的 AP 客户端库,这使得这(令牌验证、声明提取等)比编写自己的自定义代码更容易。

  2. 从性能的角度来看,应该在本地解析令牌,而无需再次调用 Google。离场谷歌的公钥是必需的,并且该密钥的检索是使用缓存策略完成的,在上面#1的谷歌客户端库中实现。

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

在此处输入图像描述

于 2020-10-17T02:36:37.213 回答
1

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

不需要。您只需为您的 API 域中的 Google 帐户用户请求标准登录并使用联合登录。只有在那之后,您才能将“持久用户 ID”与“公共界面”中的用户 ID 进行比较。

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

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

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

于 2009-01-12T01:59:34.603 回答
1

这是使用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();
}
于 2015-07-13T03:09:21.347 回答
0

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

于 2009-02-26T06:51:51.513 回答
0

任意 OAuth 访问令牌不能用于身份验证,因为令牌的含义超出了 OAuth 核心规范。它可以用于单次使用或狭窄的过期窗口,也可以提供用户不想提供的访问权限。它也是不透明的,获得它的 OAuth 消费者可能从未见过任何类型的用户标识符。

OAuth 服务提供者和一个或多个消费者可以轻松地使用 OAuth 来提供可验证的身份验证令牌,并且有一些建议和想法可以做到这一点,但是一个只讲 OAuth 核心的任意服务提供者在没有其他合作伙伴的情况下无法提供这个与消费者的协调。Google 特定的 AuthSubTokenInfo REST 方法以及用户的标识符很接近,但它也不合适,因为它可能会使令牌无效,或者令牌可能已过期。

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

OpenID 包括仅将用户发送到 OP 并返回已签名的断言。互动完全是为了 RP 的利益。没有长期存在的令牌或其他特定于用户的句柄可用于指示 RP 已成功通过 OP 对用户进行身份验证。

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

于 2009-08-28T23:45:18.707 回答
0

检查以下网址。它运作良好。它的官方文件来自谷歌本身。

推荐使用 Google API 客户端库之一(例如 Java、Node.js、PHP、Python)在生产环境中验证 Google ID 令牌。

https://developers.google.com/identity/sign-in/android/backend-auth#using-a-google-api-client-library

于 2022-02-27T06:14:15.130 回答