Custom claims under OIDC Enterprise Connection User Mapping not included on id_token

The auth0 docs for OIDC attribute mapping provide numerous examples of providing custom claims. For instance, it includes this example of providing a sf_community_id field:

"attribute_map": {
    . . .
    “attributes”: {
        …
        “sf_community_id”: “3423409219032-32”
    }
}

However, I believe I’m observing that the claim mapping only supports the non-restricted claims list for the mapping, as evidenced by the id_token generated by the following mapping:

{
  "attributes": {
    "name": "${context.userinfo.given_name}",
    "email": "${context.userinfo.email}",
    "birthdate": "${context.userinfo.birthdate}",
    "family_name": "${context.userinfo.family_name}",
    "phone_number": "${context.userinfo.phone_number}",
    "sf_community_id": "123456",
    "nickname": "foo"
  },
  "mapping_mode": "use_map"
}
{
  "family_name": "<redacted>",
  "nickname": "foo",
  "name": "<redacted>",
  "picture": "<redacted>",
  "birthdate": "<redacted>",
  "updated_at": "2023-10-11T15:21:11.900Z",
  "email": "<redacted>",
  "iss": "<redacted>",
  "aud": "<redacted>",
  "iat": 1697037672,
  "exp": 1697073672,
  "sub": "<redacted>",
  "sid": "<redacted>",
  "nonce": "<redacted>"
}

Here, we see “nickname” has been set to the constant “foo”, but there is no “sf_community_id” present.

In our example we desire to map custom claims from the external IDPs userinfo, in a manner consistent with the other userinfo fields.

The docs indicate that this should be supported, and I’m unclear if there are any other dependencies I’m not tracking.

What is the recommended approach to solve for this mapping scenario?

Hi @will.bastian,

Welcome to the Auth0 Community!

Would you mind DMing me the name of the tenant so I can take a look?

Thanks for providing your tenant name.

I was able to get the “sf_community_id” in the ID token by setting up an Action to add it as a custom claim. I’m unable to find any other way to get it in the token, including adding the claim to the scope param with the request.

Here’s the Action I used:

exports.onExecutePostLogin = async (event, api) => {
  if (event.user.sf_community_id) {
    api.idToken.setCustomClaim("sf_community_id", event.user.sf_community_id)
  }
};

Hope that helps!

1 Like

Hey Dan, Thanks! This does indeed solve for the asked question of how to define a custom claim in the OIDC user mapping, and including it on the id_token.

In exploring this further in our specific use cases I’m now met with a following question:
If one of our claim’s contents is an object, is there any means to pull specific fields out of the source object and into our custom claims?

For instance, let’s reference a claim on userinfo named my_object_claim that contains an object with a single element, my_subobject

"my_object_claim": {"my_subobject": "foo"}

–1–
I’m finding that if we apply this mapping at the my_object_claim level, we’re met with the contents of

"my_object_claim": "[object Object]",

in the id_token

This is through providing both the user mapping, and the appropriate action

mapping:

  "attributes": {
    "name": "${context.userinfo.given_name}",
    "my_object_claim": "${context.userinfo.my_object_claim}"
  },

action:

exports.onExecutePostLogin = async (event, api) => {
  if (event.user.my_object_claim) {
    api.idToken.setCustomClaim("my_object_claim", event.user.my_object_claim)
  }
};

–2–
Then, if we attempt to update the user mapping json definition to go the level further into the object contents of my_object_claim, we cannot chain object element lookup past the top level claim.

If we update our user mapping to be:

  "attributes": {
    "name": "${context.userinfo.given_name}",
    "my_subobject_claim": "${context.userinfo.my_object_claim.my_subobject}"
  },

We’re met with:

expected context.tokenset, context.connection or contect.userinfo property access: "my_subobject_claim" ${context.userinfo.my_object_claim.my_subobjectd} found: Identifier

–3–
Finally, as in 1, above, it appears we’ve already called translated my_object_claim to "[object Object]", perhaps via calling toString on it? This appears to indicate while we have the ability to update the action to introspect further into the object, it’s already a string and there’s nothing to further introspect beyond the string contents of "[object Object]"

So, doing something like

exports.onExecutePostLogin = async (event, api) => {
  if (event.user.my_object_claim) {
    api.idToken.setCustomClaim("my_object_claim", event.user.my_object_claim.my_subobject_claim)
  }
};

Returns null

Thanks for the thorough write up.

Just to confirm, when the user mapping happens (not the Action), the object is casted to a string and retains just the placeholder "[object Object]" string. Then in the action, that is all that is available.

Is that what you see in the user’s profile in the dashboard too?

Hey Dan, that is an accurate summary of my working hypothesis. The "[object Object]" serialization is present on both the id_token, as well as the user profile raw json in the dashboard.

Thanks for the confirmation. I’m going to reach out to the team and see if I can get a definitive answer.

Hi @will.bastian,

I wasn’t able to find a definitive answer on this. I suspect that object literals aren’t supported in this case. Can you please create a feature request in our Feedback category?

Hey @dan.woda - Thanks for digging into it. I’ve created a feature request at Allow object mapping/introspection in Enterprise OIDC custom claim mapping

For posterity, and anybody who finds themselves in a similar scenario, our workaround is to leverage context.tokenset.access_token mapping in the enterprise OIDC connection, and subsequently using the access_token now present on the id_token to make an explicit call to the external IDP’s userinfo to pull the information we need out of the object claim.

Separately, are there means or channels to propose update to the Auth0 docs? Your clarification around the necessity of leveraging an action to map the custom claims defined in the enterprise OIDC connection was instrumental in this all making sense, and I feel it would be a strong addition to the existing doc at Configure PKCE and Claim Mapping for OIDC Connections

1 Like

Thanks for the thorough write-up!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.