4
votes

I have been trying to upgrade to @auth0/auth0-spa-js from auth0-js, although I could not get my head around reading an email from a token which in turn was obtained from await useAuth0().getTokenSilently()

I use jwt.io to decrypt the token, and this is what I get in the payload:

{
  "iss": "https://TENANT_NAME.auth0.com/",
  "sub": "auth0|SOME_HASH",
  "aud": [
    "https://API_IDENTIFIER",
    "https://TENANT_NAME.auth0.com/userinfo"
  ],
  "iat": 1563699940,
  "exp": 1563786340,
  "azp": "SOME_OTHER_HASH",
  "scope": "openid profile email"
}

When I was using auth0-js I could just add scope: "openid email" to new auth0.WebAuth({...}) and voilà – I had email and email_verified in the payload of the decrypted token.

I believe the 2 part series of tutorials were not able to answer my question, and retrieving the token from a hooked getTokenSilently() inside my Apollo configuration was also a challenge on its own. I like the redirect implementation for SPA, however. Please, can you suggest a proper way to include email and email_verified in the token's payload?

UPDATE

By reading this piece of documentation on api-tokens I understood the token I am getting from getTokenSilently() is called the access token. I have been using ID tokens in all of my requests' headers till this day, and that was probably a bad approach:

In the OIDC-conformant pipeline, ID Tokens should never be used as API tokens.

Also, the documentation says:

The token does not contain any information about the user except for the user ID (located in the sub claim).

In many cases, you may find it useful to retrieve additional user information. You can do this by calling the /userinfo API endpoint with the Access Token.

Which I did by following the shell example. I have sent the request with my access token and magically got an object containing the user's profile information from Auth0's Custom API.

We got close, what is an algorithm converting the "sub" into user profile residing inside Auth0's Custom API which I can implement for my backend written in ruby?

1

1 Answers

0
votes

Yes, as you mention, ID tokens should not be used as API Tokens. They have a different usage (and you don't want your API Token to be too big, because you send it in each request's headers).

To get the user email, you can just fetch the UserProfile given in the ID Token. To achieve that, you just have to call getUser instead of getTokenSilently.

If you want more infos about the user, you have 2 ways to fetch user info:

  1. You use the Auth0 Management API to fetch the user infos, based on the user id (in the sub claim of the ID Token) and using this API endpoint. In Ruby, you can just use a basic HTTP request.

  2. You use a rule to always include specific fields in the ID Token. For example, you can include user_metadata and app_metadata in your ID Tokens. That way, you can use it without additional API call. To achieve that, you will need a specific Rule that will run when ID Tokens are generated (more general API doc).

An example rule that would add all user_metadata and app_metadata to the ID token would be:

function (user, context, callback) {
  const namespace = 'your_url_namespace_just_for_cosmetic_but_required/';
  context.idToken[namespace + 'user_metadata'] = user.user_metadata;
  context.idToken[namespace + 'app_metadata'] = user.app_metadata;
  callback(null, user, context);
}

And you will have the info in your ID Token for your frontend to use.

For the record, more rules examples on this hard-to-find page.