Skip to content

Commit

Permalink
feat: migrating idp userinfo changes
Browse files Browse the repository at this point in the history
  • Loading branch information
NithinKuruba committed Apr 23, 2024
1 parent 8acef67 commit 3e4808e
Showing 1 changed file with 52 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,22 @@ public class IDPUserinfoMapper extends AbstractOIDCProtocolMapper

private static final Logger logger = Logger.getLogger(IDPUserinfoMapper.class);

private static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
private static final String BEARER = "Bearer";

private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();

public static final String CLAIM_VALUE = "claim.value";

public static final String USER_ATTRIBUTE = "userAttribute";

public static final String DECODE_USERINFO_RESPONSE = "decodeUserInfoResponse";

static {
configProperties.add(new ProviderConfigProperty(DECODE_USERINFO_RESPONSE, "Decode UserInfo Response",
"Decode response returned from IDP userinfo endpoint", ProviderConfigProperty.BOOLEAN_TYPE, false));
configProperties.add(new ProviderConfigProperty(USER_ATTRIBUTE, "User Attribute",
"User Attribute returned from IDP userinfo endpoint", ProviderConfigProperty.STRING_TYPE, null));

OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, IDPUserinfoMapper.class);
}
Expand Down Expand Up @@ -74,6 +85,17 @@ private static JsonNode parseJson(String json) {
}
}

private static String decodeUserInfoResponse(String token) {
try {
String[] tokenParts = token.split("\\.");
Base64.Decoder decoder = Base64.getUrlDecoder();
String payload = new String(decoder.decode(tokenParts[1]));
return payload;
} catch (Exception e) {
return null;
}
}

@Override
protected void setClaim(
IDToken token,
Expand All @@ -91,22 +113,34 @@ protected void setClaim(
String userInfoUrl = identityProviderModel.getConfig().get("userInfoUrl");

if (userInfoUrl != null) {
FederatedIdentityModel identity =
keycloakSession.users().getFederatedIdentity(realm, userSession.getUser(), idp);
FederatedIdentityModel identity = keycloakSession.users().getFederatedIdentity(realm, userSession.getUser(),
idp);
String brokerToken = identity.getToken();
AccessTokenResponse brokerAccessToken = parseTokenString(brokerToken);
Client httpClient = ClientBuilder.newClient();
String userinfoString =
httpClient
.target(userInfoUrl)
.request()
.header("Authorization", "Bearer " + brokerAccessToken.getToken())
.get(String.class);

JsonNode jsonNode = parseJson(userinfoString);
Map<String, Object> otherClaims = token.getOtherClaims();
otherClaims.put(
mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME), jsonNode);
String userinfoString = httpClient
.target(userInfoUrl)
.request()
.header("Authorization", "Bearer " + brokerAccessToken.getToken())
.get(String.class);
boolean decode = Boolean.parseBoolean(mappingModel.getConfig().get(DECODE_USERINFO_RESPONSE));
if (decode) {
userinfoString = decodeUserInfoResponse(userinfoString);
}
try {
JsonNode jsonNode = parseJson(userinfoString);
if (jsonNode == null) {
logger.error("null response returned from [" + idp + "] userinfo URL");
}
Map<String, Object> otherClaims = token.getOtherClaims();
otherClaims.put(
mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME),
jsonNode.get(mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME)));
} catch (NullPointerException e) {
logger.errorf("'%s' returned invalid response", idp);
} catch (Exception e) {
logger.errorf("unable to fetch attributes from userinfo endpoint '%s'", userInfoUrl);
}
} else {
logger.error("Identity Provider [" + idp + "] does not have userinfo URL.");
}
Expand All @@ -123,8 +157,10 @@ public static ProtocolMapperModel create(
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
Map<String, String> config = new HashMap<>();
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, tokenClaimName);
if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
if (accessToken)
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
if (idToken)
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
mapper.setConfig(config);
return mapper;
}
Expand Down

0 comments on commit 3e4808e

Please sign in to comment.