Skip to main content

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​

CodeMessageDescription
CredentialsSigninInvalid credentialsEmail/password combination is incorrect
OAuthAccountNotLinkedAccount linking requiredEmail already exists with different provider
EmailCreateAccountAccount creation failedError creating new user account
CallbackCallback errorOAuth callback processing failed
OAuthCallbackOAuth errorProvider-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

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)
}
}
})