As part of my continuing dig into Auth0 I wanted to see how I could access user information for a user represented by a JWT Access Token issued by Auth0. For the uninitiated, Auth0 login will yield, to front end applications, 2 tokens: id_token and access_token.
The id_token is provided from Auth0 to represent the user who logged into the registered application. The access token is provided as a means to make calls to supported audiences. We talked a little about this in the previous post (Authorization with Auth0 in .NET Core 3.1). Thus, following login, we would keep the id_token stored as a way to identify our user to the application and the access_token to enable access to allowed APIs.
However, if you run each of these tokens through jwt.io you will see a large difference. Notably, the access_token contains NO user information, with the exception of the user_id as the subject (sub). The reason for this is to keep the payload small and to reduce the attack surface. The truth is, there is often no reason for the API being called to know anything about the user outside of permissions and the User_Id – passing around name, email, and other information is most often going to be superfluous and thus needs to be avoided.
The question is though, if we do need the user’s information, how can we get it? That is what I want to explore in this entry.
How should we view Auth0?
First and foremost, I want to point out that Auth0 is more than just a way to validate and generate tokens. Honestly, it should almost be viewed as a UserService as a Service. It replaces the service that would traditionally handle user related responsibilities. It even has the capability to integrate with existing accounts and data store mechanisms. As I have continued to use it, I have found that using it for login and user management is a speed boost to development and alleviates my teams from having to build the necessary UI that goes with such a system.
How do we get the UserId from our Token in .NET Core?
Honestly, I was disappointed here – I would have hoped .NET Core was smart enough to map certain well known claims to ClaimsIdentity properties so you could easily user the this.User property that exists on ControllerBase. Maybe I missed something but, given the popularity of JWT and token style logins, I would this this would be more readily available. This is how I ended up pulling out the UserId:
((ClaimsIdentity)User.Identity).Claims.First(x => x.Type.EndsWith(“nameidentifier”)).Value;
Getting the User Information
Auth0 offers a standard API to all users known as the Management API. This is registered to your account with its own ClientId and Secret. When an access_token is provided we can use it, with a tenant level endpoint, to get an access_token to the Management API. Using this we can information about users, the tenant, just about anything.
First, you need to contact your tenant level OAuth endpoint and acquire an access_token that can be used to access the Management API. This call is relatively simple and is shown below – I am using the standard HttpClient class from System.Net.Http.
The client_id and client_secret are from the M2M application created for your API (under Applications) – hint, if you do not see this, access the API in question (WeatherApi for me) and select the API Explorer, this will auto create the M2M application with the client secret and id that are needed for this exercise.
The end result of this call is a JSON payload that contains, among other things, an access_token – it is this token we can use to access the Management API.
The best way to access the Management API with .NET is to use the supplied NuGet packages from Auth0:
The rest is very easy, we simply new up an instance of ManagementApiClient and call the appropriate method. Here is the complete code sample:
Really pretty straightforward – again my only complaint was getting the UserId (sub) out of the claims in .NET, I would expect it to be easier.
Centrally, I am starting to see Auth0 more as a service for user management than a simple vendor. If you think about it, having user data in a separate service does make things more secure since if you DB is breached the passwords are safe as they are physically not there. Further, you can take advantage, to a point, of the scale offered by Auth0 and the ability for it to integrate with services like Salesforce, Azure AD, Facebook, and other user info sources.
I am personally looking forward to using Auth0 extensively for my next project.