Login 如何识别Google OAuth2用户?

Login 如何识别Google OAuth2用户?,login,google-api,oauth-2.0,Login,Google Api,Oauth 2.0,我使用Facebook登录来识别用户。当新用户到来时,我将他们的用户ID存储在数据库中。下次他们来的时候,我认出了他们的Facebook ID,我知道我的数据库中是哪个用户 现在我正试图用谷歌的OAuth2做同样的事情,但是我如何才能识别用户呢 谷歌给我发送了几个代码和令牌(access\u令牌、id\u令牌、refresh\u令牌),但它们都不是常量。这意味着,如果我在2分钟后注销并重新登录,则所有3个值都已更改。如何唯一标识用户 我正在使用他们的PHP客户端库:“这是谁?”本质上是一种服务;

我使用Facebook登录来识别用户。当新用户到来时,我将他们的用户ID存储在数据库中。下次他们来的时候,我认出了他们的Facebook ID,我知道我的数据库中是哪个用户

现在我正试图用谷歌的OAuth2做同样的事情,但是我如何才能识别用户呢

谷歌给我发送了几个代码和令牌(access\u令牌、id\u令牌、refresh\u令牌),但它们都不是常量。这意味着,如果我在2分钟后注销并重新登录,则所有3个值都已更改。如何唯一标识用户


我正在使用他们的PHP客户端库:

“这是谁?”本质上是一种服务;您必须请求将其作为作用域访问,然后向Google profile资源服务器发出请求以获取标识。有关详细信息,请参阅。

我将此方法插入到google api php客户端/src/apiClient.php中:

公共函数getUserInfo() { $req=新的apiHttpRequest('https://www.googleapis.com/oauth2/v1/userinfo'); //XXX错误处理缺失,这只是一个草稿 $req=$this->auth->sign($req); $resp=$this->io->makeRequest($req)->getResponseBody(); 返回json_解码($resp,1); } 现在我可以打电话:

$client->setAccessToken($_会话['token']);
$userinfo=$client->getUserInfo();
它返回如下数组(如果已请求该作用域,则加上电子邮件):

数组
(
[id]=>104563659999999
[姓名]=>蒂姆·斯特莱尔
[给定名称]=>Tim
[family_name]=>Strehle
[语言环境]=>de
)
解决方案源自此线程:

Java版本


正如其他人所提到的,您可以使用刚刚收到的OAuth2承载令牌发送一个GET to,您将得到一个带有用户信息(id、姓名等)的响应

还值得一提的是,Google实现了这个用户信息端点,它只是其中的一部分

是OAuth2之上的身份验证层。在Google的令牌端点交换授权时,您会得到一个访问令牌(参数
access\u令牌
以及一个OpenID连接ID令牌(参数
ID\u令牌

这两个令牌都是JWT(JSON Web令牌)

如果您解码它们,您将得到一些断言,包括用户的id。如果将此ID链接到数据库中的用户,则可以立即识别他们,而无需执行额外的userinfo GET(节省时间)

如评论中所述,这些令牌使用谷歌的私钥签名,您可能希望使用谷歌的公钥()验证签名,以确保它们是真实的

通过将JWT粘贴到(向下滚动查看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:要获得谷歌OpenID连接提供商支持的URL和功能的最新列表,您可以检查URL:。

尽管JWTs可以通过公钥在本地验证,(谷歌API客户端库自动下载并缓存它们的公钥)有必要通过端点检查Google端的令牌,以检查自令牌创建以来应用程序的访问是否已被撤销。

应该提到的是,OpenID Connect API不再返回任何
id
属性

现在是
sub
属性,作为唯一的用户标识


请参见

这似乎在技术上是最正确的,但它缺少当前公认答案所包含的额外细节。将这两个答案合并在一起,您将获得gold。是的,但是为了安全地使用此信息,您必须验证JWT的签名,您需要公钥。知道谷歌在哪里提供公钥吗?好的,找到了:我还应该指出,进行验证是绝对必要的,否则攻击者可以使用任何已经注册的谷歌帐户轻松登录到您的应用程序。我认为这并不完全准确。access_令牌不是JWT令牌,谷歌似乎已经删除了JWT解码器,但这里有一个易于使用的解码器:如果你不想将加密令牌粘贴到某个随机网站上,那么你也可以通过
tr.\u-''\ n/+'| sed'2s |$|==| p;d'| base64-d
sed
中的
2
选择元组的第二部分,这可能是您想要的。请注意,Google最近更改了响应,并且
id\u标记
现在在key
sub
中包含静态标识符,而不是像以前和上面的示例中那样在key
id
中。好了,这是他们对OpenID连接协议的解释。不幸的是,在我写这篇文章时,回答似乎有点随机:有时是
id
,有时是
sub
,所以我需要两者都支持。我认为
/oauth2/v1/userinfo
会给你
id
,而
/oauth2/v3/userinfo
会给你
sub
(注意不同的版本!)如果你不提供版本,它可能会改变?不确定这是否正确。不管文档的状态如何,如果我重新启动身份验证服务器,清除缓存并重新登录,“sub”是不同的。是否有其他人有HockeyJ的问题,即“sub”更改为相同的登录?是的,我有相同的问题,即
sub
不同。我只是在另一个帖子里问了这个问题