【发布时间】:2014-12-07 06:52:58
【问题描述】:
问题
将 Google Plus Sign In Api 与 Play 框架一起使用时,您是否必须以不同的方式设置标头?我在这里做错了什么吗?
背景
我正在使用 Play Framework(在 Java 中)来使用 Google Plus Sign in Api。
我在 OAuth 身份验证的第二阶段遇到了问题,将 Authorization Code 交换为 Token。
基本 OAuth 流程
- 将用户重定向到
User login/Consent screen- 这会询问用户是否要授予您对所请求范围的应用程序权限
- 网址:
https://accounts.google.com/o/oauth2/auth
- 将
Authorization Code换成Token- 如果用户授予您的应用程序权限,那么他们将被重定向到您指定的 URL,其中该 URL(作为
GET参数)将是Authorization Code。 - 然后您的应用程序可以使用此
Authoriztion Code从服务器获取Token - 您的应用程序通过向 Google 服务器(或您正在使用的任何服务)上的端点发出 HTTP 请求来执行此操作
- 网址:
https://accounts.google.com/o/oauth2/token
- 网址:
- 如果用户授予您的应用程序权限,那么他们将被重定向到您指定的 URL,其中该 URL(作为
- 在 API 请求中使用
Token
问题
要将Authorization Code 换成Token,使用Google Plus Sign In Api,您必须向https://accounts.google.com/o/oauth2/token 发出POST 请求,并具有以下边界
{
"code": "Security Code Returned from Step 1",
"client_id": "Client Id that was given to you in GApi Console",
"client_secret": "Client Secret that was given to you in the GApi Console",
"redirect_uri": "Redirect Uri you specified in the GApi Console",
"grant_type": "authorization_code"
}
但是,当我使用所有正确的参数发出这个请求时,我得到了这个错误
{
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
来自 Google Plus 登录 API
要在 Play Framework 中发出 HTTP 请求,请使用 WS Library。我提出这样的要求
public static F.Promise<Result> OAuthCallback(String state, String code){
/*
Note:
- The GoogleStrategy class is just a class that holds all my GApi credentials
- The parameters (String state, String code) are just GET params from Step 1, returned by the GApi
*/
//Make URL builder
WSRequestHolder requestHolder = WS.url(GoogleStrategy.getTokenUrl);
//Set headers
requestHolder.setHeader("code", code);
requestHolder.setHeader("client_id", GoogleStrategy.clientId);
requestHolder.setHeader("client_secret", GoogleStrategy.clientSecret);
requestHolder.setHeader("redirect_uri", GoogleStrategy.redirectUri);
requestHolder.setHeader("grant_type", GoogleStrategy.grantType);//GoogleStrategy.grantType = "authorization_code"
//Make HTTP request and tell program what to do once the HTTP request is finished
F.Promise<Result> getTokenPromise = requestHolder.post("").map(
new F.Function<WSResponse, Result>() {
public Result apply(WSResponse response){
return ok(response.asJson());//Returning result for debugging
}
}
);
return getTokenPromise;//Return promise, Play Framework will handle the Asynchronous stuff
}
如你所见,我设置了标题grant_type。为了确保设置标头正常工作,我制作了一个程序,在 NodeJS(Source) 中吐出请求的标头,这就是结果
{
"HEADERS": {
"host": "127.0.0.1:3000",
"code": "4/qazYoReIJZAYO9izlTjjJA.gihwUJ6zgoERgtL038sCVnsvSfAJkgI",
"grant_type": "authorization_code",
"client_secret": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"redirect_uri": "http://127.0.0.1:9000/api/users/auth/google/callback",
"client_id": "XXXX-CENSORED FOR SECURITY PURPOSES-XXX",
"content-type": "text/plain; charset=utf-8",
"connection": "keep-alive",
"accept": "*/*",
"user-agent": "NING/1.0",
"content-length": "14"
}
}
【问题讨论】:
-
你应该用你得到的错误更新你的答案。
-
您已经在我的回答中的评论中发布了该信息(您的代码)。我要的是你得到的错误(即你从谷歌得到的 HTTP 代码和正文)。
-
@Salem Oops Edited(那是我的愚蠢:P)
-
查看我的编辑。您也可以尝试在 redirect_uri 值中使用url encoding。
标签: java web-services oauth playframework google-api