Skip to main content

Multi-Tenancy

Signia's multi-tenant architecture allows you to manage multiple organizations with isolated user bases and independent configurations.

What is Multi-Tenancy?

Multi-tenancy is a software architecture where a single instance serves multiple customers (tenants), each with isolated data and configuration.

Hierarchy

Tenant (Organization)
├── Applications
│ ├── Web App
│ ├── Mobile App
│ └── Admin Portal
└── Users
├── user@example.com
├── admin@example.com
└── developer@example.com

Key Concepts:

  • Tenant - An organization (e.g., "Acme Corp")
  • Subdomain - Unique identifier (e.g., acme.signiaauth.com)
  • Applications - Apps within the tenant
  • Users - Belong to a tenant, can access multiple apps

Tenant Structure

Tenant Configuration

Each tenant has:

  • Subdomain - Unique identifier

    acme.signiaauth.com
  • Name - Display name

    Acme Corporation
  • Settings - Independent configuration

    • Security policies
    • Branding
    • Token lifetimes
    • Allowed authentication methods
  • Applications - OAuth2/OIDC clients

  • Users - Tenant-specific user base

Setting Up a Tenant

Creating a Tenant

Creating a tenant is self-service - no need to contact support!

Required Information:

  • Organization name
  • Subdomain (must be unique)
  • Admin email
  • Billing information (if applicable)

Steps:

  1. Sign up at signiaid.com
  2. Complete the registration form
  3. Choose your unique subdomain
  4. Verify your email
  5. Your tenant is ready to use!

Subdomain Rules:

  • 3-63 characters
  • Lowercase letters, numbers, hyphens
  • Cannot start/end with hyphen
  • Must be globally unique
✅ acme
✅ acme-corp
✅ my-company-2024

❌ Acme (uppercase)
❌ acme_corp (underscore)
❌ -acme (starts with hyphen)
❌ ac (too short)

Tenant URL Structure

Each tenant has unique URLs:

Auth Server:

https://acme.signiaauth.com

Dashboard:

https://signiaid.com

OIDC Discovery:

https://acme.signiaauth.com/.well-known/openid-configuration

Tenant Isolation

Data Isolation

Tenants are completely isolated:

  • ✅ Separate databases or schemas
  • ✅ Isolated user bases
  • ✅ Independent configurations
  • ✅ No cross-tenant data access

Security Boundaries

Tenant A                    Tenant B
├── Users ├── Users
│ ├── alice@a.com │ ├── bob@b.com
│ └── charlie@a.com │ └── diane@b.com
├── Apps ├── Apps
│ └── App 1 │ └── App 1
└── Settings └── Settings
└── Policy A └── Policy B

❌ Alice cannot access Tenant B
❌ Bob cannot access Tenant A apps
❌ Tenant A settings don't affect Tenant B

Tenant Configuration

Branding

Customize the authentication experience:

Logo:

  • Upload custom logo
  • Displayed on login screen
  • Recommended: 200x50px PNG

Colors:

  • Primary color
  • Button color
  • Background color

Domain:

  • Custom domain (Enterprise)
    auth.acme.com

Security Policies

Configure tenant-specific security:

Password Policies (if using passwords):

  • Minimum length
  • Complexity requirements
  • Expiration period
  • History prevention

Session Policies:

  • Session timeout
  • Concurrent sessions limit
  • Remember device duration

Authentication Methods:

  • WebAuthn/Passkeys (enabled by default)
  • Magic links
  • Social logins
  • SAML (Enterprise)
  • LDAP/Active Directory (Enterprise)

Token Configuration

Independent token settings per tenant:

Access Tokens:

  • Lifetime: 1 hour - 24 hours
  • Refresh rotation: enabled/disabled
  • Claims included

ID Tokens:

  • Lifetime: 1 hour - 24 hours
  • Custom claims

Refresh Tokens:

  • Lifetime: 1 day - 90 days
  • Rotation policy

Multi-Tenant Applications

Single Application, Multiple Tenants

Your application can serve multiple tenants:

// Determine tenant from subdomain
const tenant = req.hostname.split('.')[0]; // "acme" from "acme.myapp.com"

// Configure OIDC client dynamically
const oidcClient = new OIDCClient({
clientId: process.env.OIDC_CLIENT_ID,
redirectUri: `https://${tenant}.myapp.com/oidc-callback`,
issuer: `https://${tenant}.signiaauth.com`, // Tenant-specific issuer
scopes: ['openid', 'profile', 'email']
});

Tenant Discovery

Automatically detect tenant:

Option 1: Subdomain-based

https://acme.myapp.com  →  tenant: acme
https://xyz.myapp.com → tenant: xyz

Option 2: Path-based

https://myapp.com/acme  →  tenant: acme
https://myapp.com/xyz → tenant: xyz

Option 3: User email domain

user@acme.com    →  tenant: acme
user@xyz.com → tenant: xyz

Tenant Mapping

Store tenant configuration:

const tenantConfig = {
'acme': {
name: 'Acme Corp',
issuer: 'https://acme.signiaauth.com',
clientId: 'acme-client-id',
branding: {
logo: '/logos/acme.png',
primaryColor: '#FF5722'
}
},
'xyz': {
name: 'XYZ Inc',
issuer: 'https://xyz.signiaauth.com',
clientId: 'xyz-client-id',
branding: {
logo: '/logos/xyz.png',
primaryColor: '#2196F3'
}
}
};

// Get tenant config
const config = tenantConfig[tenant];

User Management Across Tenants

Single User, Multiple Tenants

Users can belong to multiple tenants:

{
"email": "user@example.com",
"tenants": [
{
"id": "acme",
"role": "admin"
},
{
"id": "xyz",
"role": "member"
}
]
}

Tenant Switching

Allow users to switch between tenants:

function TenantSwitcher() {
const { userTenants, currentTenant, switchTenant } = useSigniaAuth();

return (
<select
value={currentTenant}
onChange={(e) => switchTenant(e.target.value)}
>
{userTenants.map(tenant => (
<option key={tenant.id} value={tenant.id}>
{tenant.name}
</option>
))}
</select>
);
}

Tenant Administration

Admin Roles

Platform Admin:

  • Can create/delete tenants
  • Can view all tenants
  • Cannot access tenant data

Tenant Admin:

  • Full access to their tenant
  • Can manage users and apps
  • Cannot access other tenants

Tenant Settings

Access tenant settings from dashboard:

  1. Navigate to SettingsTenant
  2. View/edit tenant configuration
  3. Requires tenant admin role

Configurable:

  • Organization name
  • Subdomain (contact support)
  • Branding
  • Security policies
  • Billing settings

Usage Monitoring

Track tenant usage:

Metrics:

  • Active users (monthly)
  • Total authentications
  • API calls
  • Storage used

Billing:

  • Per-user pricing
  • Overage charges
  • Invoice history

Enterprise Features

Custom Domains

Use your own domain for authentication:

Setup:

  1. Purchase custom domain
  2. Create CNAME record:
    auth.acme.com  →  acme.signiaauth.com
  3. Contact Signia support to enable
  4. SSL certificate automatically provisioned

Benefits:

  • Branded experience
  • Consistent domain for users
  • Better trust

Dedicated Infrastructure

For high-volume tenants:

  • Dedicated database
  • Isolated compute resources
  • Custom SLA
  • Priority support

Private Deployment

Run Signia in your infrastructure:

  • On-premises deployment
  • Private cloud (VPC)
  • Full data control
  • Custom compliance requirements

Best Practices

1. Tenant Identification

Choose the right tenant identification strategy:

Subdomain-based (Recommended):

✅ Clear separation
✅ Tenant branding possible
✅ SSL per tenant

Path-based:

⚠️ Single SSL cert
⚠️ Shared cookies
✅ Easier setup

2. Configuration Management

Store tenant configs centrally:

// Database-driven config
const config = await db.tenants.findOne({ subdomain: 'acme' });

// Cache for performance
const cache = new Map();

3. Error Handling

Handle tenant not found gracefully:

if (!tenantExists(tenant)) {
return res.status(404).render('tenant-not-found');
}

4. Testing

Test with multiple tenants:

describe('Multi-tenant auth', () => {
it('should isolate tenant A from tenant B', async () => {
// Login to tenant A
// Attempt to access tenant B
// Should be denied
});
});

Migration Strategies

From Single-Tenant to Multi-Tenant

Steps:

  1. Add tenant_id column

    ALTER TABLE users ADD COLUMN tenant_id VARCHAR(255);
    ALTER TABLE applications ADD COLUMN tenant_id VARCHAR(255);
  2. Migrate existing data

    UPDATE users SET tenant_id = 'default';
    UPDATE applications SET tenant_id = 'default';
  3. Update application logic

    // Before
    const users = await db.users.find();

    // After
    const users = await db.users.find({ tenant_id: currentTenant });
  4. Add tenant middleware

    app.use(tenantMiddleware);

Troubleshooting

"Tenant not found"

Cause: Invalid or non-existent tenant subdomain

Solution:

  • Verify subdomain spelling
  • Check tenant is active
  • Contact admin if recently created

Cross-tenant access attempt

Cause: User trying to access another tenant

Solution:

  • Check tenant ID in request
  • Verify user belongs to tenant
  • Review session data

Configuration not applying

Cause: Config cached or not saved

Solution:

  • Clear config cache
  • Save and refresh dashboard
  • Check tenant ID in config

Next Steps