npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@supertokens-plugins/tenant-discovery-nodejs

v0.2.1

Published

Tenant Discovery Plugin for SuperTokens

Readme

SuperTokens Plugin Tenant Discovery

Automatically discover and route users to appropriate tenants based on their email domains. This plugin provides endpoints to infer tenant IDs from email domains.

Installation

npm install @supertokens-plugins/tenant-discovery-nodejs

Quick Start

Backend Configuration

Initialize the plugin in your SuperTokens backend configuration:

import SuperTokens from "supertokens-node";
import TenantDiscoveryPlugin from "@supertokens-plugins/tenant-discovery-nodejs";

SuperTokens.init({
  appInfo: {
    // your app info
  },
  recipeList: [
    // your other recipes
  ],
  experimental: {
    plugins: [
      TenantDiscoveryPlugin.init({
        enableTenantListAPI: false,
      }),
    ],
  }
});

API Endpoints

The plugin automatically creates these endpoints:

Get Tenant from Email

  • POST /plugin/supertokens-plugin-tenant-discovery/from-email
  • Body:
    {
      "email": "[email protected]"
    }
  • Response:
    {
      "status": "OK",
      "tenant": "company1"
    }

Block emails from tenant

The default fallback for getting the tenant ID from the email is "public". If this doesn't work in your use-case, we provide a function that can be overridden to avoid this.

You can avoid redirecting users to the public tenant by overriding the isTenantAllowedForEmail function like this:

import SuperTokens from "supertokens-node";
import TenantDiscoveryPlugin from "@supertokens-plugins/tenant-discovery-nodejs";

SuperTokens.init({
  appInfo: {
    // your app info
  },
  recipeList: [
    // your other recipes
  ],
  plugins: [
    TenantDiscoveryPlugin.init({
      enableTenantListAPI: false,
      override: (originalImplementation) => ({
        ...originalImplementation,
        isTenantAllowedForEmail: (email: string, tenantId: string) => {
          // Check whether the email can access the tenant
          return tenantId !== "public;
        },
      }),
    }),
  ],
});

List All Tenants

[!IMPORTANT]
This is disabled by default. The enableTenantListAPI field in config has to be set to true in order to enable it.

  • GET /plugin/supertokens-plugin-tenant-discovery/list
  • Response:
    {
      "status": "OK",
      "tenants": [
        {
          "tenantId": "public",
          "displayName": "public"
        },
        {
          "tenantId": "tenant1",
          "displayName": "tenant1"
        }
      ]
    }

Configuration Options

| Option | Type | Default | Description | | --------------------- | --------- | ------- | ----------------------------------------------------- | | enableTenantListAPI | boolean | false | Whether to show tenant selector (enable API's or not) |

How It Works

Email Domain to Tenant ID Inference

  • The plugin extracts the domain from user email addresses (e.g., [email protected]company.com)
  • It then extracts the tenant ID from the domain by taking the second-to-last part (e.g., company.comcompany or test.company.com -> company)
  • For domains with only one part, it uses the entire domain as tenant ID
  • If the inferred tenant doesn't exist in your SuperTokens setup, it falls back to the public tenant

Domain Restrictions

  • Popular email domains (Gmail, Yahoo, Outlook, etc.) are automatically blocked from tenant inference
  • Restricted domains automatically return public as the tenant ID
  • This prevents assignment of public email users to inferred tenant IDs

Tenant Validation

  • The plugin validates if the inferred tenant ID actually exists in your SuperTokens configuration
  • If the inferred tenant exists, it's returned as the final tenant
  • If the inferred tenant doesn't exist, public is returned as the fallback

Ways to Use Tenant Discovery

Frontend plugin

You can use the @supertokens-plugins/tenant-discovery-react plugin on the frontend to automatically integrate with this plugin

Frontend Integration

If you are using a custom UI or want to avoid using the above mentioned plugin:

Plugin APIs

Use the plugin's API endpoints from your frontend to determine which tenant a user belongs to:

// Discover tenant from email during sign-up/sign-in
const discoverTenant = async (email: string) => {
  const response = await fetch("/plugin/supertokens-plugin-tenant-discovery/from-email", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email }),
  });

  const result = await response.json();
  if (result.status === "OK") {
    // Use the validated tenant ID
    console.log(`Final tenant: ${result.tenant}`);
    // Redirect user to tenant-specific sign-in page
    window.location.href = `/auth?tenantId=${result.tenant}`;
  }
};

// Get list of all available tenants
const getTenants = async () => {
  const response = await fetch("/plugin/supertokens-plugin-tenant-discovery/list");
  const result = await response.json();
  return result.tenants;
};

Multi-Step Authentication Flow

  1. User enters email on landing page
  2. Call /from-email endpoint to infer and validate tenant
  3. Use the returned tenant field for routing (validated tenant)
  4. Redirect user to tenant-specific authentication flow
  5. User completes sign-up/sign-in in correct tenant context

API Integration

// Example: Email-based tenant discovery during user onboarding
const handleEmailSubmit = async (email: string) => {
  try {
    const response = await fetch("/plugin/supertokens-plugin-tenant-discovery/from-email", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ email }),
    });

    const result = await response.json();

    if (result.status === "OK") {
      // Proceed with authentication in validated tenant
      console.log(`User ${email} belongs to tenant: ${result.tenant}`);
      // Initialize SuperTokens with validated tenant
      initAuthWithTenant(result.tenant);
    }
  } catch (error) {
    console.error("Tenant discovery failed:", error);
    // Fallback to public tenant
    initAuthWithTenant("public");
  }
};

Error Handling

The plugin returns standardized error responses:

// Missing email
{
  "status": "ERROR",
  "message": "Email is required"
}

// Restricted domain (returns public)
{
  "status": "OK",
  "tenant": "public", // Restricted domain fallback
  "email": "[email protected]"
}

// Invalid tenant (inferred tenant doesn't exist)
{
  "status": "OK",
  "tenant": "public", // Fallback when inferred tenant doesn't exist
  "email": "[email protected]"
}

Domain Restrictions

The plugin automatically blocks these popular email domains from tenant inference:

  • gmail.com, yahoo.com, hotmail.com, outlook.com
  • icloud.com, aol.com, live.com, msn.com
  • And other popular domains

You can add custom restrictions:

TenantDiscoveryPlugin.init({
  override: (originalImplementation) => ({
        ...originalImplementation,
        isRestrictedEmailDomain: (emailDomain: string) => {
          return originalImplementation.isRestrictedEmailDomain(emailDomain) || emailDomain === "example.com"
        },
      }),
});

Examples of tenant inference:

Requirements

  • SuperTokens Node.js SDK >= 23.0.0
  • Multi-tenancy must be properly configured in your SuperTokens setup