Обмен токенами — Android Google Keycloak

#android #keycloak #passport-google-oauth2 #token-exchange

#Android #поиск ключей #паспорт-google-oauth2 #обмен токенами

Вопрос:

Контекст:

Я разрабатываю собственное приложение для Android, аутентифицирую его с помощью входа в Google, и оно работает.

У меня также есть сервер Keycloak, интегрированный с Google в качестве поставщика удостоверений, и он также работает.

Я могу импортировать свою учетную запись из Google при первом входе в систему, используя доступ к веб-браузеру http://localhost:8080/auth/realms/chapa/account /.

Когда я захожу в консоль Keycloak, я нахожу, что моя учетная запись создана и связана с Google.

Моя настройка поставщика удостоверений Google была выполнена с использованием (OpenID Connect v1 https://accounts.google.com/.well-known/openid-configuration ) или социальный Google на Keycloak.

Оба способа работают с использованием навигации по браузеру, так как я видел, что мало кто жаловался на то, что плагин Keycloak был сломан.

Моя проблема:

В моем приложении для Android я не могу выполнить обмен токенами с сервером Keycloak.

Я провел исследование, и это единственный способ интегрировать Android Google Keycloak, поскольку я не хочу снова запрашивать свои учетные данные пользователя. Пожалуйста, дайте мне знать, если вы знаете другие способы.

На моем сервере Keycloak я получаю что-либо еще, кроме этого ПРЕДУПРЕЖДЕНИЯ:

08:09:48 831 ПРЕДУПРЕЖДЕНИЕ [org.keycloak.events] (задача по умолчанию-11) type=TOKEN_EXCHANGE_ERROR, realmId=my-realm, ClientID=android-app, userId= null, IPAddress = 172.17.0.1, ошибка = invalid_token, причина = ‘сбой вызова информации о пользователе’, auth_method=token_exchange,grant_type=urn:ietf:параметры: oauth: тип предоставления: обмен токенами, subject_issuer=https://accounts.google.com, validation_method=’информация о пользователе’, client_auth_method=секрет клиента

Это запрос, который я выполняю против Keycloak вручную в Postman, ожидая обмена токенами:

 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"
}
 

Код Android:

 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
 

Ответ №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();