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


134

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

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

简短版本
很明显,如何通过Google身份验证Api ::用于Web应用程序的OAuth身份验证提供的访问令牌可以用于从一系列Google服务中请求数据。目前尚不清楚如何检查给定的访问令牌对于给定的Google帐户是否有效。我想知道如何。

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

谷歌是第三方服务之一,它允许用户使用其Google帐户针对我的服务进行身份验证。以后将扩展到包括Yahoo帐户,受信任的OpenID提供程序等。

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

替代文字http://webignition.net/images/figures/auth_figure002.png

“ 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用户实际上是他们所说的身份的一种方式。如果还有另一种方法,我很乐意尝试。


这个问题与什么特定的身份验证服务有关(OAuth,AuthSub,已安装的应用程序,...)?请提供更详细的链接。
Martin v。Löwis08年

@Martin诉Löwis:“针对Web应用程序的OAuth身份验证”服务-我已经更新了问题的开头以反映这一点。感谢您指出了这一点!
乔恩·克拉姆

有关Google密钥验证的有趣文章可能会提供更多见解groups.google.com/group/Google-Maps-API/msg/f9e3c5ad3cbda4d7
dotjoe

Answers:


138

为了进行用户检查,只需将访问令牌作为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


11
Google的oauth2-v3有一个较新的版本。在此处查看示例:developers.google.com/identity/sign-in/android/backend-auth
AlikElzin-kilaka


25

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

请参阅下一篇文章为什么以及如何执行此操作。

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


2
请更多投票!The idea of JWT is that you can validate the token without the need to contact the issuer everytime.
Moritz Schmitz诉Hülst,

是!如果他们只是打电话给Google以获得令牌信息,则ppl正在google上
daddinhquoc

您无法使用Google访问令牌执行此操作,因为它们不是JWT。检查stackoverflow.com/questions/48623656/...
DanielJaramillo

18
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
这个答案几乎仍然有效。但是似乎不再设置Issued_to。developers.google.com/accounts/docs/…–
frostymarvelous

6

Google oauth代码流响应以及access_token返回的结果id_token也包含有用的加密形式的验证信息。

使ID令牌有用的一件事是您可以在应用程序的不同组件之间传递它们。这些组件可以将ID令牌用作轻量级身份验证机制,对应用程序和用户进行身份验证。但是,在您可以使用ID令牌中的信息或将其用作用户已通过身份验证的断言之前,您必须对其进行验证。

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

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

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

另请参阅/security/37818/why-use-openid-connect-instead-of-plain-oauth


1

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

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

域值用于Google联合登录页面上,以向用户标识请求站点。它还用于确定Google返回的永久用户ID的值。

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

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


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();
}

0

尝试使用您对https://www.google.com/accounts/AuthSubTokenInfo的令牌进行OAuth身份验证的请求。该文档仅适用于AuthSub,但也适用于OAuth。它不会告诉您该令牌用于哪个用户,但是会告诉您该令牌对哪个用户有效,并且如果令牌无效或已被撤销,则请求将失败。


0

不能使用任意OAuth访问令牌进行身份验证,因为令牌的含义不在OAuth Core规范的范围内。它可以用于单次使用或狭窄的到期时间窗口,也可以提供用户不想授予的访问权限。它也是不透明的,获得它的OAuth使用者可能从未见过任何类型的用户标识符。

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

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

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

验证针对OpenID标识符的先前身份验证的一种方法是仅在使用相同的用户代理的情况下再次执行身份验证。OP应该能够在没有用户交互的情况下返回肯定的断言(例如,通过验证Cookie或客户端证书)。OP可以自由地要求其他用户交互,如果身份验证请求来自另一个域,则OP可能会进行交互(我的OP给我提供了重新验证此特定RP的选项,以后无需进行交互)。在Google的情况下,用户获取OAuth令牌所经过的UI可能不会使用相同的会话标识符,因此用户将不得不重新进行身份验证。但是无论如何,您都可以声明身份。


Google弃用了OpenID 2.0,并禁用了它,取而代之的是基于OAuth的OpenID Connect,它提供了可验证的ID令牌
Vadzim 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.