How to obtain id_token with auth0-spa-js

I’ve implemented logins in the past using both the Lock and Auth0 Web sdks successfully. I’m generally working with my own API and using metadata, etc, so I prefer to use id_tokens. However, I am trying out the spa sdk, and it is entirely unclear how to get anything other than authorization code working with the login methods, and the getToken options only return an access_token. How can I get the id_token itself, so I can use it as I please later?

4 Likes

In the new SPA SDK, you can get the ID Token claims via:

this.auth0Client.getIdTokenClaims()

I assume you want the raw, still encoded JWT token though, not just the already decoded claims, is that correct?

unclear how to get anything other than authorization code working

Not sure if you’re referring to the Authorization Code Grant as the available grant type, but just to confirm: the new SPA SDK only uses Authorization Code Grant + PKCE (not Implicit Grant anymore).

Why don’t they expose the id_token through a method in the SDK? I was watching network requests and saw it come back in a request to /oauth/token while using the popup method. The claims are all present, as you can grab them using that getClaims method, so how hard could it be to just let the user get the id_token itself?
59

TBH I don’t know, as I’m not involved in the development of this particular SDK. I think the idea here is to abstract away all complexity incl. decoding, however I understand, having the raw ID token available somewhere might make sense sometimes.
Curious though: what would you want to do with that ID token (other than parsing it for the claims on the client side). What’s your use case? (I could take that back as feedback to the product/SDK team).

In my particular use case, which prompted this, I’m using the id_token to authenticate with Hasura in JWT mode. I also use it in other applications to do my server authentication. I’m open to learning other methods of server-side auth, but JWT is pretty widely accepted as a good practice, no? Shouldn’t this be easy to do?

I cloned the repo, I’ll try to PR, but this is a little disappointing (sorry if that’s dramatic), and it would be nice to get some clarity on why this didn’t come “out of the box.”

@tehpsalmist Specifically in the case of Hasura, despite what their documentation says, you can actually use an access token to authenticate the request, as long as it is a JWT and still contains the custom claims that they require. Their GraphQL platform just cares that it’s a JWT with the claims, it doesn’t actually need to be an ID token.

The access token you need can be recovered from the SDK. To get what you want, you need to create an API within Auth0, specifying the “API Identifier” value (doesn’t have to be a real URL) and then use that value as the audience when you configure the SDK in your app. It’s just a property called audience on the options to the createAuth0Client call.

It’s a “workaround” for your case, I admit, but it will get you moving. In the meantime I will get some clarity on the ID token situation and report back.

1 Like

That is a helpful explanation. And I did notice after a while that access tokens were coming back as JWTs when an audience was specified. I submitted a PR to the library for direct id token access, so maybe that will prove helpful, as well.

Thanks a lot @tehpsalmist for doing that!

Hi all. I’ve added a reply here about why we won’t be taking this forward (for now).

In short, we don’t want to enable an undesirable precendent by exposing the ID token directly from the SDK, until we have a good enough case to do so. Because Hasura don’t specifically require an ID token, we don’t feel that the Hasura case is a strong enough reason to enable this feature in the SDK at the moment. We would however be very interested in other examples where this would be needed.

@tehpsalmist if you need some help migrating from an ID token to an access token for this scenario, please let us know! Hasura also have a webhook authentication mode if that is another option for you, but I have a feeling that using the access token will be easier.

1 Like

Ok, my reaction a little bit ago was a little over the top. Sorry to anyone who had to read that (deleted it since then). What I’m finding is the root concern here is more of a documentation issue. I dug around and found the articles about why not to use idtokens and when to use access tokens, etc. The information is there, but it’s not entirely clear when you’re going through the quick start. I’m going to talk to the Hasura folks about possibly updating their integration guide to reflect the best practices of using access tokens instead of id tokens. This is definitely an education issue that will require some focus, as this is clearly misunderstood among auth0 users and the integrations they use and create. Hopefully I can do my part in resolving the understanding of the community, though I am surely one of the more confused among us. :laughing:

6 Likes

Thanks for your understanding @tehpsalmist. I agree that it is a point of confusion generally amongst users who are trying to understand identity best practises, not just those of Auth0. Education in this area is an ongoing process.

To that end, we’ve made available our entire “Learn Identity” video course to the public, which may help your understanding. In particular, allow me to direct you to a particular section which may help, around ID tokens vs access tokens.

I think Hasura possibly has some responsibility in this area to help educate users too. They’re providing an API so it makes sense that they try and steer people towards API security best practises.

1 Like

After Creating an api (in auth0) and adding “audience”, the custom claims from hasura (Specified in rules are still not showing up in jwt ( i am using getTokenSilently() function). Is there something i am missing, please help?30%20PM

@billi0naire40308 Can you show the rules code, how you add the custom claims.

Just to confirm: you’re adding them to the access token, not the ID token, right? Because the token you’re showing above is the access token, so the custom claims should be added to that.

Something like

context.accessToken['https://namespace/customclaim'] = ...;

right?

Thank you for replying so quickly! I am actually using the auth0 dashboard to create rules (the /rules url) and creating an empty rule, something like this :

Because you mentioned above, I thought you already have setup such rule. I’m not familiar with Hasura, so what do these custom claims look like? How do they appear in the user profile when you check the user under Auth0 Dashboard > User > Raw JSON?

In any case, you would need to add them via Rule as mentioned above in my one-liner example. See the docs here:

(but for the access token, if you want them in the access token, instead of ID token)

After creating an API and adding the API’s identifier value as the audience prop to my Auth0Provider, I got the Hasura claims working by adding the following Auth0 Rule:

function hasuraClaimsRule(user, context, callback) {
  const namespace = "https://hasura.io/jwt/claims";

  context.accessToken[namespace] = {
    "x-hasura-default-role": "user",

    // do some custom logic to decide allowed roles

    "x-hasura-allowed-roles": ["user"],
    "x-hasura-user-id": user.user_id
  };

  callback(null, user, context);
}

This is almost identical to the Auth0 Rule show in Hasura’s Documentation, but with the crucial change from idToken to accessToken.

This will just take a little bit of refactoring to add in custom roles, but it works nicely for giving User-level access.

Jumping in on this because I’m in a similar situation. I’m using lambda to host my graphql api, and I can’t afford the additional cost of a http request to validate an access token on every single request that comes through, so I’m hoping to include the cert in my application and validate the id_token manually on each request.

Am I missing a piece of the flow that will allow me to validate the access token without an extraneous http request?

5 Likes

Agree with others here that having access to the signed JWT would save overhead. I’m also working on a lambda use case where making two calls to validate requests isn’t going to fly. It’s available in auth0-js … why not auth0-spa.js? Is auth0 going to get deprecated?

Burning valuable company time going through documentation on two half-baked front end libs… not a good experience with auth0.

3 Likes

Please show how if you know, but as far as I know there is no way to modify the JWT and pass the verification if you are using a .pem, are verifying the signature and audience.

This is how you can get the raw JWT in the SPA SDK:

const claims = await auth0.getIdTokenClaims();
const id_token = claims.__raw;
2 Likes