---
description: Framework-specific implementation guide for adding Auth0 OAuth to your application
---
# OAuth Implementation Guide
Detailed code walkthrough for implementing Auth0 authentication in your framework.
## Quick Start
```bash
/oauth-implement [framework]
```
Supported frameworks:
- `react` - React with Create React App or Vite
- `nextjs` - Next.js (13+ with App Router recommended)
- `nodejs` - Node.js/Express backend
- `fastapi` - Python FastAPI
- `django` - Python Django
- `vue` - Vue.js
- `svelte` - Svelte
- `flutter` - Flutter mobile
- `react-native` - React Native mobile
## Implementation Steps by Framework
### React (SPA)
#### 1. Install Auth0 React SDK
```bash
npm install @auth0/auth0-react
```
#### 2. Wrap App with Auth0Provider
```typescript
// src/main.tsx
import { Auth0Provider } from '@auth0/auth0-react'
ReactDOM.createRoot(document.getElementById('root')!).render(
)
```
#### 3. Create Login/Logout Components
```typescript
// src/components/Auth.tsx
import { useAuth0 } from '@auth0/auth0-react'
export function LoginButton() {
const { loginWithRedirect, isAuthenticated } = useAuth0()
if (isAuthenticated) return null
return
}
export function LogoutButton() {
const { logout, isAuthenticated } = useAuth0()
if (!isAuthenticated) return null
return
}
export function Profile() {
const { user, isAuthenticated } = useAuth0()
if (!isAuthenticated) return
Not logged in
return (
{user?.name}
{user?.email}
)
}
```
#### 4. Protected Routes
```typescript
// src/components/ProtectedRoute.tsx
import { useAuth0 } from '@auth0/auth0-react'
export function ProtectedRoute({ children }: any) {
const { isAuthenticated, isLoading } = useAuth0()
if (isLoading) return Loading...
if (!isAuthenticated) return Please log in
return children
}
// In App.tsx
} />
```
#### 5. Call Protected API
```typescript
// src/hooks/useApi.ts
import { useAuth0 } from '@auth0/auth0-react'
import { useEffect, useState } from 'react'
export function useApi(url: string) {
const { getAccessTokenSilently } = useAuth0()
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
let isMounted = true
const fetchData = async () => {
try {
const token = await getAccessTokenSilently()
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}` }
})
if (!response.ok) throw new Error('API error')
const result = await response.json()
if (isMounted) setData(result)
} catch (err) {
if (isMounted) setError(err instanceof Error ? err : new Error('Unknown error'))
} finally {
if (isMounted) setLoading(false)
}
}
fetchData()
return () => { isMounted = false }
}, [url, getAccessTokenSilently])
return { data, error, loading }
}
```
#### 6. Environment Variables
```env
VITE_AUTH0_DOMAIN=YOUR_DOMAIN.auth0.com
VITE_AUTH0_CLIENT_ID=YOUR_CLIENT_ID
```
---
### Next.js (Full-Stack)
#### 1. Install SDK
```bash
npm install @auth0/nextjs-auth0
```
#### 2. Create Auth Routes
**App Router** (Recommended):
```typescript
// app/api/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0'
export const GET = handleAuth()
```
**Pages Router**:
```typescript
// pages/api/auth/[auth0].ts
import { handleAuth } from '@auth0/nextjs-auth0'
export default handleAuth()
```
#### 3. Access User in Components
**App Router**:
```typescript
// app/profile/page.tsx
import { getSession } from '@auth0/nextjs-auth0'
import { redirect } from 'next/navigation'
export default async function ProfilePage() {
const session = await getSession()
if (!session) {
redirect('/api/auth/login')
}
return (
Welcome, {session.user.name}
)
}
```
#### 4. Login/Logout Links
```typescript
// app/components/Nav.tsx
import { getSession } from '@auth0/nextjs-auth0'
export async function Nav() {
const session = await getSession()
return (
)
}
```
#### 5. Call API with Token
```typescript
// app/api/items/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: 'Unauthorized' }, { status: 401 })
}
const response = await fetch('http://localhost:3001/items', {
headers: { Authorization: `Bearer ${session.accessToken}` }
})
return NextResponse.json(await response.json())
}
```
#### 6. Environment Variables
```env
AUTH0_SECRET='[generated secret]'
AUTH0_BASE_URL='http://localhost:3000'
AUTH0_ISSUER_BASE_URL='https://YOUR_DOMAIN.auth0.com'
AUTH0_CLIENT_ID='YOUR_CLIENT_ID'
AUTH0_CLIENT_SECRET='YOUR_CLIENT_SECRET'
```
---
### Node.js/Express Backend
#### 1. Install Dependencies
```bash
npm install express-jwt jwks-rsa
```
#### 2. Create JWT Middleware
```typescript
// middleware/auth.ts
import { expressjwt as jwt } from 'express-jwt'
import jwksRsa from 'jwks-rsa'
const checkJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,
jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`
}),
audience: `https://${process.env.AUTH0_DOMAIN}/api/v2/`,
issuer: `https://${process.env.AUTH0_DOMAIN}/`,
algorithms: ['RS256']
})
export default checkJwt
```
#### 3. Protect Routes
```typescript
// routes/items.ts
import express from 'express'
import checkJwt from '../middleware/auth'
const router = express.Router()
router.get('/public', (req, res) => {
res.json({ message: 'Public' })
})
router.get('/items', checkJwt, (req, res) => {
// req.auth contains decoded JWT
res.json({ userId: req.auth.sub, items: [] })
})
// Scope validation
router.delete('/items/:id', checkJwt, (req, res) => {
const scope = req.auth.scope?.split(' ') || []
if (!scope.includes('delete:items')) {
return res.status(403).json({ error: 'Insufficient permissions' })
}
res.json({ message: 'Item deleted' })
})
export default router
```
---
### FastAPI (Python)
```python
# main.py
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthCredentials
import jwt
from jwt import algorithms
app = FastAPI()
security = HTTPBearer()
DOMAIN = "YOUR_DOMAIN.auth0.com"
async def verify_token(credentials: HTTPAuthCredentials = Depends(security)):
token = credentials.credentials
try:
# Get public key
jwks_client = jwt.PyJWKClient(f"https://{DOMAIN}/.well-known/jwks.json")
signing_key = jwks_client.get_signing_key_from_jwt(token)
# Verify token
payload = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience=f"https://{DOMAIN}/api/v2/",
issuer=f"https://{DOMAIN}/"
)
return payload
except Exception as e:
raise HTTPException(status_code=401, detail="Invalid token")
@app.get("/items")
async def get_items(user: dict = Depends(verify_token)):
return { "user_id": user["sub"], "items": [] }
```
---
## Testing Implementation
### Test Login Flow
```bash
# 1. Visit login page
open http://localhost:3000/api/auth/login
# 2. Complete auth flow in Auth0
# 3. Check if callback works
# 4. Test API
curl -H "Authorization: Bearer " \
http://localhost:3001/api/items
```
### Inspect Token (React)
```javascript
// In browser console
const token = await auth0.getAccessTokenSilently()
console.log(token)
// Decode at jwt.io
```
---
## Common Issues & Solutions
| Issue | Solution |
|-------|----------|
| Token expired | SDK auto-refreshes, check refresh token rotation enabled |
| CORS error | Configure CORS in backend, check Auth0 allowed origins |
| Silent auth fails | Check `cacheLocation: "memory"`, try explicit login |
| Scope not in token | Add to Auth0 rule or API scopes config |
| Token validation fails | Verify audience, issuer, algorithms match |
---
## Next Steps
1. Test implementation with `/oauth-security-audit`
2. Run `/oauth-troubleshoot` for any issues
3. Deploy and update callback URLs to production domain
**Status**: Implementation guide ready!