Marketplace
auth0
Implements Auth0 authentication with Next.js SDK, React hooks, role-based access, and API protection. Use when integrating Auth0, implementing enterprise SSO, or needing managed authentication with MFA.
$ 安裝
git clone https://github.com/mgd34msu/goodvibes-plugin /tmp/goodvibes-plugin && cp -r /tmp/goodvibes-plugin/plugins/goodvibes/skills/webdev/authentication/auth0 ~/.claude/skills/goodvibes-plugin// tip: Run this command in your terminal to install the skill
SKILL.md
name: auth0 description: Implements Auth0 authentication with Next.js SDK, React hooks, role-based access, and API protection. Use when integrating Auth0, implementing enterprise SSO, or needing managed authentication with MFA.
Auth0
Auth0 is an identity platform providing authentication, authorization, and user management. The Next.js SDK (v4) offers full App Router and Pages Router support.
Quick Start
Installation
npm install @auth0/nextjs-auth0
Environment Variables
# .env.local
AUTH0_SECRET='use-a-long-random-string-min-32-chars'
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'
Generate secret: openssl rand -hex 32
Auth0 Dashboard Setup
- Create Regular Web Application
- Set Allowed Callback URLs:
http://localhost:3000/auth/callback - Set Allowed Logout URLs:
http://localhost:3000 - Set Allowed Web Origins:
http://localhost:3000
App Router Setup (Next.js 13+)
Create Auth Route Handler
// app/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0'
export const GET = handleAuth()
This creates routes:
/auth/login- Initiates login/auth/logout- Logs out user/auth/callback- OAuth callback/auth/me- Returns user profile
Add Provider
// app/layout.tsx
import { Auth0Provider } from '@auth0/nextjs-auth0'
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<Auth0Provider>
{children}
</Auth0Provider>
</body>
</html>
)
}
Client Component Usage
'use client'
import { useUser } from '@auth0/nextjs-auth0'
export default function Profile() {
const { user, error, isLoading } = useUser()
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
if (!user) return <a href="/auth/login">Login</a>
return (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
<a href="/auth/logout">Logout</a>
</div>
)
}
Server Component Usage
// app/dashboard/page.tsx
import { getSession } from '@auth0/nextjs-auth0'
import { redirect } from 'next/navigation'
export default async function Dashboard() {
const session = await getSession()
if (!session) {
redirect('/auth/login')
}
return (
<div>
<h1>Welcome, {session.user.name}</h1>
<pre>{JSON.stringify(session.user, null, 2)}</pre>
</div>
)
}
Protected Routes
Middleware Protection
// middleware.ts
import { withMiddlewareAuthRequired } from '@auth0/nextjs-auth0/edge'
export default withMiddlewareAuthRequired()
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*']
}
Page-Level Protection
// app/protected/page.tsx
import { withPageAuthRequired, getSession } from '@auth0/nextjs-auth0'
export default withPageAuthRequired(async function ProtectedPage() {
const session = await getSession()
return <div>Protected content for {session?.user.email}</div>
}, {
returnTo: '/protected'
})
API Route Protection
Server Component API
// app/api/me/route.ts
import { getSession } from '@auth0/nextjs-auth0'
import { NextResponse } from 'next/server'
export async function GET() {
const session = await getSession()
if (!session) {
return NextResponse.json(
{ error: 'Not authenticated' },
{ status: 401 }
)
}
return NextResponse.json({ user: session.user })
}
Protected API Route
// app/api/protected/route.ts
import { withApiAuthRequired, getSession } from '@auth0/nextjs-auth0'
import { NextResponse } from 'next/server'
export const GET = withApiAuthRequired(async function handler(req) {
const session = await getSession()
return NextResponse.json({
message: `Hello ${session?.user.name}`
})
})
Calling External APIs
Get Access Token
// app/api/external/route.ts
import { getAccessToken } from '@auth0/nextjs-auth0'
import { NextResponse } from 'next/server'
export async function GET() {
try {
const { accessToken } = await getAccessToken({
scopes: ['read:data']
})
const response = await fetch('https://api.example.com/data', {
headers: {
Authorization: `Bearer ${accessToken}`
}
})
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
return NextResponse.json(
{ error: 'Failed to get token' },
{ status: 500 }
)
}
}
Configure API Audience
AUTH0_AUDIENCE='https://api.example.com'
AUTH0_SCOPE='openid profile email read:data'
Role-Based Access Control
Add Roles to Tokens
In Auth0 Dashboard > Actions > Flows > Login, add:
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://myapp.com'
if (event.authorization) {
api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles)
api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles)
}
}
Check Roles
// lib/auth.ts
import { getSession } from '@auth0/nextjs-auth0'
export async function getUserRoles(): Promise<string[]> {
const session = await getSession()
if (!session) return []
return session.user['https://myapp.com/roles'] || []
}
export async function hasRole(role: string): Promise<boolean> {
const roles = await getUserRoles()
return roles.includes(role)
}
export async function requireRole(role: string) {
if (!(await hasRole(role))) {
throw new Error('Unauthorized')
}
}
Role-Protected Component
// app/admin/page.tsx
import { getSession } from '@auth0/nextjs-auth0'
import { redirect } from 'next/navigation'
export default async function AdminPage() {
const session = await getSession()
const roles = session?.user['https://myapp.com/roles'] || []
if (!roles.includes('admin')) {
redirect('/unauthorized')
}
return <div>Admin Dashboard</div>
}
Custom Login/Logout
Custom Login Options
// app/auth/[auth0]/route.ts
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0'
export const GET = handleAuth({
login: handleLogin({
authorizationParams: {
audience: 'https://api.example.com',
scope: 'openid profile email read:data'
},
returnTo: '/dashboard'
}),
signup: handleLogin({
authorizationParams: {
screen_hint: 'signup'
}
})
})
Custom Logout
import { handleAuth, handleLogout } from '@auth0/nextjs-auth0'
export const GET = handleAuth({
logout: handleLogout({
returnTo: '/'
})
})
Session Management
Update Session
// app/api/update-session/route.ts
import { getSession, updateSession } from '@auth0/nextjs-auth0'
import { NextResponse } from 'next/server'
export async function POST(req: Request) {
const session = await getSession()
if (!session) {
return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
}
// Update session with custom data
await updateSession({
...session,
user: {
...session.user,
customData: 'new value'
}
})
return NextResponse.json({ success: true })
}
Session Configuration
// app/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0'
export const GET = handleAuth({
onError(req, error) {
console.error(error)
}
})
Organization Support
Login to Organization
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0'
export const GET = handleAuth({
login: handleLogin({
authorizationParams: {
organization: 'org_123'
}
})
})
Dynamic Organization
// app/login/[org]/route.ts
import { handleLogin } from '@auth0/nextjs-auth0'
import { NextRequest } from 'next/server'
export async function GET(
req: NextRequest,
{ params }: { params: { org: string } }
) {
return handleLogin(req, {
authorizationParams: {
organization: params.org
}
})
}
Multi-Factor Authentication
Enable MFA in Auth0 Dashboard > Security > Multi-factor Auth:
// Force MFA for sensitive actions
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0'
export const GET = handleAuth({
'login-mfa': handleLogin({
authorizationParams: {
acr_values: 'http://schemas.openid.net/pape/policies/2007/06/multi-factor'
}
})
})
Testing
Mock User in Tests
// __tests__/profile.test.tsx
import { render, screen } from '@testing-library/react'
import { UserProvider } from '@auth0/nextjs-auth0'
import Profile from '@/app/profile/page'
const mockUser = {
name: 'Test User',
email: 'test@example.com',
picture: 'https://example.com/avatar.png'
}
test('renders user profile', () => {
render(
<UserProvider user={mockUser}>
<Profile />
</UserProvider>
)
expect(screen.getByText('Test User')).toBeInTheDocument()
})
Best Practices
- Use environment variables - Never hardcode secrets
- Protect API routes - Use
withApiAuthRequired - Add roles to tokens - Use Auth0 Actions
- Configure audiences - For API access tokens
- Handle errors gracefully - Provide user-friendly messages
- Use middleware - For route protection at scale
References
Repository

mgd34msu
Author
mgd34msu/goodvibes-plugin/plugins/goodvibes/skills/webdev/authentication/auth0
0
Stars
0
Forks
Updated6h ago
Added1w ago