Docs
Features

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 LoginAttempt tracking (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

  1. Go to Google Cloud Console
  2. Create a project and enable the Google+ API
  3. Create OAuth 2.0 credentials (Web application)
  4. 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

  1. Go to GitHub Developer Settings
  2. Click New OAuth App
  3. 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

ConceptDescription
PermissionA single capability, e.g. post:create
RoleA named group of permissions, e.g. Editor
AdminUserAn admin account that can hold multiple roles
SuperuserBypasses 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:

GroupConstants
Admin usersADMIN_USER_VIEW, ADMIN_USER_CREATE, ADMIN_USER_EDIT, ADMIN_USER_DELETE
RolesADMIN_ROLE_VIEW, ADMIN_ROLE_CREATE, ADMIN_ROLE_EDIT, ADMIN_ROLE_DELETE
ContentPOST_VIEW, POST_CREATE, POST_EDIT, POST_DELETE
ProductsPRODUCT_VIEW, PRODUCT_CREATE, PRODUCT_EDIT, PRODUCT_DELETE
OrdersORDER_VIEW, ORDER_EDIT
MembersMEMBER_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 from AUDIT_ACTIONS (e.g. ADMIN_USER_CREATE)
  • resource / resourceId — what was changed
  • details — 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
Authentication & Authorization | Tikship