来自服务器的 OAuth2“无效授权”响应
Posted
技术标签:
【中文标题】来自服务器的 OAuth2“无效授权”响应【英文标题】:OAuth2 "Invalid Grant" response from server 【发布时间】:2012-12-06 03:12:49 【问题描述】:我要求我的客户使用他创建 google api 项目的授权 gmail 帐户访问此 URL。
https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://www.XXXXXXXX.com/oauth2callback&client_id=XXXXXX.apps.googleusercontent.com&state=profile&approval_prompt=force
然后让他提供重定向 URL 中的 code 参数
http://www.XXXXXXXX.com/oauth2callback?code=4/jUxc2MdX0xmF-b4_I6v2SLMQMuxO.cvQLVEpcJMUXOl05ti8ZT3ZvsT9ddwI
然后我自己发布此表格并附上以下信息。
<form action="https://accounts.google.com/o/oauth2/token" method="post" >
<input type="hidden" name="grant_type" value="authorization_code" >
<input type="text" name="code" value="**is the one i recieved from previous step**">
<input type="hidden" name="client_id" value="XXXXXXX.apps.googleusercontent.com" >
<input type="hidden" name="client_secret" value="XXXXXXXXXXXX" >
<input type="hidden" name="redirect_uri" value="http://www.XXXXXX.com/oauth2callback" >
<input type="submit" value="Submit">
</form>
然后我得到以下错误
"error" : "invalid_grant"
当我自己生成代码 url 参数并执行下一步时。我已成功收到以下回复
"access_token" : "XXXXXXStBkRnGyZ2mUYOLgls7QVBxOg82XhBCFo8UIT5gM",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "XXXXXX3SEBX7F2cfrHcqJEa3KoAHYeXES6nmho"
但如果客户端生成 url 参数“代码”,那么我会看到无效的授权错误。
我的客户在英国,而我在另一个国家。任何人都可以确认这是否是错误,因为客户端正在另一个国家/地区生成代码参数,而我在另一个国家/地区使用该代码?
提前致谢。
【问题讨论】:
【参考方案1】:我对 invalid_grant 错误感到恼火,而不是同一代码有时会为我提供正确的访问令牌。
Shaikh 的回答指引我正确的方向。
首先我们尝试从以下位置获取访问代码:
https://accounts.google.com/o/oauth2/auth
用户被引导到“允许权限”屏幕,然后我们的应用会收到访问代码。
使用该访问代码,我们尝试从以下位置获取访问令牌:
https://accounts.google.com/o/oauth2/token
在第一次尝试中,它会返回 access_token 和 grant_type=authorization_code,但是一旦向我们提供了 access_token,它就不再期望再次收到 grant_type=authorization,而是希望收到 grant_type=refresh_token
安卓开发者代码如下:
String accessToken = null, refreshToken = null;
HttpPost httppost = new HttpPost(https://accounts.google.com/o/oauth2/token);
HttpParams myParams = new BasicHttpParams();
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("client_id", BLOGGER_CLIENT_ID));
SharedPreferences prefs = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
String bloggerAccessToken = prefs.getString(PREFERENCES_KEY_BLOGGER_ACCESS_TOKEN, null);
if(bloggerAccessToken != null && bloggerAccessToken.length() > 0)
nameValuePairs.add(new BasicNameValuePair("refresh_token", prefs.getString(PREFERENCES_KEY_BLOGGER_REFRESH_TOKEN, null)));
nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
else
nameValuePairs.add(new BasicNameValuePair("code", prefs.getString(PREFERENCES_KEY_BLOGGER_ACCESS_CODE, null)));
nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
nameValuePairs.add(new BasicNameValuePair("redirect_uri", "http://localhost"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient httpClient = new DefaultHttpClient(myParams);
response = httpClient.execute(httppost);
String returnedJsonStr = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = new JSONObject(returnedJsonStr);
accessToken = jsonObject.getString("access_token");
if(jsonObject.has("refresh_token"))
refreshToken = jsonObject.getString("refresh_token");
【讨论】:
【参考方案2】:您可以要求客户端自己生成代码以及随后的刷新令牌。让他访问上面生成 refresh_token 的表单。
那么就可以使用refresh_token来生成access_tokens了。
希望它能解决您的问题。
【讨论】:
以上是关于来自服务器的 OAuth2“无效授权”响应的主要内容,如果未能解决你的问题,请参考以下文章
如何在 OAuth2 资源服务器中设置自定义 403 响应?
来自 oauth2 安全休息 Web 服务的 Spring 休息服务 api 调用
授权代码流后,Spring OAuth2 服务器没有响应刷新令牌
Spring Security OAuth2何时检查访问令牌到期?
如果下游服务响应 401,如何在 Zuul API 网关中触发 OAuth2 身份验证
spring-security oauth2 REST 服务器在错误凭据(400)错误响应中不需要的 Stacktrace