Skip to main content
Technology & EngineeringAuth Services271 lines

Auth0

Build with Auth0 for enterprise authentication and identity. Use this skill when

Quick Summary35 lines
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 lines
Paste into your CLAUDE.md or agent config

Auth0 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 withPageAuthRequired and withApiAuthRequired for 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

Get CLI access →