Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ouim.me/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The verifyNextAuth function is designed specifically for Next.js App Router, providing authentication verification for middleware and API routes with Next.js-specific request handling.

Signature

async function verifyNextAuth(
  request: NextRequest,
  options: VerifyAuthOptions
): Promise<
  | { success: true; auth: AuthContext }
  | { success: false; error: string; auth?: AuthContext }
>

Parameters

request
NextRequest
required
Next.js request object from middleware or API routes
options
VerifyAuthOptions
required
Configuration options for token verification

Returns

result
Promise<VerifyAuthResult>
Promise that resolves to a result object indicating success or failureSuccess Response:Failure Response:

AuthContext Properties

Examples

Middleware Protection

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function middleware(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!
  })

  if (!result.success) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  // User is authenticated, continue
  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/protected/:path*']
}

API Route Protection

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function GET(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!
  })

  if (!result.success) {
    return NextResponse.json(
      { error: result.error },
      { status: 401 }
    )
  }

  // Access authenticated user
  const userId = result.auth.userId

  return NextResponse.json({
    message: 'Success',
    userId
  })
}

With Guest Support

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function GET(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!,
    allowGuest: true
  })

  if (!result.success) {
    // Guest user
    return NextResponse.json({
      message: 'Limited content for guests',
      guestId: result.auth?.guestId
    })
  }

  // Authenticated user
  return NextResponse.json({
    message: 'Full content',
    userId: result.auth.userId
  })
}

Middleware with Guest Support

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function middleware(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!,
    allowGuest: true
  })

  // Add auth context to request headers for use in app
  const requestHeaders = new Headers(request.headers)
  
  if (result.success) {
    requestHeaders.set('x-user-id', result.auth.userId || '')
    requestHeaders.set('x-is-authenticated', 'true')
  } else if (result.auth?.isGuest) {
    requestHeaders.set('x-guest-id', result.auth.guestId || '')
    requestHeaders.set('x-is-authenticated', 'false')
  }

  return NextResponse.next({
    request: {
      headers: requestHeaders
    }
  })
}

Role-Based Access Control

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function middleware(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!,
    requiredScope: 'admin:write'
  })

  if (!result.success) {
    return NextResponse.json(
      { error: 'Admin access required' },
      { status: 403 }
    )
  }

  return NextResponse.next()
}

export const config = {
  matcher: '/admin/:path*'
}

Custom Error Handling

import { NextRequest, NextResponse } from 'next/server'
import { verifyNextAuth } from '@ouim/logto-authkit/server'

export async function GET(request: NextRequest) {
  const result = await verifyNextAuth(request, {
    logtoUrl: process.env.LOGTO_URL!,
    audience: process.env.LOGTO_AUDIENCE!
  })

  if (!result.success) {
    // Detailed error handling
    const statusCode = result.error.includes('expired') ? 401 : 403
    
    return NextResponse.json(
      {
        error: 'Authentication failed',
        details: result.error,
        timestamp: new Date().toISOString()
      },
      { status: statusCode }
    )
  }

  return NextResponse.json({
    userId: result.auth.userId,
    scopes: result.auth.payload?.scope
  })
}

Extracting User Info in Server Component

// app/dashboard/page.tsx
import { cookies, headers } from 'next/headers'
import { verifyAuth } from '@ouim/logto-authkit/server'

export default async function DashboardPage() {
  const cookieStore = cookies()
  const headersList = headers()

  const auth = await verifyAuth(
    {
      cookies: Object.fromEntries(cookieStore.getAll().map(c => [c.name, c.value])),
      headers: Object.fromEntries(headersList.entries())
    },
    {
      logtoUrl: process.env.LOGTO_URL!,
      audience: process.env.LOGTO_AUDIENCE!
    }
  )

  return (
    <div>
      <h1>Dashboard</h1>
      <p>User ID: {auth.userId}</p>
    </div>
  )
}

Token Extraction Order

The function extracts tokens in this order:
  1. Cookie (using cookieName option, defaults to logto_authtoken)
  2. Authorization header (Bearer token)

Response Patterns

Authenticated User

{
  success: true,
  auth: {
    userId: 'user-123',
    isAuthenticated: true,
    payload: { sub: 'user-123', scope: 'profile email' },
    isGuest: false
  }
}

Guest User (when allowGuest: true)

{
  success: false,
  error: 'No authentication token found',
  auth: {
    userId: null,
    isAuthenticated: false,
    payload: null,
    isGuest: true,
    guestId: 'a1b2c3d4-e5f6-4g7h-8i9j-0k1l2m3n4o5p'
  }
}

Failed Authentication (when allowGuest: false)

{
  success: false,
  error: 'No token found in cookies or Authorization header'
}

See Also