Stytch
Build with Stytch for passwordless and modern authentication. Use this skill when
You are an auth specialist who integrates Stytch into projects. Stytch is an
authentication platform focused on passwordless methods — magic links, OTPs,
passkeys, and biometrics — with strong B2B multi-tenancy support.
## Key Points
- Use magic links or OTPs as the primary auth method — better UX than passwords
- Store Stytch session tokens in httpOnly cookies — never in localStorage
- Validate sessions on every request — sessions can be revoked server-side
- Use B2B SDK for multi-tenant apps — organizations, roles, and SSO built in
- Set appropriate session durations — 7 days for consumer, shorter for enterprise
- Use Stytch's user metadata to store app-specific data alongside auth
- Storing session tokens in localStorage — XSS vulnerability
- Not validating sessions server-side — expired or revoked sessions must be caught
- Building organization management yourself when Stytch B2B handles it
- Using long session durations for sensitive apps — use shorter sessions with refresh
- Not handling magic link expiry — links expire after the configured time
- Sending OTPs without rate limiting — prevents abuse
## Quick Example
```bash
npm install stytch
```
```typescript
// Revoke current session
await client.sessions.revoke({ session_token: sessionToken });
// Revoke all sessions for a user
await client.sessions.revokeAll({ user_id: userId });
```skilldb get auth-services-skills/StytchFull skill: 214 linesStytch Authentication Integration
You are an auth specialist who integrates Stytch into projects. Stytch is an authentication platform focused on passwordless methods — magic links, OTPs, passkeys, and biometrics — with strong B2B multi-tenancy support.
Core Philosophy
Passwordless first
Stytch was built for a post-password world. Magic links, email OTPs, SMS OTPs, passkeys, and biometric auth are first-class. Password auth exists but isn't the default. Passwordless reduces friction and eliminates credential stuffing.
B2B and B2C in one platform
Stytch offers separate B2C and B2B SDKs. B2B includes organization management, SSO/SAML, SCIM provisioning, and role-based access — the enterprise auth features startups usually build months later.
API-first
Stytch's API is clean and RESTful. The SDKs are thin wrappers. You can integrate Stytch purely via API calls without a frontend SDK if you prefer full control.
Setup
Install
npm install stytch
Initialize
import * as stytch from 'stytch';
const client = new stytch.Client({
project_id: process.env.STYTCH_PROJECT_ID!,
secret: process.env.STYTCH_SECRET!,
});
Key Techniques
Magic link authentication
// Send magic link
export async function POST(req: Request) {
const { email } = await req.json();
const response = await client.magicLinks.email.loginOrCreate({
email,
login_magic_link_url: `${process.env.NEXT_PUBLIC_URL}/api/auth/callback`,
signup_magic_link_url: `${process.env.NEXT_PUBLIC_URL}/api/auth/callback`,
});
return Response.json({ sent: true });
}
// Handle callback
export async function GET(req: Request) {
const url = new URL(req.url);
const token = url.searchParams.get('token');
if (!token) return new Response('Missing token', { status: 400 });
const response = await client.magicLinks.authenticate({
token,
session_duration_minutes: 60 * 24 * 7, // 7 days
});
// Set session token as cookie
const headers = new Headers();
headers.set('Set-Cookie', `stytch_session=${response.session_token}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${60 * 60 * 24 * 7}`);
headers.set('Location', '/dashboard');
return new Response(null, { status: 302, headers });
}
Email OTP
// Send OTP
const response = await client.otps.email.loginOrCreate({
email: 'user@example.com',
expiration_minutes: 10,
});
const methodId = response.email_id;
// Verify OTP
const authResponse = await client.otps.authenticate({
method_id: methodId,
code: userEnteredCode,
session_duration_minutes: 60 * 24 * 7,
});
OAuth (Google, GitHub, etc.)
// Start OAuth flow
export async function GET() {
const url = client.oauth.google.getAuthorizationURL({
login_redirect_url: `${process.env.NEXT_PUBLIC_URL}/api/auth/oauth/callback`,
signup_redirect_url: `${process.env.NEXT_PUBLIC_URL}/api/auth/oauth/callback`,
});
return Response.redirect(url);
}
// Handle callback
export async function GET(req: Request) {
const url = new URL(req.url);
const token = url.searchParams.get('token')!;
const response = await client.oauth.authenticate({
token,
session_duration_minutes: 60 * 24 * 7,
});
// response.user contains user info
// response.session_token is the session
// Set cookie and redirect
}
Session validation
import { cookies } from 'next/headers';
export async function validateSession() {
const sessionToken = (await cookies()).get('stytch_session')?.value;
if (!sessionToken) return null;
try {
const response = await client.sessions.authenticate({
session_token: sessionToken,
});
return response.user;
} catch {
return null;
}
}
// Use in pages
export default async function DashboardPage() {
const user = await validateSession();
if (!user) redirect('/login');
return <div>Welcome {user.emails[0]?.email}</div>;
}
Session revocation
// Revoke current session
await client.sessions.revoke({ session_token: sessionToken });
// Revoke all sessions for a user
await client.sessions.revokeAll({ user_id: userId });
B2B organizations
import * as stytch from 'stytch';
const b2bClient = new stytch.B2BClient({
project_id: process.env.STYTCH_PROJECT_ID!,
secret: process.env.STYTCH_SECRET!,
});
// Create organization
const org = await b2bClient.organizations.create({
organization_name: 'Acme Corp',
organization_slug: 'acme',
email_allowed_domains: ['acme.com'],
});
// Invite member
await b2bClient.magicLinks.email.invite({
organization_id: org.organization.organization_id,
email_address: 'employee@acme.com',
});
// SSO/SAML for enterprise orgs
await b2bClient.sso.saml.createConnection({
organization_id: orgId,
display_name: 'Acme SSO',
});
Best Practices
- Use magic links or OTPs as the primary auth method — better UX than passwords
- Store Stytch session tokens in httpOnly cookies — never in localStorage
- Validate sessions on every request — sessions can be revoked server-side
- Use B2B SDK for multi-tenant apps — organizations, roles, and SSO built in
- Set appropriate session durations — 7 days for consumer, shorter for enterprise
- Use Stytch's user metadata to store app-specific data alongside auth
Anti-Patterns
- Storing session tokens in localStorage — XSS vulnerability
- Not validating sessions server-side — expired or revoked sessions must be caught
- Building organization management yourself when Stytch B2B handles it
- Using long session durations for sensitive apps — use shorter sessions with refresh
- Not handling magic link expiry — links expire after the configured time
- Sending OTPs without rate limiting — prevents abuse
Install this skill directly: skilldb add auth-services-skills
Related Skills
Auth0
Build with Auth0 for enterprise authentication and identity. Use this skill when
Clerk
Build with Clerk for authentication and user management. Use this skill when the
Cognito
Build with Amazon Cognito for authentication and user management. Use this skill
Descope
Integrate Descope to add secure, no-code/low-code authentication and user management to your applications.
Firebase Auth
Build with Firebase Authentication for user sign-in. Use this skill when the
Hanko
Integrate Hanko for modern, passwordless authentication in your web applications.