Add custom claim to access token not working

Hi-
I have a react SPA and a flask backend that I’m trying to use with auth0 together. I can authenticate just fine, but I’m having big troubles with authorization… Because of a concurrently-running legacy application using the same databases, I can’t change anything in the db to encompass authorization (like I suspect I’m supposed to to, to use RBAC or something). If I were to just send the access token and use that to get the userinfo, I’d have to do that on every single request from every single user, which doesn’t seem right.

So, what I think should work is either: append a custom claim to my access_token with the user’s email, or send the id_token as well to my backend on every request, and be able to extract the user’s email from there.

I have tried both rules and hooks (and am still not super clear about the difference between them, and what would or wouldn’t run when my application requests tokens?) but neither have seemed to actually affect the access token I’m getting back, though both work in the “try it out” feature of the panel where you set them up… And the client exchange hook doesn’t have an obvious way to access the user object anyway, that I can tell.

The contents of my rule are:
function (user, context, callback) {
const namespace = ‘boxtribute.com/’;
context.accessToken[namespace + ‘email’] = user.email;
callback(null, user, context);
}

I also thought about just sending the id_token as well, but even if I add my client-id to the audience, I can’t decode it with jose.jwt, because
No access_token provided to compare against at_hash claim

Is my best option here REALLY to just send the email address in a separate header field and give up on it being part of any kind of token the backend can consume?

Hi Katie,

Welcome to the Auth0 community!

Namespaces need to start with either http:// or https:// as described in our documentation here: Create Custom Claims

The contents of your Rule look good to me.

Could you try modifying your namespace and seeing if it solves the issue?

1 Like

it worked!!! Thanks so much. While I have you here though, could you clarify the difference between rules and hooks, and when I should be using each? I looked into some other forum questions and it sounded like rules SHOULDN’T run when the client authenticates, but it seems to in this case. Also, why does the client-exchange hook not have access to the user object? Am I just not understanding the point at which that happens?
thanks again!

As naming convention shows per-registration and post registration, hooks only execute once when new user gets register with Auth0 system
Rules execute every time user login to the system.

So which is best to use depends upon the specific requirement.

If starting with http:// or https:// is actually required, I recommend updating the documentation, which does not say that. Currently the page you linked to says:

  • “Namespaces are arbitrary identifiers, so technically you can call your namespace anything you want.”
  • “using the URI of a resource you control is conventional” (emphasis added)

The page recommends using a URI that you control in order to avoid clashes, but nowhere on that page does it say that using a URI is required. Confusingly, when I’ve tried out custom rules with non-URI namespaces, their data is included when testing in the dashboard, but it’s not included in the data sent to the client.

Further down the article, it does address the scheme:

Use the following guidelines:

  • Use any non-Auth0 HTTP or HTTPS URL as a namespace identifier. Auth0 domains, which cannot be used as namespace identifiers include:
  • Although ideally you will use a URI that you control, the namespace URI does not have to point to an actual resource. It is only used as an identifier; it will not be called.
  • You can use any number of namespaces.

Namespaces are arbitrary identifiers, so technically you can call your namespace anything you want[1]. However, using the URI of a resource you control is conventional[2], following the way XML namespaces are defined.[3]

[1] This refers to how you name your namespace identifier, not how it’s structured. For example, your namespace could be a non-resolving URI (http://my-api) or a URL (http://myapp.com/my-api).
[2] I added the emphasis to clarify semantics.
[3] XML namespaces are identified by a URI reference. By definition, URIs begin with a scheme.


Confusingly, when I’ve tried out custom rules with non-URI namespaces, their data is included when testing in the dashboard, but it’s not included in the data sent to the client.

Namespacing custom claims applies to ID Tokens (in compliance with OIDC guidance). IIRC, if you’re testing within the Dashboard (i.e. the “Try This Rule” button), you’re not issuing an ID Token, so namespacing is not enforced.


I hope this helps clarify things.

Thanks for the reply! I still don’t think the documentation is clear on this. I don’t have a problem with the way these restrictions work, I just want the documentation to be clear and accurate.

  • This sentence is introduced by the words “Use the following guidelines:”. I parse this in context as “guidelines to help benefit from our suggestion of using a URI you own in order to avoid collisions”. More to the point, “Guidelines” is not equivalent to “Requirements” so it’s not clear that these “guidelines” must be followed.
  • My interpretation of this guideline as optional is supported by the earlier section which says “you can call your namespace anything you want”. This “anything” quote refers to “your namespace”, not “your XML namespace”, so it’s not even implied that there’s an enforced limitation on the namespace format with how that sentence is worded.
  • In the doc, the term “namespace” is used several times before it is compared to “XML namespaces” (which only happens once). The concept of a namespace can mean many different things outside of XML, including simply nesting all data under a single unique key. Also note that we’re modifying JSON objects, not XML documents, so it’s not obvious or intuitive that XML rules apply unless that’s stated explicitly.
  • There are schemes other than http: and https:, but it seems that no other schemes work with the Auth0 API. If I use a different scheme, the data will not be included (I tried ftp:, git: and the made up foo:). This tells me that the actual rule is not “Must be a URI”, but rather "Must start with the string "http:" or "https:". Accuracy matters in technical documents and it would actually be more direct and take less space to simply define this explicit rule (start with http[s]) and then provide details on why the recommended method of following the rule is by using a URI you control in order to avoid collisions.
  • That explanation makes sense, thanks. I’d love to see a toggle there to enable enforcement of the namespacing rules when using the “Try This Rule” button as if an ID token were being generated (bonus points for showing a message if your data was removed due to a namespace rule). Treating the inserted data differently in the dashboard makes these types of issues harder to debug. If there’s a better place to submit a feature request for that, let me know.

I urge you to get the Custom Claims documentation updated to explicitly name the two possible strings that a namespace must start with. These are Auth0’s own rules (not XML namespace rules, even if that was the inspiration), so your documentation needs to explicitly define the rules it’s using.

I agree that the documentation could be clearer.

Would you mind submitting your feedback here?

2 Likes

I am also in the same boat. I have tried everything but can’t get simple thing in the access token.
(I am using React SPA)
My Rule looks like:

function addEmailToAccessToken(user, context, callback) {
  // This rule adds the authenticated user's email address to the access token.

  var namespace = 'https://dev-xxx.us.auth0.com/';
	console.log("I am here", "at: ", context.accessToken, "it: ", context.idToken);
  if (context.accessToken) {
  	context.accessToken[namespace + 'email'] = user.email;
}
  
 	if (context.idToken) {
  	context.idToken[namespace + 'email'] = user.email;
}
  return callback(null, user, context);
}

I can see the rule is fired only when when user logs in (not every time when I call getAccessTokenSilently)
But also when it gets called, the context.accessToken and context.idToken are empty.

 I am here at: {} it: {}

I have also tried using pre made template and even tried Action/Flows Can’t seem to get custom claims/attributes in access token.

Can anyone from Auth0 please help?

Got it working. Issue was To be precise, auth0 should not be there in the namespace.
Renaming ‘https://dev-xxx.us.auth0.com/’ → ‘https://somedomain/’ works

1 Like

Perfect! Thanks for sharing that with the rest of community!