Unable to add custom claim to access token

This simple rule seems to be executing upon user login, but I’m not able to see the custom claim in the user’s access token obtained from POST /oauth/token. Is there something I’m missing?

function (user, context, callback) {
  context.accessToken['http://example.com/email'] = 'test@example.com';
  console.log('Appears in logger extension upon login', context);
  callback(null, user, context);
}

Hi @johnwp,

Welcome to the Community!

Your code looks like it is adding the custom claim correctly. I tested out the rule in my own tenant, and after logging in, the decoded JWT Access Token looks like this:

{
  "http://example.com/email": "test@example.com",
  "iss": "https://my-domain.us.auth0.com/",
  "sub": "google-oauth2|115088824167938831773",
  "aud": [
    "https://test.com",
    "https://my-domain.us.auth0.com/userinfo"
  ],
  "iat": 1619003783,
  "exp": 1619003803,
  "azp": "iTAbnWQtk4voRjZyOp0ZHYL24s101ppB",
  "scope": "openid profile email",
  "permissions": []
}

When you decode the Access Token at https://jwt.io/, does it look similar (but missing the http://example.com/email claim)?

Hi @stephanie.chamblee, thanks so much for your help.

Here’s the decoded JWT Access Token that I’m getting. This is obtained using <Auth0Provider /> from npm package @auth0/auth0-react

I do have a custom database connection enabled. Do you think that could be interfering with this process? Thanks again!

{
  "nickname": "John",
  "name": "",
  "picture": "https://s.gravatar.com/avatar/73a4bedfdfd2929d20852b173b8e6f71?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fjp.png",
  "updated_at": "2021-04-21T15:49:39.157Z",
  "iss": "https://<my-domain>.us.auth0.com/",
  "sub": "auth0|1",
  "aud": "<Client ID for React SPA>",
  "iat": 1619020180,
  "exp": 1619056180,
  "nonce": "bFYydE94QXNBbkFTUThwaFQ5aHM4d20xbm44bzc3WVA2TGRCczE5bmZZUQ=="
}

Ah, okay! When you make the POST /oauth/token request, you should receive two tokens, an ID Token and an Access Token. The ID Token is used for your frontend to get basic profile info about the user. The Access Token is for your frontend to send to your API as a bearer token. The token you have shared looks like an ID Token.

If you’d like to add a custom claim to the ID Token, you’d adjust the rule like so:

function (user, context, callback) {
  context.idToken['http://example.com/email'] = 'test@example.com';
  console.log('Appears in logger extension upon login', context);
  callback(null, user, context);
}

To get the Access Token instead of the ID Token, you can use the getAccessTokenSilently hook:

const { getAccessTokenSilently } = useAuth0();

const token = await getAccessTokenSilently();

Hmm, very interesting. It looks like the values I’m getting for access_token and id_token might be swapped. Here’s what the response looks like for POST /oauth/token.

access_token is a short token and id_token is the JWT that I posted decoded above.

{
	"access_token": "ZXIrU2bPPgsHtFNJVZVk--TM<...truncated>",
	"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjBqa1p6RnllNzdIQ0QxenZRYVFZZiJ9.eyJuaWNrbmFtZSI6IkpvaG4gUG91Y2hhayIsIm5hbWUiOiIiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvNzNhNGJlZGZkZmQyOTI5ZDIwODUyYjE3M2I4ZTZmNzE_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZqcC5wbmciLCJ1cGRhdGVkX2F0IjoiMjAyMS0wNC0yMVQxNTo0OTozOS4xNTdaIiwiaXNzIj<...truncated>",
	"scope": "openid profile email",
	"expires_in": 86400,
	"token_type": "Bearer"
}

Also, when using:

const { getAccessTokenSilently } = useAuth0();
const token = await getAccessTokenSilently();

I get a non-JWT short token that looks like what’s assigned to access_token in my example response above.

Does that seem right?

It sounds like your app may be receiving an opaque token. An opaque token is returned when an audience is not specified in the Auth0Provider. The audience should be your API’s identifier:

ReactDOM.render(
  <Auth0Provider
    domain={config.domain}
    clientId={config.clientId}
    audience="YOUR_API_IDENTIFIER"
    redirectUri={window.location.origin}
  >
    <App />
  </Auth0Provider>,
  document.getElementById("root")
);

The API identifier is created when you register your API: Register APIs

1 Like

Adding audience worked for me. Thank you again for your all your help!

1 Like

Great! Glad you were able to find your solution!

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