Role-based access control with JWT

Role-based access control allows you to set granular access to your site, or to specific pages. We use JSON Web Tokens (JWT), roles, and redirect rules to grant access to those sections.

# Create users and set roles

When you use an authentication provider that supports JWT, your site visitors log in to your site using the provider service, and the service returns an encrypted JWT with user data.

One JWT provider at a time

You may use Netlify Identity or an external provider for JWT-based authentication, but you cannot use both at the same time.

# Netlify Identity

Netlify Identity is built to provide JWT-based user authentication for your Netlify sites with minimal required setup. Visit the Identity docs for next steps to:

When you’ve completed the setup above, come back to this page to learn how to configure role-based redirects below.

# External providers

This feature may not be available on all plans.

As an alternative to Netlify Identity, you can manage your users with any third party authentication provider that supports JWT tokens with roles metadata, such as Auth0 or Okta. Please note that you cannot authenticate third party JWT tokens if you have Netlify Identity enabled on a site.

To configure an external JWT secret:

  1. Generate a JWT application in your authentication provider of choice, and copy the application’s client secret.
  2. Go to your Netlify site settings under Access control > Visitor access > Password / JWT secret.
  3. Select Set JWT secret, and enter the secret from your authentication provider. We use this secret to verify the access tokens for your site.

Team-wide default secret

You can set a default JWT secret for all sites belonging to your team from your team settings under Sites > Global site settings > Password / JWT secret. JWT settings at the site level will override team-level defaults.

Once you’ve configured your site, go back to your authentication provider and set roles for the users you want to grant access to. For example, you can set specific roles for people in a specific GitHub organization, or with a specific company email.

We use the app_metadata object in the token to read the user roles. The same user can have one or more roles to access different pages in your site. Make sure that the app_metadata has the following format and that the JWT token for your users has a required exp (expiration) field. The value of exp should be a time/date in the future using the Unix Epoch time format.

  "id": "some id",
  "exp": 1602522810,
  "app_metadata": {
    "authorization": {
      "roles": ["admin","editor"]

# Redirect visitors based on roles

Once you have a method for authenticating users with roles assigned in app_metadata, you can start directing them to different areas of your site with role-based redirects. This access control is implemented at our CDN edge, removing the need for a round trip to our origin servers.

Role-based redirect rules work like other redirect rules on Netlify, except that they include a Role parameter which determines which users are redirected according to the rule.

You can set redirect rules in a _redirects file or in a Netlify configuration file. The following examples use syntax for the _redirects file.

# Role-based redirects do not have a “to” property.

/admin/*  200!  Role=admin

The rule above tells Netlify’s CDN to grant access to the /admin path, and everything under it, only to visitors whose JWT tokens include the admin role in their app_metadata. Any other visitor that tries to access those URLs will be presented with a 404 page.

If you don’t want to present a 404 page, you can set a fallback rule to redirect unauthorized users to a specific page, like a login page. The next example adds a new rule to accomplish that:

/admin/*          200!  Role=admin
/admin/*  /login  401!

The second rule in the example is what we call a fallback rule. It tells Netlify’s CDN that it must redirect every visitor that’s not in the admin role to the /login page.

You can also grant several roles access to the same path by chaining them with commas:

/private/*    200!  Role=editor,admin

You can read more about these and other redirect rules in our Redirects documentation.