使用从 JavaScript 客户端收到的令牌在服务器上创建社交连接
Use token received from JavaScript client to create a social connection on the server
我有一个使用 PHP/JavaScript 的网页,可以在客户端成功执行 Google 登录过程。然后我想将获得的令牌转发到使用 Spring-Social 创建社交连接的后端,并能够调用应用程序已获得授权的 APIs。
我设法在 Facebook (OAUTH2) 和 Twitter (OAUTH1) 上都做到了这一点,它们都完美地工作,但是对于 Google,我在尝试创建连接时总是收到 401 响应。
服务器中的代码是这样的:
AccessGrant accessGrant = new AccessGrant(accessToken);
connection = ((OAuth2ConnectionFactory<?>) connectionFactory).createConnection(accessGrant);
客户端的代码是这样的:
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Email: ' + profile.getEmail());
var access_token = googleUser.getAuthResponse().id_token;
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost/signin/google');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
console.log('access_token=' + access_token);
};
xhr.send('access_token=' + access_token);
}
后者的大部分是从 Google 文档中复制的关于如何使用后端服务器进行身份验证的文档:https://developers.google.com/identity/sign-in/web/backend-auth
我追踪了 spring-social-google 内部的调用,它们导致对 https://www.googleapis.com/oauth2/v2/userinfo 的 REST 调用,即回复 401 和以下 JSON:
{
"error": {
"errors": [{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}],
"code": 401,
"message": "Invalid Credentials"
}
}
我自己尝试调用相同的 REST API,我也得到了相同的响应,所以这似乎不是 spring-social-[=52 的问题=] 正如我在其他一些帖子中读到的那样,没有正确发送令牌。
我认为这个问题与 JavaScript API 给我一个 "id_token" 而 REST API 期待一个 "access_token"。但是,我没有找到一种方法来获取访问令牌作为与 id_token 分开的东西,并且 Google 文档确实将 id_token 发送到后端。 "access_token" 属性 在 googleUser.getAuthResponse() 中使用的 "id_token" 属性 旁边有一个 "access_token" 属性 但它返回未定义。
这个文档当然不是针对 spring-social 所以我并不是说它不正确,我只是想知道实现这个的正确方法是什么。
spring-无法处理 id_token 是社会的错吗?
我没有看到一些明确的方法来获得 access_token 是我的错吗?
无论如何,我觉得我有点接近了,但解决方案似乎仍然无法掌握。
谢谢!
嗯,我找到了。看来把整件事都写下来真的是脑子里有什么东西绊倒了...
问题实际上是 id_token 不能代替 access_token。根据我的口味,Google 文档在他们展示的示例中可能对此更明确一些,但他们最终在 https://developers.google.com/identity/sign-in/web/reference
的实际客户参考中对其进行了解释
关键是 getAuthResponse() 的布尔参数,它是可选的,默认为 false。来自文档:
includeAuthorizationData Optional: A boolean that specifies whether
to always return an access token and scopes. By default, the access
token and requested scopes are not returned when fetch_basic_profile
is true (the default value) and no additional scopes are requested.
通过在我的 JS 中将其设置为 true,填充了以前未定义的 access_token 字段,使用此令牌可以访问 /oauth2/v2/userinfo 端点和 spring-social-google 可以像其他提供商一样正确地创建连接。
我希望这至少对其他人有所帮助。
我有一个使用 PHP/JavaScript 的网页,可以在客户端成功执行 Google 登录过程。然后我想将获得的令牌转发到使用 Spring-Social 创建社交连接的后端,并能够调用应用程序已获得授权的 APIs。 我设法在 Facebook (OAUTH2) 和 Twitter (OAUTH1) 上都做到了这一点,它们都完美地工作,但是对于 Google,我在尝试创建连接时总是收到 401 响应。 服务器中的代码是这样的:
AccessGrant accessGrant = new AccessGrant(accessToken);
connection = ((OAuth2ConnectionFactory<?>) connectionFactory).createConnection(accessGrant);
客户端的代码是这样的:
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Email: ' + profile.getEmail());
var access_token = googleUser.getAuthResponse().id_token;
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost/signin/google');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
console.log('access_token=' + access_token);
};
xhr.send('access_token=' + access_token);
}
后者的大部分是从 Google 文档中复制的关于如何使用后端服务器进行身份验证的文档:https://developers.google.com/identity/sign-in/web/backend-auth
我追踪了 spring-social-google 内部的调用,它们导致对 https://www.googleapis.com/oauth2/v2/userinfo 的 REST 调用,即回复 401 和以下 JSON:
{
"error": {
"errors": [{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}],
"code": 401,
"message": "Invalid Credentials"
}
}
我自己尝试调用相同的 REST API,我也得到了相同的响应,所以这似乎不是 spring-social-[=52 的问题=] 正如我在其他一些帖子中读到的那样,没有正确发送令牌。
我认为这个问题与 JavaScript API 给我一个 "id_token" 而 REST API 期待一个 "access_token"。但是,我没有找到一种方法来获取访问令牌作为与 id_token 分开的东西,并且 Google 文档确实将 id_token 发送到后端。 "access_token" 属性 在 googleUser.getAuthResponse() 中使用的 "id_token" 属性 旁边有一个 "access_token" 属性 但它返回未定义。 这个文档当然不是针对 spring-social 所以我并不是说它不正确,我只是想知道实现这个的正确方法是什么。
spring-无法处理 id_token 是社会的错吗?
我没有看到一些明确的方法来获得 access_token 是我的错吗?
无论如何,我觉得我有点接近了,但解决方案似乎仍然无法掌握。
谢谢!
嗯,我找到了。看来把整件事都写下来真的是脑子里有什么东西绊倒了...
问题实际上是 id_token 不能代替 access_token。根据我的口味,Google 文档在他们展示的示例中可能对此更明确一些,但他们最终在 https://developers.google.com/identity/sign-in/web/reference
的实际客户参考中对其进行了解释关键是 getAuthResponse() 的布尔参数,它是可选的,默认为 false。来自文档:
includeAuthorizationData Optional: A boolean that specifies whether to always return an access token and scopes. By default, the access token and requested scopes are not returned when fetch_basic_profile is true (the default value) and no additional scopes are requested.
通过在我的 JS 中将其设置为 true,填充了以前未定义的 access_token 字段,使用此令牌可以访问 /oauth2/v2/userinfo 端点和 spring-social-google 可以像其他提供商一样正确地创建连接。
我希望这至少对其他人有所帮助。