1

语境:

我正在开发一个原生 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
4

1 回答 1

1

我修复了它,改变了获取令牌的方式:

new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... params) {
        try {
            String accessToken = GoogleAuthUtil.getToken(
                getApplicationContext(),
                account.getAccount().name, "oauth2:"
                        + "https://www.googleapis.com/auth/userinfo.profile" +
                        " https://www.googleapis.com/auth/plus.profile.emails.read");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }
}.execute();
于 2021-12-07T09:26:37.080 回答