Skip to main content

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