Tag: ReactJS
Checking Auth0 Roles and Permissions with a React SPA

Checking Auth0 Roles and Permissions with a React SPA

With Auth0 you can set up a completely SAAS-based Authentication and Authorization provider, freeing you of any worries surrounding losing passwords, implementing the latest authentication best practices and a whole heap of other things.

One thing that tripped me up with it, however, was checking what permissions have been assigned to my users.

In my setup, I was using a .NET Core Web API hosted in Azure and a React SPA hosted separately. My API would need to check the permissions assigned to my users in order to check they could perform actions such as updating another user, and my React front end would need to show and hide various pieces of functionality to match.

Checking Permissions in the .NET Core Web API

This article isn't about permissions in APIs but it's important to understand how this differs too what's needed in the React front end.

The tutorial ASP.NET Core Web API v2.1: authoization is relatively straightforward to follow and at the end, you will have an API that performs Authorization with a user's permissions.

Permissions in Auth0 are assigned to users via roles. i.e. A user gets assigned a role and roles have related permissions. This way we can design our application around granular permissions and the roles which give those permissions to a user can be configured separately.

The permissions are provided to the API within the user's authentication token, however for this to work they actually have to be in the token to start with. By default roles and permissions are not included in a token.

These can be included by setting the scope property when calling getAccessTokenSilently (the function to get a token) in React.

1const token = await getAccessTokenSilently({
2 authorizationParams: {
3 audience: 'https://api.example.com/',
4 scope: 'read:posts',
5 },
6});
7const response = await fetch('https://api.example.com/posts', {
8 headers: {
9 Authorization: `Bearer ${token}`,
10 },
11});

Alternatively, you can Enable Role-Based Access Control for APIs. This will increase the size of your token by including all permissions assigned to the person, but removes the need to request them.

Checking Permissions in React

It's likely that before calling an API you will want your React logic to check the users permissions. After all, it wouldn't be a great user experience if they're allowed to perform actions which result in permission errors.

As well as the getAccessTokenSilently the useAuth0 React Hook contains a property for the user and getIdTokenClaims. When using these you will be able to see the details associated with the logged in user. e.g. Name. However unlike getAccessTokenSilently, it doesn't matter what you include in the scope or if you've enabled role-based access control, the properties will not include what permissions or roles are assigned to the user.

To include them you must setup a login action to add them to the token. See Add user roles to ID and Access tokens in Auth0's documentation.

This will direct you to create a login flow where you add a custom action containing the following.

1/**
2 * @param {Event} event - Details about the user and the context in which they are logging in.
3 * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
4 */
5exports.onExecutePostLogin = async (event, api) => {
6 const namespace = 'https://my-app.example.com';
7 if (event.authorization) {
8 api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
9 api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
10 }
11}

Note, the namespace part is so that what you add to the token is unique and doesn't clash with anything Auth0 is adding.

You can now follow these examples to perform a claims checks on the user. E.g.

1import { User } from '@auth0/auth0-react';
2
3function checkClaims(claim?: User, role?: string) {
4 return claim?.['https://my-app.example.com/roles']?.includes(role);
5}
6
7export default checkClaims;

This as you may have spotted is only assigning a role to the token rather than actual permissions. In my case, this was enough, however, this is one area I think the react hook is severely lacking.

Writing custom logic to set a users permissions into the set of claims feels highly wrong, but after some back and forth with Auth0's support team, for now though this appears to be the only option.

JavaScript frameworks explained to an ASP.NET dev

JavaScript frameworks explained to an ASP.NET dev

For most of my career I've been an ASP.NET dev and a JavaScript dev. If I was going to say I was more of an expert in one of them it would be the .NET side of things but I've never really lost touch with JavaScript.

Right now I think it's fair to say technologies in the world are starting to shift how we build websites, with JavaScript frameworks reaching a point with features like static site generation where they actually now offer a decent performance incentive to use them. At some point Blazor may get to a point where it reverses this, but right now there's a compelling argument to move.

For a ASP.NET dev this can be a daunting task. You might be thinking of trying out a headless CMS with a JavaScript front end, but just take a look at this screen grab from Prismic's sdk list.

There's 7 different JavaScript based SDK's listed there! Over half of the total and none of them are that Angular thing you had heard about. Where do you start?

Lets compare to .NET

Well recently I've been updating my JS skills again trying out some of the frameworks I hadn't used before, so I thought I'd share some learnings. The good news is as always it's not really as different as it first seems. To take some of the pain out of understanding what all these frameworks are I thought it would be good to try and relate them back to .NET and what the almost equivalent is.

Assembly Code

No not actual assembler but what does our code actually compile to. In the .NET world we have CIL (Common Intermediate Language), previously known as MSIL (Microsoft Intermediate Language) that our C#, F#, VB etc all compile down to before then being converted to the correct machine code for where they run.

In the front end world think of JavaScript being a bit like this (apart from the fact you actually write JavaScript and we don't write CIL).

View Engine

To render views into HTML, in the ASP.NET world we have Razor, but not just Razor. We also have WebForm, Brail, Bellevue, NDjango (see more here), it just happens that we mostly just use Razor.

I see the equivalents of these being ReactJS, VueJS and Angular. Its not an exact match as they also aren't exact equivalents or each other, but they're largely your functionality that will take a model and turn it into HTML.

Web Application Framework

The problem with the name framework is it applies to basically anything, but this is what I'm going with for describing ASP.NET MVC/ASP.NET Razor Pages/Web Forms, you know all those things built on-top of .NET that make it a website rather than a desktop app. They do things like routing, organising our files into controller and view folders, know how to respond to http requests etc.

Here we have Next.js, Nuxt.js and maybe Gatsby. The link between these and View Engine is a bit stronger than the ASP.NET MVC world as you essentially have a one to one mapping Next.js -> React, Nuxt.js -> Vue but they are what adds routing, static site generation and organization to your code.

Lower Level Framework

Now this one could be wrong :)

In .NET we have different version of the framework. e.g. .NET Framework /3.5/4, .NET Core, .NET 5, Mono. On the front end side they have Node.

Languages

In .NET we have choices including C#, F#, VB among other.

JavaScript has JavaScript (which I know I said was assembly), TypeScript, Coffee Script maybe more.

Not so daunting

There's probably a bunch of flaws with my comparison list and reasons people can point out why things I've said are the same are in fact different, but my point was really to show that while .NET may appear as one button on a SDK list alongside 7 JavaScript based SDK's its not that different. Out of the 7 Node is based on JavaScript. Vue and React are based on Node, and Next/Gatsby/Nuxt are based on Vue/React. There just isn't the same concept of all of it being built by one company or one particular combination being dominant in the same way that ASP.NET MVC + C# + Razor has been for the last generation of .NET websites.