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

Hi @eldarj and @nkfir

I’m also need to inject custom claims in my access token.

My principal concern here is about the refresh token. When my access token expires and I refresh it, I will need to pass the custom claims again in the refresh endpoint or I can “query” the old access token and copy them from there to the new one?

The only way is to implement a custom Protocol Mapper? Can you provide a functional code example?

Hi
our implementation is to sent the custom claims in a special header containing json claims base64 encoded.
The protocol mapper takes the header, decode it and add it to the token claims.
This is done both in auth call or refresh call.

Nice, and this ProtocolMapper can manipulate the claims from all tokens (id token, access token, refresh token, userinfo) ???

yes
look for AbstractOIDCProtocolMapper implementation examples
like this

1 Like

You never want to manipulate the refresh token, this is not in your concern. The refresh token is only meant for the issuing party (the AS/IdP, here: Keycloak) itself.

Everything else, you can control with the protocol mappers.

Nice, thanks a lot.

I have just more 1 question… Can I contract custom query-params to the authorization flows (like authorization code and others)

I know that OIDC has the claims parameter, but it has an specific schema. I would like to create my own query-param named “extra-claims”.

Can I do this? The keycloak will let it passtrought without validating it and I will be able to recover it inside the Protocol Mapper implementation?