When creating a Single Page Application (SPA) with a backend API using [Auth0], there are two types of tokens you will encounter:
- ID tokens - these are used to authenticate a user, and are available on the client
- Access tokens - are used to authorize access to resources, and are appended on the client to backend requests
The problem is, the ID token has details about the current user, but by default the Access token does not. The access token will contain a sub - this is the subject identifies the principal that is the subject of the JWT and does uniquely identify the user, but it is not a usable value. For example, if the user logged in via a Google accont, the sub value will be something like google-oauth2|118034840821107000000
(this is not a real number).
While you could pass the ID token values through on your requests, this is not secure as a threat actor could use a valid access token with spoofed user details.
Auth0 allows you to configure Action Triggers that will allow you to intercept the creation of the token, and append the values you’d like included.
-
In the Auth0 dashboard, go to
Actions
,Triggers
, andpost-login
-
Under
Add Action
, clickCustom
, and thenCreate Action
-
Name your trigger
-
Add any custom claims to the access token. In my example, I am adding the user’s email, full name, first name, and surname.
-
Deploy your trigger by clicking the “Deploy” button
-
Go back to
Actions
,Triggers
and thenpost-login
(as per step 1) -
Drag your custom trigger into the pipeline
-
Click
Apply
On your client application, you will now need to log out and back in, and now, if you inspect the token - it will contain the claims you added.
On the backend (I am using Azure Functions), this is now available to you in code:
var user = req.HttpContext.User;
var email = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
var name = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value;
var surname = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value;
var fullName = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value;