Authentication & Authorization
Complete authentication system with multiple login methods, enterprise-grade RBAC, brute-force protection, and audit logs.
Email / Password Login
Traditional credentials-based authentication with a full registration flow:
- Registration — user signs up, receives a one-time verification code by email
- Email verification — OTP must be confirmed before the account is activated
- Password strength validation — configurable minimum strength (
weak/medium/strong) - Password reset — time-limited reset link sent to the registered email
- Rate limiting — brute-force protection via
LoginAttempttracking (15-minute lockout after N failures)
Configuration
# .env
NEXTAUTH_SECRET="your-secret-key" # openssl rand -base64 32
NEXTAUTH_URL="http://localhost:3000"Generate a secure secret with: openssl rand -base64 32
Usage
import { signIn } from 'next-auth/react'
await signIn('credentials', {
email: 'user@example.com',
password: 'password123',
redirectTo: '/dashboard',
})Password Strength
import { checkPasswordStrength } from '@/lib/utils/validators'
const strength = checkPasswordStrength('mypassword')
// Returns: 'weak' | 'medium' | 'strong'Configure the minimum required strength in src/config/site.ts:
export const siteConfig = {
auth: {
password: {
minStrength: 'medium', // 'weak' | 'medium' | 'strong'
},
},
}Google OAuth
One-click sign-in via NextAuth.js Google provider.
Setup
- Go to Google Cloud Console
- Create a project and enable the Google+ API
- Create OAuth 2.0 credentials (Web application)
- Add authorized redirect URI:
https://yourdomain.com/api/auth/callback/google
Configuration
# .env
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"Usage
import { signIn } from 'next-auth/react'
await signIn('google', { redirectTo: '/dashboard' })GitHub OAuth
One-click sign-in via NextAuth.js GitHub provider — ideal for developer-focused products.
Setup
- Go to GitHub Developer Settings
- Click New OAuth App
- Set the callback URL:
https://yourdomain.com/api/auth/callback/github
Configuration
# .env
GITHUB_ID="your-github-client-id"
GITHUB_SECRET="your-github-client-secret"Usage
import { signIn } from 'next-auth/react'
await signIn('github', { redirectTo: '/dashboard' })Admin RBAC
Enterprise-grade role-based access control for the admin panel.
Concepts
| Concept | Description |
|---|---|
| Permission | A single capability, e.g. post:create |
| Role | A named group of permissions, e.g. Editor |
| AdminUser | An admin account that can hold multiple roles |
| Superuser | Bypasses all permission checks |
Protect API Routes
import { requireAdminAuth } from '@/lib/admin'
import { PERMISSIONS } from '@/config/permissions'
export async function POST(req: NextRequest) {
const { adminUserId, error } = await requireAdminAuth(
req,
PERMISSIONS.ADMIN_USER_CREATE
)
if (error) return error
// Your logic here
}Check Permissions in Components
import { useAdminAuth } from '@/components/providers/AdminAuthProvider'
import { PERMISSIONS } from '@/config/permissions'
export function CreatePostButton() {
const { hasPermission } = useAdminAuth()
if (!hasPermission(PERMISSIONS.POST_CREATE)) return null
return <Button>New Post</Button>
}Available Permissions
All permission constants live in src/config/permissions.ts:
| Group | Constants |
|---|---|
| Admin users | ADMIN_USER_VIEW, ADMIN_USER_CREATE, ADMIN_USER_EDIT, ADMIN_USER_DELETE |
| Roles | ADMIN_ROLE_VIEW, ADMIN_ROLE_CREATE, ADMIN_ROLE_EDIT, ADMIN_ROLE_DELETE |
| Content | POST_VIEW, POST_CREATE, POST_EDIT, POST_DELETE |
| Products | PRODUCT_VIEW, PRODUCT_CREATE, PRODUCT_EDIT, PRODUCT_DELETE |
| Orders | ORDER_VIEW, ORDER_EDIT |
| Members | MEMBER_VIEW, MEMBER_EDIT |
Superusers (isSuperuser: true) automatically pass every permission check — no need to assign roles to them.
Create Custom Permissions
Custom permissions follow the resource:action pattern and can be created directly in the Admin Panel under Roles & Permissions → Permissions. No code change required.
Login Rate Limiting
Brute-force protection is built in via the LoginAttempt model in Prisma.
// src/config/site.ts
export const siteConfig = {
auth: {
loginLimits: {
enabled: true,
maxAttempts: 10, // failed attempts before lockout
windowMinutes: 15, // lockout duration
},
},
}When maxAttempts is exceeded the account is locked for windowMinutes minutes. The lockout is tracked per email address and IP address combination.
Audit Logs
Every significant admin action is recorded in the AuditLog table with:
action— constant fromAUDIT_ACTIONS(e.g.ADMIN_USER_CREATE)resource/resourceId— what was changeddetails— key field values (passwords and secrets are never stored)ipAddress&userAgent— for forensic tracing
import { logAudit } from '@/lib/audit/service'
import { AUDIT_ACTIONS } from '@/lib/audit/constants'
await logAudit({
adminUserId,
action: AUDIT_ACTIONS.ADMIN_USER_CREATE,
resource: 'AdminUser',
resourceId: newUser.id,
details: { username: newUser.username, email: newUser.email },
ipAddress: req.headers.get('x-forwarded-for') ?? 'unknown',
userAgent: req.headers.get('user-agent') ?? 'unknown',
})Audit logs are viewable in Admin Panel → Audit Logs with filtering by action, resource, and date range.
Session Management
Server-side
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth/options'
export async function GET() {
const session = await getServerSession(authOptions)
if (!session) return new Response('Unauthorized', { status: 401 })
return Response.json({ user: session.user })
}Client-side
import { useSession } from 'next-auth/react'
export function UserGreeting() {
const { data: session, status } = useSession()
if (status === 'loading') return <Spinner />
if (status === 'unauthenticated') return <LoginButton />
return <p>Welcome, {session.user.name}</p>
}Next Steps
- Admin Panel — manage admin users, roles, and permissions from the UI
- Email — configure verification code and password reset emails
- Payments — gate features behind paid plans
Overview
Explore TikShip's complete feature set — authentication, payments, CMS, admin panel, email, database, i18n, UI, file upload, and SEO.
Payments
Dual payment provider integration with Stripe and PayPal — one-time payments, subscriptions, webhook auto-sync, guest checkout, and automated email notifications.