Provide Additional claims when getting access token

I’m trying to provide additional claims when requesting the token on

/auth/realms/realm-name/protocol/openid-connect/token

I tried providing claims as query params or in the header, besides the client id and secret, but the token returned never contains the custom claims provided.

How can I achieve this?

I would say that requesting claims as query parameter is not a standard approach -Final: OpenID Connect Core 1.0 incorporating errata set 1

On the Keycloak level you should to define mapper in the used OIDC client config (you can play also with scopes, which is abstraction on top of mappers). Then that mapper(s) will create claim(s) in the token.

1 Like

I added the Claims parameter Token Mapper, so I assumed adding ‘claims’ in header would get Keycloak to add them into the response token, but that’s not happening.

I know that I can create other mappers as well, but I don’t want these to be resolved and evaluated on Keycloak, such as user attributes, roles etc. but I need some custom ones to add.

Any ideas whether the above mentioned Claims parameter mapper just isn’t working, or it’s for something else?

I don’t understand your use case, but it is definetely good idea to provide reproducible example first.

I really don’t understand:

I added the Claims parameter Token Mapper, so I assumed adding ‘claims’ in header

Claims parameter Token Mapper - this type of mapper doesn’t exist in the Keycloak by default :person_shrugging:
adding ‘claims’ in header - you mentioned first that you used query parameters :person_shrugging:
:person_shrugging::person_shrugging::person_shrugging:

Good question/description gives you good answer and higher chance for some answer as well.

I tried providing claims as query params or in the header

First thing, I wrote that I tried both adding it as query param or within the headers. And I tried adding it as query params only because in some places in docs it is not clear.

Second thing, if you check the docs or even the source, you’ll find ClaimsParameterTokenMapper.java

I’m not sure what you mean when you say it doesn’t exist.

And finally, I really don’t get what would be hard for you to understand here - when providing a set of custom claims, when requesting the token, Keycloak doesn’t return these claims in the token.

But thanks for the advice in any case.

Doc is your friend: Final: OpenID Connect Core 1.0 incorporating errata set 1 - it is Authorization Request parameter, not a Token Request parameter.

1 Like

Of course I agree, but it’s hard to follow OpenID docs, when you’re supposed to follow Keycloak docs itself.

Thanks for the link

Hi
we implemented similar mechanism to add our custom claims to the access token as follow:

  • Adding in request a custom header containing our custom claims json - base64 encoded

  • Implement a protocol mapper, which configuration of the name of the custom header and type (Json)

  • The mapper read the custom header value, decode the value and the json value to the access token

Example code

@Override
protected void setClaim(AccessTokenResponse token, ProtocolMapperModel mappingModel,
UserSessionModel userSession, KeycloakSession keycloakSession,
ClientSessionContext clientSessionCtx) {
JsonNode claimNode = extractClaim(mappingModel, keycloakSession, userSession.getUser().getUsername());
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, claimNode);
}

private JsonNode extractClaim(ProtocolMapperModel mappingModel, KeycloakSession keycloakSession, String userName) {
String headerName = mappingModel.getConfig().get(“header.name”);
List headerValueList = keycloakSession.getContext().getRequestHeaders().getRequestHeaders().get(headerName);
String claimJsonStr = “”;
String claimTokenHeaderStr = “”;
try {
if (headerValueList != null && headerValueList.size() > 0) {
claimTokenHeaderStr = headerValueList.get(0);
byte[] decodedBytes = Base64.getDecoder().decode(claimTokenHeaderStr);
claimJsonStr = new String(decodedBytes);
ObjectNode objectNode = (ObjectNode) objectMapper.readTree(claimJsonStr);
return objectNode;
} else {
logger.error(“Header " + headerName + " not found”);
}
} catch (Exception e) {
logger.error("Failed to base64 decode value " + claimTokenHeaderStr, e);
}
return null;
}

2 Likes

I was thinking that Keycloak provides this functionality out of the box, with an existing mapper, but yeah - seems like you have to implement your own.

Thanks a lot for your reply, I think I’ll solve it in the same way

Hi,

I am also trying to implement the same thing.

Were you able to aching this provide additional claims when requesting the token.

How can I achieve this?

I believe I have the same request. How do I return my additional claims as part of the ID Token?

Try looking up AbstractOIDCProtocolMapper and OIDCAccessTokenMapper.

I ended up implementing a custom mapper SPI, and overriding the transformAccessToken method.

Something like

public class MyTokenMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
...
@Override
  public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel,
      KeycloakSession session, UserSessionModel userSession,
      ClientSessionContext clientSessionCtx
  ) {

    token.getOtherClaims().put("someClaimName", someHashMapOrObject);
    return super.transformAccessToken(token, mappingModel, session, userSession, clientSessionCtx);
}
...
}

I think you need a RPT. The RPT = access token + authorization.

You can use a built-in mapper if you want to add claims from user attributes or properties.

1 Like