我想获取授权码,以便为我的应用启用服务器端API访问。我在Unity3D中使用针对Unity的Google Play游戏服务插件执行此过程。我有从GoogleAuthUtils类调用本机getToken()函数的函数:
public string GetToken() {
string token = null;
Debug.Log("Before RetrieveUserEmail");
string email = RetrieveUserEmail() ?? "NULL";
Debug.Log("After RetrieveUserEmail email: " + email);
string scope = "oauth2:server:client_id:" + "666666666666-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com"
+ ":api_scope:" + "https://www.googleapis.com/auth/plus.login";
using (AndroidJavaClass jc_unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"),
jc_gau = new AndroidJavaClass("com.google.android.gms.auth.GoogleAuthUtil")) {
using(AndroidJavaObject jo_Activity = jc_unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) {
token = jc_gau.CallStatic<string>("getToken", jo_Activity, email, scope);
}
}
Debug.Log("Token " + token);
return token;
}
但是我得到了AndroidJavaException:com.google.android.gms.auth.UserRecoverableAuthException:NeedPermission
此功能接合正常,因为它适用于
string scope = "audience:server:client_id:" + "666666666666-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com"
并返回受众标记。
我无法想象我做错了什么。
有什么建议吗?
或者你可以澄清一下,即使用URL调用:
将我重定向到像
这样的网址参数代码= 4 / YUVer ...
是那个代码是我试图通过Unity函数得到的那个代码吗?
提前感谢,我将不胜感激。
答案 0 :(得分:0)
一些值得检查的事情:
当您从Android发出请求时,您的重定向URI将是特定于设备的重定向URI,urn:ietf:wg:oauth:2.0:oob。
您获得的错误表示用户在授权应用时点击取消(或从未点击确认)。如果您正在获取授权代码(4 / YUY ....字符串),那么这不应该发生。
authZ,访问令牌,刷新令牌和授权代码有三种重要的OAuth响应类型。如果您尝试将访问令牌(或刷新令牌)作为授权代码进行交换,则响应将没有任何意义。确保您使用getToken中的授权代码,并在执行令牌交换时传递正确匹配的重定向URI。
回到你的评论,这是有道理的:
是那个代码是我试图通过Unity函数得到的那个代码吗?
OAuth服务器重定向后获得的代码是您想要的代码,它是从getToken中的Android返回的。有关获取/交换代码的更多信息,请查看Google+ Android Client & Server Sign-In上的博客文章。
有关如何获取代码的演示,请参阅Haiku+ Android client。相关代码是:
public String getCodeSynchronous() throws GoogleAuthException, CodeException {
StringBuilder scopeString = new StringBuilder("");
for (String scope : Constants.SCOPES) {
scopeString.append(" ").append(scope);
}
String scope = new StringBuilder("oauth2:server:client_id:")
.append(Constants.SERVER_CLIENT_ID)
.append(":api_scope:")
.append(scopeString.toString())
.toString();
Bundle appActivities = new Bundle();
String types = TextUtils.join(" ", Constants.ACTIONS);
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES, types);
String code = null;
try {
code = GoogleAuthUtil.getToken(
mContext,
mAccountName,
scope,
appActivities);
// Immediately invalidate so we get a different one if we have to try again.
GoogleAuthUtil.invalidateToken(mContext, code);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
throw new CodeException("Error: could not establish connection to server.");
}
return code;
}
有关如何更换代码服务器端,请参阅Haiku+ Java server:
try {
// Upgrade the authorization code into an access and refresh token.
return new GoogleAuthorizationCodeTokenRequest(HaikuPlus.TRANSPORT,
HaikuPlus.JSON_FACTORY,
getClientId(),
getClientSecret(),
authorization,
redirectUri).execute();
} catch (TokenResponseException e) {
//Failed to exchange authorization code.
logger.log(Level.INFO, "Failed to exchange auth code; return 400", e);
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return null;
} catch (IOException e) {
logger.log(Level.INFO, "Failed to exchange auth code; return 400", e);
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
答案 1 :(得分:0)
我有同样的问题。这就是我解决它的方式。
第1步:我在Try Sign-In for Android跟踪了Google文档。所以我有登录工作。我必须按照本教程Start Integrating Google Sign-In into Your Android App创建&#34; Android的客户端ID&#34;
第2步: 同样,在我为Android&#34;创建&#34;客户端ID的同时,我必须为Web&#34;创建&#34;客户端ID。这一步给了我&#34; Web的客户端ID&#34;我稍后会用。
第3步:
按照本教程获取令牌ID&#34;使用后端服务器进行身份验证&#34;。在登录时onConnected方法中,添加
GetIdTokenTask getIdTokenTask = new GetIdTokenTask();
getIdTokenTask.execute();
您可以按照教程&#34;找到GetIdTokenTask课程。 使用后端服务器进行身份验证&#34; 。以下是onConnected方法的示例。
@Override
public void onConnected(Bundle bundle) {
// onConnected indicates that an account was selected on the device, that the selected
// account has granted any requested permissions to our app and that we were able to
// establish a service connection to Google Play services.
Log.d(TAG, "onConnected:" + bundle);
mShouldResolve = false;
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
Log.d(TAG, "onConnected:" + "start GetIdTokenTask");
GetIdTokenTask getIdTokenTask = new GetIdTokenTask();
getIdTokenTask.execute();
} else {
Log.d(TAG, "onConnected:" + "Cannot get current person's information.");
}
// Show the signed-in UI
showSignedInUI();
}
第4步:配置我们可以从 GetIdTokenTask 类
中的第2步获得的SERVER_CLIENT_ID以下是GetIdTokenTask的示例。
private class GetIdTokenTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
Account account = new Account(accountName, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
String scopes = "audience:server:client_id:" + SERVER_CLIENT_ID; // Not the app's client ID.
try {
return GoogleAuthUtil.getToken(getApplicationContext(), account, scopes);
} catch (IOException e) {
Log.e(TAG, "Error retrieving ID token.", e);
return null;
} catch (GoogleAuthException e) {
Log.e(TAG, "Error retrieving ID token.", e);
return null;
}
}
@Override
protected void onPostExecute(String result) {
Log.i(TAG, "ID token: " + result);
if (result != null) {
// Successfully retrieved ID Token
// ...
} else {
// There was some error getting the ID Token
// ...
}
}
}