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…