Reputation: 354
I'm trying to integrate signup/login from linkedIn in my application which currently uses keycloak for authentication. I've implemented my flow in this way:
Here's an example code:
public JwtTokenResponse processOAuthCallbackAndGetToken(String code) {
// Step 1: Exchange authorization code for an access token
String accessToken = exchangeAuthorizationCodeForAccessToken(code);
// Step 2: Fetch user info from LinkedIn
Map<String, Object> userInfo = fetchLinkedInUserProfile(accessToken);
// Step 3: Create users in app
if (userInfo == null) {
throw new SomeException("Error occurred while fetching user info from LinkedIn.");
}
String email = (String) userInfo.get("email");
// create user in the application if needed
// Step 4: Create use in keycloak with federatedIdentity
log.info("User Info from LinkedIn ::: {}", userInfo);
Map<String, Object> federatedIdentity = new HashMap<>();
federatedIdentity.put("identityProvider", "linkedin");
federatedIdentity.put("userId", userInfo.get("sub")); // LinkedIn user ID
federatedIdentity.put("userName", email);
userService.createKeycloakUserWithFederatedIdentity(agentByEmail.getUser(), federatedIdentity);
log.info("Created user in keycloak with federated identity ::: {}", federatedIdentity);
// Step 5: Exchange LinkedIn access_token with jwt
return keycloakAuthServerConnector.getTokenFromLinkedInAccessToken(accessToken);
}
....
private static final String GRANT_TYPE_OAUTH_TOKEN_EXCHANGE =
"urn:ietf:params:oauth:grant-type:token-exchange";
private static final String REQUESTED_TOKEN_TYPE =
"urn:ietf:params:oauth:token-type:access_token";
public static final String PROTOCOL_OPENID_CONNECT_TOKEN = "/protocol/openid-connect/token";
public com.agencyheight.dto.onboardingv2.auth.JwtTokenResponse getTokenFromLinkedInAccessToken(
String accessToken) {
log.info("Requesting token with linkedIn access token :: {}", accessToken);
return webClient
.post()
.uri(PROTOCOL_OPENID_CONNECT_TOKEN)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(
BodyInserters.fromFormData("client_id", clientId)
.with("client_secret", clientSecret)
.with("grant_type", GRANT_TYPE_OAUTH_TOKEN_EXCHANGE)
.with("subject_token", accessToken)
.with("subject_issuer", "linkedin")
.with("requested_token_type", REQUESTED_TOKEN_TYPE))
.retrieve()
.bodyToMono(com.agencyheight.dto.onboardingv2.auth.JwtTokenResponse.class)
.block();
}
I'm getting this response from keycloak when trying to exchange token. Status : 400 Bad Request
{
"error": "invalid_token",
"error_description": "invalid token"
}
I have added the necessary configuration in keycloak:
I've enabled the token exchange permission as well and set the policy, as per this document : Granting permission for the exchange
What am I missing or what is causing the error?
Upvotes: 0
Views: 41
Reputation: 354
So the issue is that linkedIn's LinkedIn OpenID Connect, which provides opaque token, is supported only starting Keycloak's version 22 and greater New LinkedIn OpenID Connect social provider. I was using keycloak version 19 and worked on upgrading!
Upvotes: 0