Auth0
Build with Auth0 for enterprise authentication and identity. Use this skill when
You are an auth specialist who integrates Auth0 into projects. Auth0 is an enterprise identity platform supporting OAuth 2.0, SAML, social login, MFA, passwordless auth, and enterprise SSO — all managed through a universal login page and extensible via Actions (serverless hooks). ## Key Points - Use Universal Login — don't build custom login forms unless you have a strong reason - Store only `user.sub` (Auth0 user ID) in your database — fetch profile data from Auth0 - Use Actions for post-login logic — sync users, add custom claims, enforce policies - Use RBAC for authorization — assign roles in Auth0, check them in your app - Request minimal scopes — only ask for what you need - Use `withPageAuthRequired` and `withApiAuthRequired` for route protection - Building custom login/signup forms instead of using Universal Login - Storing Auth0 tokens in localStorage — the SDK handles token storage securely - Not namespacing custom claims — Auth0 requires a URL namespace to avoid conflicts - Using Rules instead of Actions — Rules are legacy and being deprecated - Calling the Management API from the client — it requires admin credentials - Not setting up brute-force protection — enable it in Auth0 Dashboard ## Quick Example ```bash npm install @auth0/nextjs-auth0 ``` ```env AUTH0_SECRET=<random-32-byte-string> AUTH0_BASE_URL=http://localhost:3000 AUTH0_ISSUER_BASE_URL=https://your-tenant.auth0.com AUTH0_CLIENT_ID=your-client-id AUTH0_CLIENT_SECRET=your-client-secret ```
skilldb get auth-services-skills/Auth0Full skill: 271 linesAuth0 Authentication Integration
You are an auth specialist who integrates Auth0 into projects. Auth0 is an enterprise identity platform supporting OAuth 2.0, SAML, social login, MFA, passwordless auth, and enterprise SSO — all managed through a universal login page and extensible via Actions (serverless hooks).
Core Philosophy
Universal Login
Auth0's Universal Login page handles authentication in a hosted, secure context. Instead of building login forms, you redirect users to Auth0's login page. This centralizes security, enables SSO across apps, and supports every auth method without code changes.
Identity as a service
Auth0 manages the identity layer — user storage, password hashing, MFA, brute-force protection, anomaly detection. Your application receives tokens and user profiles. You focus on authorization logic, not auth infrastructure.
Extensible via Actions
Auth0 Actions are serverless functions that run at specific points in the auth pipeline — post-login, pre-registration, post-password-change. They replace the older Rules and Hooks system.
Setup
Install (Next.js)
npm install @auth0/nextjs-auth0
Environment variables
AUTH0_SECRET=<random-32-byte-string>
AUTH0_BASE_URL=http://localhost:3000
AUTH0_ISSUER_BASE_URL=https://your-tenant.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
Initialize (Next.js App Router)
// app/api/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0';
export const GET = handleAuth();
// Creates: /api/auth/login, /api/auth/logout, /api/auth/callback, /api/auth/me
Provider
// app/layout.tsx
import { UserProvider } from '@auth0/nextjs-auth0/client';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<UserProvider>{children}</UserProvider>
</body>
</html>
);
}
Key Techniques
Client-side auth
'use client';
import { useUser } from '@auth0/nextjs-auth0/client';
function Profile() {
const { user, error, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>{error.message}</div>;
if (!user) {
return <a href="/api/auth/login">Log in</a>;
}
return (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
<a href="/api/auth/logout">Log out</a>
</div>
);
}
Server-side auth (App Router)
import { getSession, withPageAuthRequired } from '@auth0/nextjs-auth0';
// Protected page
export default withPageAuthRequired(async function Dashboard() {
const session = await getSession();
const user = session?.user;
return <div>Welcome {user?.name}</div>;
});
// API route protection
import { withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export const GET = withApiAuthRequired(async function handler(req) {
const session = await getSession();
const userId = session?.user.sub;
const data = await db.query.posts.findMany({
where: eq(posts.authorId, userId),
});
return Response.json(data);
});
Custom login parameters
// Redirect to signup instead of login
<a href="/api/auth/login?screen_hint=signup">Sign up</a>
// Force specific connection (e.g., Google)
<a href="/api/auth/login?connection=google-oauth2">Sign in with Google</a>
// Custom handler with parameters
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
export const GET = handleAuth({
login: handleLogin({
authorizationParams: {
audience: 'https://api.example.com',
scope: 'openid profile email read:posts',
},
}),
});
Access tokens for APIs
import { getAccessToken } from '@auth0/nextjs-auth0';
export async function GET() {
const { accessToken } = await getAccessToken({
scopes: ['read:posts'],
});
const res = await fetch('https://api.example.com/posts', {
headers: { Authorization: `Bearer ${accessToken}` },
});
return Response.json(await res.json());
}
Management API
import { ManagementClient } from 'auth0';
const management = new ManagementClient({
domain: process.env.AUTH0_DOMAIN!,
clientId: process.env.AUTH0_MGMT_CLIENT_ID!,
clientSecret: process.env.AUTH0_MGMT_CLIENT_SECRET!,
});
// Get user
const user = await management.users.get({ id: userId });
// Update user metadata
await management.users.update(
{ id: userId },
{ user_metadata: { plan: 'pro' } }
);
// Assign roles
await management.users.assignRoles(
{ id: userId },
{ roles: ['role_admin_id'] }
);
Actions (post-login hook)
// Auth0 Dashboard > Actions > Flows > Login
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://myapp.com';
// Add custom claims to token
api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization?.roles || []);
api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization?.roles || []);
// Sync user to external database on first login
if (event.stats.logins_count === 1) {
await fetch('https://myapp.com/api/webhooks/auth0', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Auth0-Secret': event.secrets.WEBHOOK_SECRET },
body: JSON.stringify({
event: 'user.created',
user: { id: event.user.user_id, email: event.user.email, name: event.user.name },
}),
});
}
};
Role-based access control (RBAC)
import { getSession } from '@auth0/nextjs-auth0';
export async function GET() {
const session = await getSession();
const roles = session?.user['https://myapp.com/roles'] || [];
if (!roles.includes('admin')) {
return new Response('Forbidden', { status: 403 });
}
// Admin-only logic
const allUsers = await db.query.users.findMany();
return Response.json(allUsers);
}
Machine-to-machine (M2M) auth
// Backend service getting a token
const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: process.env.M2M_CLIENT_ID,
client_secret: process.env.M2M_CLIENT_SECRET,
audience: 'https://api.example.com',
grant_type: 'client_credentials',
}),
});
const { access_token } = await response.json();
Best Practices
- Use Universal Login — don't build custom login forms unless you have a strong reason
- Store only
user.sub(Auth0 user ID) in your database — fetch profile data from Auth0 - Use Actions for post-login logic — sync users, add custom claims, enforce policies
- Use RBAC for authorization — assign roles in Auth0, check them in your app
- Request minimal scopes — only ask for what you need
- Use
withPageAuthRequiredandwithApiAuthRequiredfor route protection
Anti-Patterns
- Building custom login/signup forms instead of using Universal Login
- Storing Auth0 tokens in localStorage — the SDK handles token storage securely
- Not namespacing custom claims — Auth0 requires a URL namespace to avoid conflicts
- Using Rules instead of Actions — Rules are legacy and being deprecated
- Calling the Management API from the client — it requires admin credentials
- Not setting up brute-force protection — enable it in Auth0 Dashboard
Install this skill directly: skilldb add auth-services-skills
Related Skills
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.
Kinde
Build with Kinde for authentication and user management. Use this skill when the