Skip to main content

Protecting backend APIs and website routes

Protecting backend API routes#

Add email verification checks to all API routes#

If you want to protect all your backend API routes with email verification checks, set the mode to REQUIRED in the EmailVerification config. Routes protected with the verifySession middleware will now additionally check for email verification status.

import SuperTokens from 'supertokens-node';
import EmailVerification from "supertokens-node/recipe/emailverification";
import Session from "supertokens-node/recipe/session";

SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailVerification.init({
// This means that verifySession will now only allow calls if the user has verified their email
mode: "REQUIRED",
}),
Session.init()
]
});

In case you have set the email verification mode to REQUIRED but want to disable the check for a specific route, you can make the following changes to the verifySession middleware:

import { verifySession } from "supertokens-node/recipe/session/framework/express";
import express from "express";
import { SessionRequest } from "supertokens-node/framework/express";
import { EmailVerificationClaim } from "supertokens-node/recipe/emailverification";

let app = express();

app.post(
"/update-blog",
verifySession({
overrideGlobalClaimValidators: async (globalValidators) => globalValidators.filter(v => v.id !== EmailVerificationClaim.key),
}),
async (req: SessionRequest, res) => {
// All validator checks have passed and the user has a verified email address
}
);

Add email verification checks to specific API routes#

If you want to protect specific backend API routes with email verification checks, set the mode to OPTIONAL in the EmailVerification config. You will then override the verifySession middleware protecting the route to check for email verification status.

import { verifySession } from "supertokens-node/recipe/session/framework/express";
import express from "express";
import { SessionRequest } from "supertokens-node/framework/express";
import { EmailVerificationClaim } from "supertokens-node/recipe/emailverification";

let app = express();

app.post(
"/update-blog",
verifySession({
overrideGlobalClaimValidators: async (globalValidators) => [...globalValidators, EmailVerificationClaim.validators.isVerified()],
}),
async (req: SessionRequest, res) => {
// All validator checks have passed and the user has a verified email address
}
);

Protecting frontend routes #

Protect all frontend routes #

Set the email verification mode to REQUIRED and wrap your website routes using <SessionAuth />. If the user's email is not verified, SuperTokens will automatically redirect the user to the email verification screen.

Protect specific frontend routes #

Set the email verification mode to OPTIONAL. We will create a generic component called VerifiedRoute which enforces that its child components can only be rendered if the user has a verified email address.

import React from "react";
import { SessionAuth, useSessionContext } from 'supertokens-auth-react/recipe/session';
import { EmailVerificationClaim } from 'supertokens-auth-react/recipe/emailverification';

const VerifiedRoute = (props: React.PropsWithChildren<any>) => {
return (
<SessionAuth>
<InvalidClaimHandler>
{props.children}
</InvalidClaimHandler>
</SessionAuth>
);
}

function InvalidClaimHandler(props: React.PropsWithChildren<any>) {
let sessionContext = useSessionContext();
if (sessionContext.loading) {
return null;
}

if (sessionContext.invalidClaims.some(i => i.validatorId === EmailVerificationClaim.id)) {
// Alternatively you could redirect the user to the email verification screen to trigger the verification email
// Note: /auth/verify-email is the default email verification path
// window.location.assign("/auth/verify-email")
return <div>You cannot access this page because your email address is not verified.</div>
}

// We show the protected route since all claims validators have
// passed implying that the user has verified their email.
return <div>{props.children}</div>;
}

In the VerifiedRoute component, we use the SessionAuth wrapper to ensure that the session exists. The EmailVerificationClaim validator is automatically added to the <SessionAuth> component if the EmailVerification recipe has been initialized.

Finally, we check the result of the validation in the InvalidClaimHandler component which displays "You cannot access this page because your email address is not verified." if the EmailVerificationClaim validator failed. Alternatively you could also redirect the user to the default email verification path to trigger the sending of the verification email.

If all validation passes, we render the props.children component.

note

You can extend the VerifiedRoute 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).

Manually checking verification status

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

import Session from "supertokens-auth-react/recipe/session";
import {EmailVerificationClaim} from "supertokens-auth-react/recipe/emailverification"

function ProtectedComponent() {
let claimValue = Session.useClaimValue(EmailVerificationClaim)
if (claimValue.loading || !claimValue.doesSessionExist) {
return null;
}
let isEmailVerified = claimValue.value;
if (isEmailVerified !== undefined && isEmailVerified) {
//...
} else {
// Redirect the user the email verification path to send the verification email
// Note: /auth/verify-email is the default email verification path
window.location.assign("/auth/verify-email")
}
}