NextAuth.js Authentication
Overviewβ
The /api/auth/[...nextauth]
endpoint handles all authentication flows for Ring Platform using NextAuth.js v5. This endpoint manages multiple authentication providers including Google OAuth, Apple ID, MetaMask/Web3 wallets, and traditional credentials.
Authentication Providersβ
Google OAuthβ
- Provider: Google
- Scopes:
openid
,email
,profile
- Auto-registration: Enabled for new users
Apple IDβ
- Provider: Apple
- Scopes:
name
,email
- Privacy: Supports private relay emails
MetaMask/Web3β
- Provider: Credentials (Web3)
- Method: Signature verification
- Wallet: Automatic wallet creation on first login
Email/Passwordβ
- Provider: Credentials
- Validation: Email format and password strength
- Security: Bcrypt hashing with salt rounds
Endpointsβ
Sign Inβ
POST /api/auth/signin
Request Body:
{
"email": "user@example.com",
"password": "securePassword123",
"callbackUrl": "/dashboard"
}
Response:
{
"url": "https://ring.ck.ua/dashboard",
"ok": true
}
Sign Outβ
POST /api/auth/signout
Response:
{
"url": "https://ring.ck.ua/",
"ok": true
}
Sessionβ
GET /api/auth/session
Response:
{
"user": {
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"image": "https://example.com/avatar.jpg",
"role": "member"
},
"expires": "2024-12-31T23:59:59.999Z"
}
CSRF Tokenβ
GET /api/auth/csrf
Response:
{
"csrfToken": "abc123def456ghi789"
}
Authentication Flowβ
1. OAuth Flow (Google/Apple)β
2. Web3 Flow (MetaMask)β
Code Examplesβ
JavaScript/TypeScriptβ
import { signIn, signOut, useSession } from 'next-auth/react'
// Sign in with Google
await signIn('google', { callbackUrl: '/dashboard' })
// Sign in with credentials
await signIn('credentials', {
email: 'user@example.com',
password: 'password123',
callbackUrl: '/dashboard'
})
// Sign out
await signOut({ callbackUrl: '/' })
// Get session
const { data: session, status } = useSession()
cURL Examplesβ
# Get CSRF token
curl -X GET "https://ring.ck.ua/api/auth/csrf" \
-H "Accept: application/json"
# Sign in with credentials
curl -X POST "https://ring.ck.ua/api/auth/callback/credentials" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=user@example.com&password=password123&csrfToken=abc123"
# Get current session
curl -X GET "https://ring.ck.ua/api/auth/session" \
-H "Cookie: next-auth.session-token=your-session-token"
Error Handlingβ
Common Error Codesβ
Code | Message | Description |
---|---|---|
CredentialsSignin | Invalid credentials | Email/password combination is incorrect |
OAuthAccountNotLinked | Account linking required | Email already exists with different provider |
EmailCreateAccount | Account creation failed | Error creating new user account |
Callback | Callback error | OAuth callback processing failed |
OAuthCallback | OAuth error | Provider-specific OAuth error |
Error Response Formatβ
{
"error": "CredentialsSignin",
"message": "Invalid email or password",
"status": 401
}
Security Featuresβ
CSRF Protectionβ
- Automatic CSRF token generation
- Token validation on all state-changing requests
- Secure token storage in HTTP-only cookies
Session Securityβ
- JWT tokens with RS256 signing
- Secure HTTP-only session cookies
- Automatic session rotation
- Configurable session expiry (30 days default)
Rate Limitingβ
- 5 failed login attempts per IP per 15 minutes
- 10 successful logins per IP per minute
- Progressive backoff for repeated failures
Configurationβ
Environment Variablesβ
NEXTAUTH_URL=https://ring.ck.ua
NEXTAUTH_SECRET=your-secret-key
# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Apple ID
APPLE_ID=your-apple-id
APPLE_TEAM_ID=your-apple-team-id
APPLE_PRIVATE_KEY=your-apple-private-key
APPLE_KEY_ID=your-apple-key-id
# Firebase
FIREBASE_PROJECT_ID=your-firebase-project
FIREBASE_CLIENT_EMAIL=your-firebase-client-email
FIREBASE_PRIVATE_KEY=your-firebase-private-key
Related Endpointsβ
/api/auth/crypto/generateNonce
- Web3 nonce generation/api/profile
- User profile management/api/set-user-role
- Role assignment
Testingβ
Test Accountsβ
// Development test accounts
const testAccounts = {
admin: { email: 'admin@ring.ck.ua', password: 'admin123' },
member: { email: 'member@ring.ck.ua', password: 'member123' },
subscriber: { email: 'subscriber@ring.ck.ua', password: 'subscriber123' }
}
Integration Testsβ
describe('Authentication API', () => {
test('should authenticate with valid credentials', async () => {
const response = await signIn('credentials', {
email: 'test@example.com',
password: 'password123',
redirect: false
})
expect(response?.ok).toBe(true)
expect(response?.error).toBeNull()
})
test('should reject invalid credentials', async () => {
const response = await signIn('credentials', {
email: 'test@example.com',
password: 'wrongpassword',
redirect: false
})
expect(response?.ok).toBe(false)
expect(response?.error).toBe('CredentialsSignin')
})
})
Troubleshootingβ
Common Issuesβ
Issue: "CSRF token mismatch" Solution: Ensure CSRF token is included in requests and matches server-generated token
Issue: "OAuth account not linked" Solution: User needs to sign in with original provider or link accounts manually
Issue: "Session not found" Solution: Check cookie settings and ensure session hasn't expired
Issue: "MetaMask connection failed" Solution: Verify MetaMask is installed and user has approved connection
Debug Modeβ
// Enable debug logging
export default NextAuth({
debug: process.env.NODE_ENV === 'development',
logger: {
error(code, metadata) {
console.error('NextAuth Error:', code, metadata)
},
warn(code) {
console.warn('NextAuth Warning:', code)
},
debug(code, metadata) {
console.debug('NextAuth Debug:', code, metadata)
}
}
})