What White-Label Auth Actually Means
White-label authentication is the ability to present your own brand throughout the entire authentication experience, with zero mention of the underlying auth provider. Your users see your company name, your logo, your colors — from the SMS they receive to the login page they land on.
This matters more than most developers think. When a user receives an SMS saying "Your Auth0 verification code is: 482913" and they've never heard of Auth0, trust evaporates instantly. They think it's a phishing attempt. Support tickets spike. Conversion drops.
The difference between branded and unbranded auth:
Use Cases for White-Label Auth
Multi-Tenant SaaS Platforms
If you're building a SaaS platform where each customer (tenant) has their own users, white-label auth is essential. A project management tool serving both "Acme Corp" and "Beta Inc" needs each company's employees to see their own employer's branding during login — not yours, and certainly not your auth provider's.
Each tenant needs:
- Their company name in SMS messages
- Their logo on hosted login pages
- Their domain for authentication callbacks
- Their own user pool (tenant A's users can't log into tenant B)
Marketplace Platforms
Marketplaces like Shopify, Etsy, and Teachable serve thousands of independent businesses. Each business needs its own authentication experience. When a customer buys from "Sarah's Handmade Candles" on your marketplace, the OTP should say "Sarah's Handmade Candles" — not "ShopifyVerification" or some generic code.
Agency White-Labeling
Digital agencies build apps for clients. The auth system needs to be invisible. No "Powered by Auth0" footers. No third-party domains in the OAuth redirect. The agency delivers a complete product with authentication baked in, and the client's brand is the only one visible.
Branded SMS Messages
"Your {AppName} code is: 482913" — the tenant's name is automatically injected into every OTP message based on the API key used.
Custom Email Templates
Magic link emails, password reset emails, and welcome emails all carry the tenant's logo, colors, and sender address.
Hosted Login Pages
Each tenant gets a hosted login page at their own domain or subdomain, pre-styled with their brand colors and logo.
Invisible Infrastructure
No "Powered by" badges. No third-party domains in redirects. The auth provider is completely invisible to the end user.
How Auth1 Does White-Label Auth
Auth1 is multi-tenant by architecture. Every API key maps to a tenant, and every tenant has its own branding configuration. When an OTP request comes in, Auth1 looks up the tenant from the API key and applies their branding automatically.
Step 1: Create a Tenant with Branding
curl -X POST https://auth-api.z101.ai/api/admin/tenants \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -d '{ "name": "Acme Corp", "slug": "acme", "branding": { "sms_sender_name": "Acme", "sms_template": "Your {name} code is: {code}. Expires in {expiry} minutes.", "logo_url": "https://acme.com/logo.png", "primary_color": "#2563eb", "login_page_title": "Sign in to Acme", "support_email": "support@acme.com" }, "settings": { "otp_length": 6, "otp_expiry_minutes": 10, "max_otp_attempts": 5, "rate_limit_per_hour": 5, "voip_blocking": true } }' # Response: { "tenant_id": "tn_acme_7f3a...", "api_key": "auth1_pk_acme_a8b2c3d4e5f6...", "name": "Acme Corp" }
Step 2: Use the Tenant API Key
Every request using the Acme API key automatically gets Acme branding. No additional parameters needed:
// When this request is made with Acme's API key, // the SMS will say: "Your Acme code is: 482913" // No branding config needed in the request itself. const response = await fetch('https://auth-api.z101.ai/api/auth/request', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'auth1_pk_acme_a8b2c3d4e5f6...' }, body: JSON.stringify({ phone: '+15551234567' }) }); // The user receives: // "Your Acme code is: 482913. Expires in 10 minutes."
Step 3: Multiple Tenants, One Auth1 Instance
A single Auth1 deployment handles unlimited tenants. Each tenant is completely isolated — separate user pools, separate branding, separate rate limits. Your SaaS platform creates a new tenant for each customer:
// When a new customer signs up for your SaaS platform, // automatically provision an Auth1 tenant for them: async function provisionTenant(customer) { const tenant = await fetch('https://auth-api.z101.ai/api/admin/tenants', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${ADMIN_TOKEN}` }, body: JSON.stringify({ name: customer.companyName, slug: customer.slug, branding: { sms_sender_name: customer.companyName, logo_url: customer.logoUrl, primary_color: customer.brandColor, login_page_title: `Sign in to ${customer.companyName}` } }) }); const data = await tenant.json(); // Store the API key in your database // Use it for all auth requests for this customer's users await db.customers.update(customer.id, { auth1_api_key: data.api_key, auth1_tenant_id: data.tenant_id }); return data; }
Webhook Integration
Auth1 sends webhook events for every authentication action. Each webhook payload includes the tenant context, so your application can handle multi-tenant auth events in a single webhook endpoint:
// Auth1 webhook payload { "event": "auth.verified", "tenant_id": "tn_acme_7f3a...", "tenant_name": "Acme Corp", "user": { "phone": "+15551234567", "user_id": "usr_abc123", "is_new": true }, "risk": { "score": 0.12, "line_type": "mobile", "carrier": "T-Mobile", "voip": false }, "timestamp": "2026-03-23T14:22:31Z" } // Your webhook handler can route by tenant app.post('/webhooks/auth1', async (req, res) => { const { event, tenant_id, user, risk } = req.body; if (event === 'auth.verified') { // Find the customer in your database by tenant_id const customer = await db.customers.findBy({ auth1_tenant_id: tenant_id }); // Create or update the user in the customer's context await db.users.upsert({ customer_id: customer.id, phone: user.phone, auth1_user_id: user.user_id, risk_score: risk.score }); } res.sendStatus(200); });
How Others Handle White-Labeling
| Feature | Auth0 | Clerk | Firebase Auth | Auth1 |
|---|---|---|---|---|
| Branded SMS | Enterprise plan only ($3,500+/mo) | No (Clerk-branded) | No (Firebase-branded) | All plans |
| Custom login page | Yes (Universal Login) | Yes (components) | Limited | Yes (hosted + custom) |
| Remove provider branding | Enterprise only | Pro plan ($25/mo) | Not available | All plans |
| Per-tenant branding | Organizations add-on | Not available | Not available | Built-in |
| Multi-tenant user isolation | Yes (connections) | Limited | Separate projects required | Built-in (API key per tenant) |
| Self-hostable | No | No | No | Yes |
| Fraud protection per tenant | Bot detection only | No | reCAPTCHA integration | VOIP blocking + risk scoring |
The core issue with most providers is that white-labeling is an afterthought, available only on enterprise plans. Auth1 is multi-tenant by default — white-labeling is the normal mode of operation, not an upsell.
Auth0's white-label capabilities require the Enterprise plan starting at $3,500/month. Clerk's Pro plan at $25/month removes the "Secured by Clerk" badge but doesn't support per-tenant branding. Auth1's white-label features are available on all plans, including the free tier (1,000 verifications/month).
SDK Integration
For frontend integration, the Auth1 SDK handles the branded login flow with a few lines of code:
// Install: npm install @auth1/sdk import { Auth1Client } from '@auth1/sdk'; // Initialize with the tenant's API key const auth1 = new Auth1Client({ apiKey: process.env.AUTH1_API_KEY, // tenant-specific key baseUrl: 'https://auth-api.z101.ai' }); // Request OTP - SMS is automatically branded export async function requestOTP(phone) { const result = await auth1.requestOTP({ phone }); return result; // SMS sent: "Your Acme Corp code is: 482913" } // Verify OTP export async function verifyOTP(phone, code) { const result = await auth1.verifyOTP({ phone, code }); if (result.verified) { // Set session cookie cookies().set('auth_token', result.token, { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 86400 * 7 }); } return result; }
Custom Domains
For hosted login pages, each tenant can use their own domain or subdomain. Auth1 handles the TLS certificate provisioning via Let's Encrypt:
# Add a custom domain for the Acme tenant curl -X POST https://auth-api.z101.ai/api/admin/tenants/tn_acme_7f3a/domains \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -d '{ "domain": "login.acme.com", "auto_ssl": true }' # Response: { "domain": "login.acme.com", "status": "pending_dns", "cname_target": "custom.auth1.ai", "instructions": "Add a CNAME record: login.acme.com -> custom.auth1.ai" } # Once DNS propagates, the hosted login page is live at: # https://login.acme.com # Branded with Acme's logo, colors, and login page title
The hosted login page is fully responsive and customizable through the branding
configuration. Users visiting https://login.acme.com see a polished
login experience with Acme's branding — no mention of Auth1 anywhere.
Auth1's multi-tenant architecture stores branding configuration in the
auth_tenants PostgreSQL table. Each API key maps to exactly one
tenant. Lookups are cached in Redis with a 60-second TTL, so branding changes
take effect within a minute. The SMS template is rendered server-side before
being sent to Twilio, ensuring the branding is applied consistently regardless
of client implementation.