Skip to main content
Which UI do you use?
Custom UI
Pre built UI

Protecting API and frontend routes

caution

This guide applies to scenarios which involve SuperTokens Session Access Tokens.

If you are implementing Unified Login, that uses OAuth2 Access Tokens, please check our separate page that shows you how to validate them. You will have to check for the roles claim in the token payload.

Protecting API routes#

In your API routes you:

  1. Verify that a session exists
  2. Validate that the roles/permissions saved in the access token payload have the appropriate value
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import express from "express";
import { SessionRequest } from "supertokens-node/framework/express";
import UserRoles from "supertokens-node/recipe/userroles";

let app = express();

app.post(
"/update-blog",
verifySession({
overrideGlobalClaimValidators: async (globalValidators) => [
...globalValidators,
UserRoles.UserRoleClaim.validators.includes("admin"),
// UserRoles.PermissionClaim.validators.includes("edit")
],
}),
async (req: SessionRequest, res) => {
// All validator checks have passed and the user is an admin.
}
);
  • We add the UserRoleClaim validator to the verifySession function which makes sure that the user has an admin role.
  • The globalValidators represents other validators that apply to all API routes by default. This may include a validator that enforces that the user's email is verified (if enabled by you).
  • We can also add a PermissionClaim validator to enforce a permission.

If you want to have more complex access control, you can either create your own validator, or you can get the roles list from the session as follows, and check the list yourself:

import express from "express";
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import { SessionRequest } from "supertokens-node/framework/express";
import UserRoles from "supertokens-node/recipe/userroles";
import { Error as STError } from "supertokens-node/recipe/session"

let app = express();

app.post("/update-blog", verifySession(), async (req: SessionRequest, res) => {
const roles = await req.session!.getClaimValue(UserRoles.UserRoleClaim);

if (roles === undefined || !roles.includes("admin")) {
// this error tells SuperTokens to return a 403 to the frontend.
throw new STError({
type: "INVALID_CLAIMS",
message: "User is not an admin",
payload: [{
id: UserRoles.UserRoleClaim.key
}]
})
}
// user is an admin..
});

Protecting frontend routes#

On your frontend:

  1. Verify that a session exists
  2. Use the roles / permissions claim validators to enforce certain roles and permissions.
  3. If the user doesn't have the right roles, we show them an error message indicating they don't have access.
import React from "react";
import { SessionAuth } from 'supertokens-auth-react/recipe/session';
import { AccessDeniedScreen } from 'supertokens-auth-react/recipe/session/prebuiltui';
import { UserRoleClaim, /*PermissionClaim*/ } from 'supertokens-auth-react/recipe/userroles';

const AdminRoute = (props: React.PropsWithChildren<any>) => {
return (
<SessionAuth
accessDeniedScreen={AccessDeniedScreen}
overrideGlobalClaimValidators={(globalValidators) => [
...globalValidators, UserRoleClaim.validators.includes("admin"),
]
}>
{props.children}
</SessionAuth>
);
}

Above we are creating a generic component called AdminRoute which enforces that its child components can only be rendered if the user has the admin role.

In the AdminRoute component, we use the SessionAuth wrapper to ensure that the session exists. We also add the UserRoleClaim validator to the <SessionAuth> component which checks if the validators pass or not. If all validation passes, we render the props.children component. If the claim validation has failed, it will display the AccessDeniedScreen component instead of rendering the children. You can also pass your own custom component to the accessDeniedScreen prop.

note

You can extend the AdminRoute component to check for other types of validators as well. This component can then be reused to protect all of your app's components (In this case, you may want to rename this component to something more appropriate, like ProtectedRoute).

If you want to have more complex access control, you can get the roles list from the session as follows, and check the list yourself:

import Session from "supertokens-auth-react/recipe/session";
import {UserRoleClaim} from "supertokens-auth-react/recipe/userroles"

function ProtectedComponent() {
let claimValue = Session.useClaimValue(UserRoleClaim)
if (claimValue.loading || !claimValue.doesSessionExist) {
return null;
}
let roles = claimValue.value;
if (Array.isArray(roles) && roles.includes("admin")) {
// User is an admin
} else {
// User doesn't have any roles, or is not an admin..
}
}
Looking for older versions of the documentation?
Which UI do you use?
Custom UI
Pre built UI