---
title: Implement common domain login
description: Authenticate users across different tenants through a common domain.
sidebar:
  order: 40
---

## Overview

This guide shows you how to authenticate users through the same page, `https://example.com/auth`, and then redirect them to their subdomain after sign-in.
The login page adjusts the authentication method based on the tenant's configuration.

You can determine the tenant in several ways.
A common approach is to ask the user for their organization name and use it as the `tenantId` configured in SuperTokens.

:::info[Important]
You can find an example app for this setup with the **pre-built UI** on [the GitHub example directory](https://github.com/supertokens/supertokens-auth-react/tree/master/examples/with-one-login-many-subdomains). The app is setup to have three tenants:
- `tenant1`: Login with `emailpassword` + Google sign in
- `tenant2`: Login with `emailpassword`
- `tenant3`: Login with passwordless + GitHub sign in

You can also generate a demo app using the following command:

```bash
npx create-supertokens-app@latest --recipe=multitenancy

```
:::


## Before you start

<PaidFeatureCallout />

The tutorial assumes that you already have a working application integrated with **SuperTokens**.
If you have not, please check the [Quickstart Guide](/quickstart).

You also need to create the tenants that your application requires.
View the [previous tutorial](/authentication/enterprise/initial-setup) for more information on how to do this.


## Steps

### 1. Ask for the tenant ID on the login page

<UITypeSwitch />

<VariantContent storageKey="ui-type" value="prebuilt">


If you have [followed the pre-built UI setup](/quickstart#1-integrate-the-frontend-sdk), when you visit the login screen, you see the login screen immediately.
The flow needs to change to first ask the user to enter their tenant ID and then display the login UI based on the tenant ID.

To do that, first obtain the tenant ID from the user.
You can achieve this by building a UI that asks them to enter their tenant ID or organization name (which can serve as the tenant ID).
This example implements the UI in a component called `AuthPage`.

:::warning
You have to [create tenants](/authentication/enterprise/initial-setup) before you can complete this step.
:::

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
:::info[Caution]
No code snippet provided here, however, if you visit the auth component, you see that the pre-built UI renders in the `"supertokensui"` `div` element on page load. The logic here needs to change to first check if the user has provided the `tenantId`. If they have, the SuperTokens UI renders as usual. If they have not, a simple UI renders which asks the user for their tenant id and saves that in `localstorage`.

Switch to the React code tab here to see the implementation in React, and a similar logic applies here.
:::
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
<DependentContent group="react-router" label="Do you use react-router-dom?">
<ContentOption title="With React Router" value="yes">
```tsx
import { useState } from "react";
import * as reactRouterDom from "react-router-dom";
import { Routes } from "react-router-dom";
import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { useSessionContext } from "supertokens-auth-react/recipe/session";

export const AuthPage = () => {
  const location = reactRouterDom.useLocation();
  const [inputTenantId, setInputTenantId] = useState("");
  const tenantId = localStorage.getItem("tenantId") ?? undefined;
  const session = useSessionContext();

  if (session.loading) {
    return null;
  }

  if (
    tenantId !== undefined || // if we have a tenantId stored
    session.doesSessionExist === true || // or an active session (it'll contain the tenantId)
    new URLSearchParams(location.search).has("tenantId") // or we are on a link (e.g.: email verification) that contains the tenantId
  ) {
    // Since this component (AuthPage) is rendered in the /auth route in the main Routes component,
    // and we are rendering this in a sub route as shown below, the third arg to getSuperTokensRoutesForReactRouterDom
    // tells SuperTokens to create Routes without /auth prefix to them, otherwise they would
    // render on /auth path.
    return <Routes>{getSuperTokensRoutesForReactRouterDom(reactRouterDom, [EmailPasswordPreBuiltUI], "/auth")}</Routes>;
  } else {
    return (
      <form
        onSubmit={() => {
          // this value will be read by SuperTokens as shown in the next steps.
          localStorage.setItem("tenantId", inputTenantId);
        }}
      >
        <h2>Enter your organization's name:</h2>
        <input type="text" value={inputTenantId} onChange={(e) => setInputTenantId(e.target.value)} />
        <br />
        <button type="submit">Next</button>
      </form>
    );
  }
};
```
</ContentOption>
<ContentOption title="Without React Router" value="no">
```tsx
import { useState } from "react";
import { getRoutingComponent } from "supertokens-auth-react/ui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { useSessionContext } from "supertokens-auth-react/recipe/session";

export const AuthPage = () => {
  const [inputTenantId, setInputTenantId] = useState("");
  const tenantId = localStorage.getItem("tenantId") ?? undefined;
  const session = useSessionContext();

  if (session.loading) {
    return null;
  }

  if (
    tenantId !== undefined || // if we have a tenantId stored
    session.doesSessionExist === true || // or an active session (it'll contain the tenantId)
    new URLSearchParams(location.search).has("tenantId") // or we are on a link (e.g.: email verification) that contains the tenantId
  ) {
    return getRoutingComponent([EmailPasswordPreBuiltUI]);
  } else {
    return (
      <form
        onSubmit={() => {
          // this value will be read by SuperTokens as shown in the next steps.
          localStorage.setItem("tenantId", inputTenantId);
        }}
      >
        <h2>Enter your organization's name:</h2>
        <input type="text" value={inputTenantId} onChange={(e) => setInputTenantId(e.target.value)} />
        <br />
        <button type="submit">Next</button>
      </form>
    );
  }
};
```
</ContentOption>
</DependentContent>
</Tab>
<Tab title="Angular" value="angular">

</Tab>
</CodeGroup>

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Reactjs" value="reactjs">
The example creates a simple UI that asks the user for their organization's name.
Their input serves as their tenant ID.
When the user submits that form, the value is stored in local storage.

:::info[Important]
The `AuthPage` component should render to show on `/auth/*` paths of the website.

The `AuthPage` replaces the call to `getSuperTokensRoutesForReactRouterDom` or `getRoutingComponent` that you may have added to your app from the quick setup section.
:::
</ContentOption>
</DependentContent>

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">


You need to build a UI that asks the user to enter their tenant ID or organization name (which can serve as the tenant ID). The input value is then used in function calls, as shown below.

Once you have the user's tenant ID, you can fetch their list of configured providers and render the third party login buttons accordingly:


<CodeGroup group="frontend-custom-ui">
<Tab title="Web" value="web">
<DependentContent group="install-method" label="Installation method">
<ContentOption title="npm" value="npm">
```tsx
import Multitenancy from "supertokens-web-js/recipe/multitenancy";

async function fetchThirdPartyLoginProvidersForTenant(tenantId: string) {
  const loginMethods = await Multitenancy.getLoginMethods({
    tenantId,
  });

  if (loginMethods.firstFactors.includes("thirdparty")) {
    const providers = loginMethods.thirdParty.providers;
    if (providers.find((i) => i.id === "active-directory")) {
      // render sign in with Active Directory button
    } else {
      // more checks for other providers
    }
  } else {
    // thirdparty login is disabled for the tenant
  }
}
```
</ContentOption>
<ContentOption title="Script tag" value="script-tag">
```tsx
import Multitenancy from "supertokens-web-js/recipe/multitenancy";
async function fetchThirdPartyLoginProvidersForTenant(tenantId: string) {
  const loginMethods = await Multitenancy.getLoginMethods({
    tenantId,
  });

  if (loginMethods.firstFactors.includes("thirdparty")) {
    const providers = loginMethods.thirdParty.providers;
    if (providers.find((i) => i.id === "active-directory")) {
      // render sign in with Active Directory button
    } else {
      // more checks for other providers
    }
  } else {
    // thirdparty login is disabled for the tenant
  }
}
```
</ContentOption>
</DependentContent>
</Tab>
<Tab title="Mobile" value="mobile">
```bash
curl --location --request GET '<YOUR_API_DOMAIN>/auth/loginmethods'
```
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Web" value="web">
- The code snippet fetches the login methods for the tenant ID.
- It then renders the login UI buttons based on the configured `thirdPartyId` values in the response.
</ContentOption>
<ContentOption title="Mobile" value="mobile">
The response body from the API call has a `status` property in it:

- `status: "OK"`: The `recipes` field contains information about which login methods are active along with the list of third party providers configured for this tenant.
- `status: "GENERAL_ERROR"`: This is only possible if you have overridden the backend API to send back a custom error message which should appear on the frontend.
</ContentOption>
</DependentContent>



</VariantContent>


### 2. Include the tenant ID in authentication flow

You need to tell SuperTokens how to resolve the tenant ID.
To do this, set the `getTenantId` function in the `Multitenancy` recipe.
In the current example, local storage provides the `tenantId`.


<VariantContent storageKey="ui-type" value="prebuilt">


<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
```tsx
import React from "react";

import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
import Multitenancy from "supertokens-auth-react/recipe/multitenancy";

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
    apiBasePath: "...",
    websiteBasePath: "...",
  },
  usesDynamicLoginMethods: true,
  recipeList: [
    Multitenancy.init({
      override: {
        functions: (oI) => {
          return {
            ...oI,
            getTenantId: (input) => {
              let tid = localStorage.getItem("tenantId");
              return tid === null ? undefined : tid;
            },
          };
        },
      },
    }),
    // other recipes...
  ],
});
```
</Tab>
<Tab title="Angular" value="angular">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)

supertokensUIInit({
  appInfo: {
    appName: "...",
    apiDomain: "...",
    websiteDomain: "...",
    apiBasePath: "...",
    websiteBasePath: "...",
  },
  usesDynamicLoginMethods: true,
  recipeList: [
    supertokensUIMultitenancy.init({
      override: {
        functions: (oI) => {
          return {
            ...oI,
            getTenantId: (input) => {
              let tid = localStorage.getItem("tenantId");
              return tid === null ? undefined : tid;
            },
          };
        },
      },
    }),
    // other recipes...
  ],
});
```
</Tab>
</CodeGroup>

:::info[Important]
Set the `usesDynamicLoginMethods` to `true` to tell SuperTokens that the login methods are dynamic (based on the `tenantId`). On page load (of the login page), SuperTokens first fetches the configured login methods for the `tenantId`. It then displays the login UI based on the result of the API call.
:::

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">



<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Web" value="web">
Initialize the multitenancy recipe with the following callback. You can get the tenant ID from wherever you stored it after asking the user for it.
</ContentOption>
<ContentOption title="Mobile" value="mobile">
All the steps for mobile app login are similar to the [social login steps](/authentication/social/initial-setup#2-add-the-login-ui). However, when you are calling the sign in up API, you also need to pass in the `tenantId` in the request path. An example of this appears below:
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-custom-ui">
<Tab title="Web" value="web">
<DependentContent group="install-method" label="Installation method">
<ContentOption title="npm" value="npm">
```tsx
import SuperTokens from "supertokens-web-js";
import Multitenancy from "supertokens-web-js/recipe/multitenancy";

SuperTokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    Multitenancy.init({
      override: {
        functions: (oI) => {
          return {
            ...oI,
            getTenantId: (input) => {
              let tid = localStorage.getItem("tenantId");
              return tid === null ? undefined : tid;
            },
          };
        },
      },
    }),
    // other recipes...
  ],
});
```
</ContentOption>
<ContentOption title="Script tag" value="script-tag">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
supertokens.init({
  appInfo: {
    appName: "...",
    apiDomain: "...",
  },
  recipeList: [
    supertokensMultitenancy.init({
      override: {
        functions: (oI) => {
          return {
            ...oI,
            getTenantId: (input) => {
              let tid = localStorage.getItem("tenantId");
              return tid === null ? undefined : tid;
            },
          };
        },
      },
    }),
    // other recipes...
  ],
});
```
</ContentOption>
</DependentContent>
</Tab>
<Tab title="Mobile" value="mobile">
```bash
curl --location --request POST '<YOUR_API_DOMAIN>/auth/signinup' \
--header 'Content-Type: application/json' \
--data-raw '{
    "thirdPartyId": "...",
    "clientType": "...",
    "oAuthTokens": {
        "access_token": "...",
        "id_token": "..."
    },
}'
```
</Tab>
</CodeGroup>



</VariantContent>


### 3. Redirect users based on tenant subdomain (optional)

If each tenant has access to specific subdomains in your application, redirect users after sign-in.

#### 3.1 Restrict subdomain access

Before redirecting users, restrict which subdomains their sessions can be used on.
To do this configure the SDK to know which domain each `tenantId` has access to.

<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
import SuperTokens from "supertokens-node";
import Multitenancy from "supertokens-node/recipe/multitenancy";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Multitenancy.init({
      getAllowedDomainsForTenantId: async (tenantId, userContext) => {
        // query your db to get the allowed domain for the input tenantId
        // or you can make the tenantId equal to the subdomain itself
        return [tenantId + ".myapp.com", "myapp.com", "www.myapp.com"];
      },
    }),
    // other recipes...
  ],
});
```
</Tab>
<Tab title="Go" value="go">
```go
import (
	"github.com/supertokens/supertokens-golang/recipe/multitenancy"
	"github.com/supertokens/supertokens-golang/recipe/multitenancy/multitenancymodels"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	supertokens.Init(supertokens.TypeInput{
		RecipeList: []supertokens.Recipe{
			multitenancy.Init(&multitenancymodels.TypeInput{
				GetAllowedDomainsForTenantId: func(tenantId string, userContext supertokens.UserContext) ([]string, error) {
					// query your db to get the allowed domain for the input tenantId
					// or you can make the tenantId equal to the subdomain itself
					return []string{tenantId + ".myapp.com", "myapp.com", "www.myapp.com"}, nil
				},
			}),
		},
	})
}
```
</Tab>
<Tab title="Python" value="python">
```python
from supertokens_python import init, InputAppInfo, SupertokensConfig
from supertokens_python.recipe import multitenancy
from typing import Dict, Any, List

async def get_allowed_domains_for_tenant_id(tenant_id: str, user_context: Dict[str, Any]) -> List[str]:
    return [tenant_id + ".myapp.com", "myapp.com", "www.myapp.com"]

init(
    app_info=InputAppInfo(
        app_name="...",
        api_domain="...",
        website_domain="...",
    ),
    supertokens_config=SupertokensConfig(
        connection_uri="...",
    ),
    framework="django", # Change this to "flask" or "fastapi" if you are using Flask or FastAPI
    recipe_list=[
        multitenancy.init(
            get_allowed_domains_for_tenant_id=get_allowed_domains_for_tenant_id
        )
    ],
)
```
</Tab>
</CodeGroup>

The code sample tells SuperTokens to add the returned domains to the user's session claims when they sign in.
The claim is available on the frontend and backend and can restrict where the session is used.

:::warning[Domain checks are not tenant authorization]
`AllowedDomainsClaim` and `hasAccessToCurrentDomain` restrict session use by hostname. They do not prove that the user
belongs to an organization, enforce CORS or allowed browser origins, authorize access to business data, or provide
complete tenant isolation. After authentication, verify the user's tenant membership. On every business-data access,
the backend must derive the tenant from trusted session data and enforce application-level tenant authorization. Do
not trust a tenant ID, hostname, or claim supplied by the browser as authorization.
:::

#### 3.2 Redirect the user to their subdomain after sign-in

<VariantContent storageKey="ui-type" value="prebuilt">

After sign-in, the frontend SDK redirects the user to the `/` route by default.
You can instead redirect them to their subdomain based on their tenant ID.

<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
```tsx
import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";
import Multitenancy from "supertokens-auth-react/recipe/multitenancy";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  getRedirectionURL: async (context) => {
    if (context.action === "SUCCESS" && context.newSessionCreated) {
      let claimValue: string[] | undefined = await Session.getClaimValue({
        claim: Multitenancy.AllowedDomainsClaim,
      });
      if (claimValue !== undefined) {
        window.location.href = "https://" + claimValue[0];
      } else {
        // there was no configured allowed domain for this user. Throw an error cause of
        // misconfig or redirect to a default subdomain
      }
    }
    return undefined;
  },
  recipeList: [
    /* Recipe init here... */
  ],
});
```
</Tab>
<Tab title="Angular" value="angular">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)

supertokensUIInit({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  getRedirectionURL: async (context) => {
    if (context.action === "SUCCESS" && context.newSessionCreated) {
      let claimValue: string[] | undefined = await supertokensUISession.getClaimValue({
        claim: supertokensUIMultitenancy.AllowedDomainsClaim,
      });
      if (claimValue !== undefined) {
        window.location.href = "https://" + claimValue[0];
      } else {
        // there was no configured allowed domain for this user. Throw an error cause of
        // misconfig or redirect to a default subdomain
      }
    }
    return undefined;
  },
  recipeList: [
    /* Recipe init here... */
  ],
});
```
</Tab>
</CodeGroup>

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">

On the frontend, after the user signs in, you can read the domain from their session and redirect them accordingly.

<CodeGroup group="install-method">
<Tab title="npm" value="npm">
```tsx
import Session from "supertokens-web-js/recipe/session";
import Multitenancy from "supertokens-web-js/recipe/multitenancy";

async function redirectToSubDomain() {
  if (await Session.doesSessionExist()) {
    let claimValue: string[] | undefined = await Session.getClaimValue({
      claim: Multitenancy.AllowedDomainsClaim,
    });
    if (claimValue !== undefined) {
      window.location.href = "https://" + claimValue[0];
    } else {
      // there was no configured allowed domain for this user. Throw an error cause of
      // misconfig or redirect to a default subdomain
    }
  } else {
    window.location.href = "/auth";
  }
}
```
</Tab>
<Tab title="Script tag" value="script-tag">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
async function redirectToSubDomain() {
  if (await supertokensSession.doesSessionExist()) {
    let claimValue: string[] | undefined = await supertokensSession.getClaimValue({
      claim: supertokensMultitenancy.AllowedDomainsClaim,
    });
    if (claimValue !== undefined) {
      window.location.href = "https://" + claimValue[0];
    } else {
      // there was no configured allowed domain for this user. Throw an error cause of
      // misconfig or redirect to a default subdomain
    }
  } else {
    window.location.href = "/auth";
  }
}
```
</Tab>
</CodeGroup>

</VariantContent>


- The `AllowedDomainsClaim` claim is auto added to the session by the backend SDK if you provide the `GetAllowedDomainsForTenantId` configuration from the previous step.
- This claim contains the domains configured for the session's tenant ID. It is not proof of user membership or authorization to business data.

### 6. Share sessions across subdomains (optional)

If the user authenticates on your main website domain (`https://example.com/auth`) and is redirected to a subdomain, update the Session recipe to share sessions across subdomains.
You can do this [by setting the `sessionTokenFrontendDomain` value in the Session recipe](/post-authentication/session-management/share-session-across-sub-domains).

If the subdomains assigned to your tenants have their own backends on separate subdomains (one per tenant), you can also enable [sharing of sessions across API domains](/post-authentication/session-management/advanced-workflows/multiple-api-endpoints).

### 7. Limit session use to the tenant's subdomain (optional)

The frontend uses session claim validators to restrict session use by subdomain.
Before proceeding, make sure that you define the `GetAllowedDomainsForTenantId` function mentioned above.
This adds the list of allowed domains into the user's access token payload.

On the frontend, check whether the current subdomain is in the session's allowed domains.
If it is not, redirect the user to the correct subdomain.
You can achieve this by using the `hasAccessToCurrentDomain` session validator from the multitenancy recipe.


<VariantContent storageKey="ui-type" value="prebuilt">

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
You need to make changes to the auth route configuration, as well as to the `supertokens-web-js` SDK configuration at the root of your application:

This change is in your auth route configuration.
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
```tsx
import React from "react";
import Session from "supertokens-auth-react/recipe/session";
import { AllowedDomainsClaim } from "supertokens-auth-react/recipe/multitenancy";

Session.init({
  override: {
    functions: (oI) => ({
      ...oI,
      getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => [
        ...claimValidatorsAddedByOtherRecipes,
        {
          ...AllowedDomainsClaim.validators.hasAccessToCurrentDomain(),
          onFailureRedirection: async () => {
            let claimValue = await Session.getClaimValue({
              claim: AllowedDomainsClaim,
            });
            return "https://" + claimValue![0];
          },
        },
      ],
    }),
  },
});
```
</Tab>
<Tab title="Angular" value="angular">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)

supertokensUISession.init({
  override: {
    functions: (oI) => ({
      ...oI,
      getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => [
        ...claimValidatorsAddedByOtherRecipes,
        {
          ...supertokensMultitenancy.AllowedDomainsClaim.validators.hasAccessToCurrentDomain(),
          onFailureRedirection: async () => {
            let claimValue = await supertokensUISession.getClaimValue({
              claim: supertokensMultitenancy.AllowedDomainsClaim,
            });
            return "https://" + claimValue![0];
          },
        },
      ],
    }),
  },
});
```
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Reactjs" value="reactjs">
Above, in `Session.init` on the frontend, add the `hasAccessToCurrentDomain` claim validator to the global validators. This means that [whenever a route requires protection](/additional-verification/session-verification/protect-frontend-routes), it checks if `hasAccessToCurrentDomain` has passed. If not, SuperTokens redirects the user to the correct subdomain using the values in the `AllowedDomainsClaim` session claim.
</ContentOption>
<ContentOption title="Angular" value="angular">
This change goes in the `supertokens-web-js` SDK configuration at the root of your application:
</ContentOption>
</DependentContent>

<CodeGroup passive group="frontend-prebuilt-ui">
<Tab title="Angular" value="angular">
```tsx
import Session from "supertokens-web-js/recipe/session";
import { AllowedDomainsClaim } from "supertokens-web-js/recipe/multitenancy";

Session.init({
  override: {
    functions: (oI) => ({
      ...oI,
      getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => [
        ...claimValidatorsAddedByOtherRecipes,
        {
          ...AllowedDomainsClaim.validators.hasAccessToCurrentDomain(),
          onFailureRedirection: async () => {
            let claimValue = await Session.getClaimValue({
              claim: AllowedDomainsClaim,
            });
            return "https://" + claimValue![0];
          },
        },
      ],
    }),
  },
});
```
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
Above, in `Session.init` on the frontend, add the `hasAccessToCurrentDomain` claim validator to the global validators. This means that [whenever a route requires protection](/additional-verification/session-verification/protect-frontend-routes), it checks if `hasAccessToCurrentDomain` has passed. If not, SuperTokens redirects the user to the correct subdomain using the values in the `AllowedDomainsClaim` session claim.
</ContentOption>
</DependentContent>

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">

<CodeGroup group="install-method">
<Tab title="npm" value="npm">
```tsx
import Session from "supertokens-web-js/recipe/session";
import { AllowedDomainsClaim } from "supertokens-web-js/recipe/multitenancy";

Session.init({
  override: {
    functions: (oI) => ({
      ...oI,
      getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => [
        ...claimValidatorsAddedByOtherRecipes,
        {
          ...AllowedDomainsClaim.validators.hasAccessToCurrentDomain(),
          onFailureRedirection: async () => {
            let claimValue = await Session.getClaimValue({
              claim: AllowedDomainsClaim,
            });
            return "https://" + claimValue![0];
          },
        },
      ],
    }),
  },
});
```
</Tab>
<Tab title="Script tag" value="script-tag">
```tsx check=false reason="This example omits surrounding application and SuperTokens configuration."
supertokensSession.init({
  override: {
    functions: (oI) => ({
      ...oI,
      getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => [
        ...claimValidatorsAddedByOtherRecipes,
        {
          ...supertokensMultitenancy.AllowedDomainsClaim.validators.hasAccessToCurrentDomain(),
          onFailureRedirection: async () => {
            let claimValue = await supertokensSession.getClaimValue({
              claim: supertokensMultitenancy.AllowedDomainsClaim,
            });
            return "https://" + claimValue![0];
          },
        },
      ],
    }),
  },
});
```
</Tab>
</CodeGroup>

Above, in `Session.init` on the frontend, add the `hasAccessToCurrentDomain` claim validator to the global validators. This means that [whenever a route requires protection](/additional-verification/session-verification/protect-frontend-routes#check-the-claims-of-a-session), it checks if `hasAccessToCurrentDomain` has passed. If not, SuperTokens redirects the user to the correct subdomain using the values in the `AllowedDomainsClaim` session claim.

</VariantContent>


---

## See also

<CardGroup cols={3}>
  <Card title="Create and configure tenants" href="/authentication/enterprise/manage-tenants" />
  <Card title="Implement common domain login" href="/authentication/enterprise/common-domain-login" />
  <Card title="Implement subdomain login" href="/authentication/enterprise/subdomain-login" />
  <Card title="SAML" href="/authentication/enterprise/saml" />
  <Card title="Create and configure apps" href="/authentication/enterprise/manage-apps" />
</CardGroup>
