语境:
我正在开发一个原生 Android 应用程序,使用 Google SignIn 对其进行身份验证并且它正在运行。
我还有一个 Keycloak 服务器作为身份提供者与谷歌集成,它也可以工作。
首次登录时,我可以使用访问 http://localhost:8080/auth/realms/chapa/account/ 的网络浏览器从 Google 导入我的帐户。
当我进入 Keycloak 控制台时,我发现我的帐户已创建并与 Google 相关联。
我的 Google 身份提供程序设置是使用 (OpenId Connect v1 + https://accounts.google.com/.well-known/openid-configuration ) 或 Keycloak 上的 Social Google 完成的。
这两种方式都可以使用浏览器导航,因为我看到很少有人抱怨 Keycloak 插件坏了。
我的问题:
在我的 Android 应用程序上,我无法使用 Keycloak 服务器执行令牌交换。
我做了一项研究,这是集成 Android + Google + Keycloak 的唯一方法,因为我不想再次询问我的用户凭据。如果您知道其他方法,请告诉我。
在我的 Keycloak 服务器上,我得到的不是这个警告:
08:09:48,831 WARN [org.keycloak.events](默认任务 11)类型=TOKEN_EXCHANGE_ERROR,realmId=my-realm,clientId=android-app,userId=null,ipAddress=172.17.0.1,error=invalid_token,原因='用户信息调用失败', auth_method=token_exchange, grant_type=urn:ietf:params:oauth:grant-type:token-exchange, subject_issuer=https://accounts.google.com, validation_method='用户信息', client_auth_method =客户机密
这是我在 Postman 上手动对 Keycloak 执行的请求,期望交换令牌:
curl --location --request POST 'http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=android-app' \
--data-urlencode 'client_secret=a1739b19-3131-4f5c-ba31-8d24afff8d84' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token' \
--data-urlencode 'subject_token=eyJhbGciOiJSUzI1NiIsImtpZCI6... (truncated)' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:jwt' \
--data-urlencode 'subject_issuer=google'
邮递员响应(400 错误请求):
{
"error": "invalid_token",
"error_description": "invalid token"
}
安卓代码:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken(clientId) //same client id used on Keycloak Identity Provider
.requestScopes(new Scope(Scopes.PROFILE), new Scope(Scopes.PLUS_ME), new Scope(Scopes.EMAIL))
.build();
GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(getApplicationContext(), gso);
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(getApplicationContext());
Log.w("getServerAuthCode", account.getServerAuthCode()); //null
Log.w("getIdToken", account.getIdToken()); //value passed on Postman subject_token parameter