我使用 Facebook 登录来识别用户。当一个新用户到来时,我将他们的用户 ID 存储在我的数据库中。下次他们来的时候,我认出了他们的 Facebook ID,并且我知道它在我的数据库中是哪个用户。
现在我正在尝试对 Google 的 OAuth2 做同样的事情,但是我怎样才能识别用户呢?
Google 向我发送了几个代码和令牌(access_token、id_token、refresh_token),但它们都不是恒定的。这意味着如果我注销并在 2 分钟后重新登录,所有 3 个值都已更改。如何唯一标识用户?
我正在使用他们的 PHP 客户端库:https://code.google.com/p/google-api-php-client/
正如其他人所提到的,您可以使用刚刚收到的 OAuth2 不记名令牌向 https://www.googleapis.com/oauth2/v3/userinfo 发送 GET,您将收到包含有关用户的一些信息(id、姓名等)的响应。
还值得一提的是,Google 实现了 OpenID Connect,而这个用户信息端点只是其中的一部分。
OpenID Connect 是 OAuth2 之上的身份验证层。在 Google 的令牌端点交换授权 code
时,您会获得一个访问令牌(access_token
参数)以及一个 OpenID Connect ID 令牌(id_token
参数)。
这两个令牌都是 JWT(JSON Web 令牌,https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token)。
如果你解码它们,你会得到一些断言,包括用户的 id。如果将此 ID 链接到数据库中的用户,则可以立即识别他们,而无需执行额外的 userinfo GET(节省时间)。
如评论中所述,这些令牌使用 Google 的私钥签名,您可能需要使用 Google 的公钥 (https://www.googleapis.com/oauth2/v3/certs) 验证签名以确保它们是真实的。
您可以通过将 JWT 粘贴到 https://jwt.io/(向下滚动以查看 JWT 调试器)来查看 JWT 中的内容。断言看起来像:
{
"iss":"accounts.google.com",
"id":"1625346125341653",
"cid":"8932346534566-hoaf42fgdfgie1lm5nnl5675g7f167ovk8.apps.googleusercontent.com",
"aud":"8932346534566-hoaf42fgdfgie1lm5nnl5675g7f167ovk8.apps.googleusercontent.com",
"token_hash":"WQfLjdG1mDJHgJutmkjhKDCdA",
"iat":1567923785,
"exp":1350926995
}
还有用于各种编程语言的库以编程方式解码 JWT。
PS:要获取 Google 的 OpenID Connect 提供商支持的 URL 和功能的最新列表,您可以检查该 URL:https://accounts.google.com/.well-known/openid-configuration。
我将此方法插入到 google-api-php-client/src/apiClient.php 中:
public function getUserInfo()
{
$req = new apiHttpRequest('https://www.googleapis.com/oauth2/v1/userinfo');
// XXX error handling missing, this is just a rough draft
$req = $this->auth->sign($req);
$resp = $this->io->makeRequest($req)->getResponseBody();
return json_decode($resp, 1);
}
现在我可以打电话了:
$client->setAccessToken($_SESSION[ 'token' ]);
$userinfo = $client->getUserInfo();
它返回一个像这样的数组(如果已请求该范围,则加上电子邮件):
Array
(
[id] => 1045636599999999999
[name] => Tim Strehle
[given_name] => Tim
[family_name] => Strehle
[locale] => de
)
解决方案源自此线程:https://groups.google.com/forum/#!msg/google-api-php-client/o1BRsQ9NvUQ/xa532MxegFIJ
id_token
现在在键 sub
中包含静态标识符,而不是在键 id
中,如之前和上面的示例中那样。 AFAIK,这种变化是他们对 OpenID Connect 协议的解释。不幸的是,在我写这篇文章的时候,响应似乎有些随机:有时是 id
,有时是 sub
,所以我需要同时支持这两者。
/oauth2/v1/userinfo
会给你 id
,而 /oauth2/v3/userinfo
会给你 sub
(注意不同的版本!)如果你不提供版本,它可能会改变?
应该提到的是,OpenID Connect API 不再返回 id
属性。
它现在是用作唯一用户标识的 sub
属性。
请参阅Google Dev OpenID Connect UserInfo
sub
不同。刚刚在另一个线程 stackoverflow.com/questions/53421907/… 中问了这个问题
“这是谁?”本质上是一种服务;您必须以 范围 的形式请求访问它,然后向 Google 配置文件 资源服务器 发出请求以获取身份。有关详细信息,请参阅 OAuth 2.0 for Login。
可以使用公钥在本地验证 JWT,(Google API 客户端库会自动下载并缓存它们的公钥)通过 https://www.googleapis.com/oauth2/v1/tokeninfo 端点检查 Google 端的令牌是必要的,以检查应用程序的访问权限是否已被撤销令牌的创建。
不定期副业成功案例分享
tr '._-' '\n/+' | sed '2s|$|===|p;d' | base64 -D
传递 id 令牌。sed
中的2
选择元组的第二部分,这可能是您想要的。