Auth0 suddenly not allowing not namespaced custom claims in the token

So after the new update we moved all our access token custom claims from namespaced to not namespaced custom claims (we are aware of the not allowed claim names and therefor our names are for sure not striking any rules).
Up to what I said above this was working before. But now we see that those are ignored. Can’t give you a date but it broke suddenly.
No logs about “depreciations”.

So may I know why does auth0 ignore my not namespaced custom claims and allows them when I use namespaced naming.

Important to know
Auth0 DOES put those custom claims in my IDTOKEN. (I can see them in the JWT ID token)

In case you guys want to see a code example:

// THIS WILL BE ALLOWED:
api.accessToken.setCustomClaim(`https://custom.com/userId`, payload.userId);

// THIS WILL BE IGNORED:
api.accessToken.setCustomClaim(`userId`, payload.userId);
// we also tried "randomText_userId" and that didn't work aswell

Place/Location of the action:

  • After login

Whole code snippet

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  const userLoginMethod = event.user.user_id.split("|")[0]; // waas, git, auth, etc

  const axios = require("axios");
  const jwt = require("jsonwebtoken")
  const URL_TO_BACK_END = "https://cencoredDomain/api"
  const ENDPOINT = "/cencoredEndpoint"

  const TOKEN = api.redirect.encodeToken({
    secret: event.secrets.SHARED_SECRET,
    payload: {
      firstName: event.user.given_name || '',
      lastName: event.user.family_name || '',
      email: event.user.email,
      userName: event.user.username || event.user.nickname || `${event.user.name||event.user.given_name}${event.user.family_name||''}`,
      allIdentities: event.user.identities,
      userLoginMethod: userLoginMethod
    },
  })
  try{
    // Now get the user if he exist.
    const getUser = await axios.get(`${URL_TO_BACK_END}${ENDPOINT}`, {
      headers: {
      'content-type': 'application/json',
      'Authorization': `Bearer ${TOKEN}`,
      'cencored': 'cencored'
      }
    });
    
    const payload = jwt.verify(getUser.data.accessToken, event.secrets.SHARED_SECRET)
    // None of the below accessToken claims work. only the IDTOKEN claims work
    // userId
    api.idToken.setCustomClaim(`userId`, payload.userId);
    api.accessToken.setCustomClaim(`userId`, payload.userId);

    // userType
    api.idToken.setCustomClaim(`userType`, payload.userType);
    api.accessToken.setCustomClaim(`userType`, payload.userType);

    // customerIds
    api.idToken.setCustomClaim(`customerIds`, payload.customerIds);
    api.accessToken.setCustomClaim(`customerIds`, payload.customerIds);

    api.idToken.setCustomClaim(`userPermissions`, payload.permissions);
    api.accessToken.setCustomClaim(`userPermissions`, payload.permissions);

    api.idToken.setCustomClaim(`departments`, payload.departments);
    api.accessToken.setCustomClaim(`departments`, payload.departments);
    
    api.user.setUserMetadata('languageCode', payload.languageCode)

  } catch (err) {
    api.access.deny(err.response.data);
  }
};


/**
* Handler that will be invoked when this action is resuming after an external redirect. If your
* onExecutePostLogin function does not perform a redirect, this function can be safely ignored.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
/*
exports.onContinuePostLogin = async (event, api) => {
};
*/

1 Like

Hey there @11TStudio welcome back!

Interesting - The only thing I’m aware of related to this was the migration that happened at the end of July.

I’m not seeing any reason in particular the non-namespaced claim would be ignored in your code - I’m curious, do you get a similar claim to come through if you are to create another basic action to test. Something like:

exports.onExecutePostLogin = async (event, api) => {
  if (event.authorization) {
     api.idToken.setCustomClaim(`userId`, event.user.user_id);
    api.accessToken.setCustomClaim(`userId`, event.user.user_id);
  }
}

In testing in my own environment, I’m not currently able to reproduce what you are seeing. I am able to add non-namespaced claims to both ID and access tokens.

Let us know!

Hey @tyf

I wont spend more time on this issue as I did tested this mutliple times with multiple tenants.
Access token has not been decorised but the id token does. Might be something temporal but since persistance is important for us we immidiatly moved to namespaced as we are 100% certain it works (and it does).

However I suspect it would be because;

  • the claims being too large (but then it doesn’t even accept the custom claim userId which is basically an uuid)
  • or it would be that the action thinks the call comes internally (as I have read somewhere where it wouldn’t put the non namespaced claims if they came internally). I might be wrong with this one tho as I couldn’t find the place where I readed this…

Thanks for the fast reply between :slight_smile: