Invalid_token error when exchanging google id_token for a set of keycloak tokens

I’m developing a mobile application, which uses keycloak for user auth.
I have run into problems adding Google social signin to it.

For the client (app side) I’ve set up the native GoogleSignin (called with “userinfo.profile” and “userinfo.email” scopes] and created an OAuth2 android client in the Google Developer Console.
I’ve also created a web client in the Google console to obtain the client_id and client_secret (for keycloak).
In the keycloak dashboard I’ve set up google as identity provider, with a token-exchange policy for my-app client within my-realm.

At this point after signin in the app I can get a JWT id_token from Google:

{:scopes #js ["https://www.googleapis.com/auth/userinfo.profile" "https://www.googleapis.com/auth/userinfo.email"], :serverAuthCode nil, :idToken "eyJhb...", :user #js {:photo "http://photo.jpg", :email "fubar@fu.bar", :familyName "Bar", :givenName "Fu", :name "Fu Bar", :id "1234"}}

I than ask keycloak to exchange it for its own tokens within the realm, so that the app can go back to a “normal” auth flow:

curl -X POST \
    -d "client_id=my-app" \
    -d "client_secret=mkU..." \
    --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
    --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
    -d "subject_issuer=google" \
    -d "audience=my-app" \
    -d "subject_token=${idToken}" \
    http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token

but it fails, with 401 when checking the token presumably:

keycloak_1  | 12:17:39,810 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-1) AUTHENTICATE CLIENT
keycloak_1  | 12:17:39,810 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-1) client authenticator: client-secret
keycloak_1  | 12:17:39,811 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-1) client authenticator SUCCESS: client-secret
keycloak_1  | 12:17:39,811 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-1) Client my-app authenticated by client-secret
keycloak_1  | 12:17:39,839 DEBUG [org.keycloak.broker.oidc.OIDCIdentityProvider] (default task-1) GOOGLE userInfoUrl: https://openidconnect.googleapis.com/v1/userinfo
keycloak_1  | 12:17:39,892 DEBUG [org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider] (default task-1) Failed to invoke user info status: 401

keycloak_1  | 12:17:50,055 WARN  [org.keycloak.events] (default task-9) type=TOKEN_EXCHANGE_ERROR, realmId=my-realm, clientId=my-app, userId=null, ipAddress=172.18.0.1, error=invalid_token, reason='user info call failure', auth_method=token_exchange, grant_type=urn:ietf:params:oauth:grant-type:token-exchange, subject_issuer=google, validation_method='user info', client_auth_method=client-secret

As a side-note if I navigate to http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/auth?client_id=my-app&response_type=code I can create a new user within the realm using google link / button, so the provider must be set up correctly, its specifically the token_exchange that’s failing…

To answer my own question the solution is to obtain access_token (not identity_token) from google, which can than be exchanged without problems.

1 Like

I am in a very similar situation with the same set up as you. I also created an android client in the Google Developer Console and the Web client (because you have to have a client secret to set up google idp in keycloak). But my code for my application uses the android’s client_id that is on the Google Dev Console because I have been unable to retrieve google token response using the web client_id. Do you mind sharing your code/any packages you used in order to retrieve your google tokens? When I use the android client_id and google as the issuer, I receive a token response, but when I use the access token I receive in a curl or postman call I get the exact same error. If you could provide the format of the access token when you made the call or share the code you have to retrieve this access token from google I would greatly appreciate it.