Skip to content

Need official pattern to compose AuthKit with other middleware that forwards request headers (e.g., next-intl) #361

@dpkass

Description

@dpkass

Summary

When using @workos-inc/authkit-nextjs alongside other middleware like next-intl in Next.js Edge proxy, there's no documented way to forward AuthKit's internal request headers (x-workos-middleware, x-workos-session, etc.) if another middleware creates the final NextResponse. The applyResponseHeaders helper only merges response headers (e.g., set-cookie), but AuthKit also needs to forward request headers to downstream handlers for withAuth and internal logic to work correctly.

Problem

The current composable middleware helpers (partitionAuthkitHeaders, applyResponseHeaders) don't cover the case where you need to merge AuthKit's forwarded request headers into a NextResponse that was created by another middleware.

const { headers: authkitHeaders } = await authkit(request);
const { requestHeaders, responseHeaders } = partitionAuthkitHeaders(request, authkitHeaders);

const intlResponse = intlMiddleware(request); // returns NextResponse.next({ request: { headers } })

// This only merges response headers; AuthKit requestHeaders are not forwarded
return applyResponseHeaders(intlResponse, responseHeaders);

Result: Downstream server components and withAuth don't see x-workos-middleware, x-workos-session, etc., so they behave as if AuthKit middleware wasn't applied, even though cookies are set correctly.

Current Workaround

Mutate request.headers directly before passing to next-intl, then apply response headers normally:

const { session, headers: authkitHeaders } = await authkit(request);
const { requestHeaders, responseHeaders } = partitionAuthkitHeaders(
  request,
  authkitHeaders,
);

// HACK: Mutate request.headers directly (not officially supported)
for (const [name, value] of requestHeaders) {
  request.headers.set(name, value);
}

const intlResponse = intlMiddleware(request);

// Apply AuthKit response headers
return applyResponseHeaders(intlResponse, responseHeaders);

This works because next-intl clones request.headers when creating its NextResponse.next({ request: { headers } }), so AuthKit's internal headers get included in the forwarded request.

Why This Is Problematic

  • Mutating request.headers is not documented or guaranteed to work across Next.js versions or runtimes.
  • It relies on implementation details of how next-intl (and Next.js) clones headers.
  • It's conceptually wrong: request headers should be forwarded via NextResponse.next({ request: { headers } }), not by mutating the incoming request object.

Request

Please provide either:

  1. An official composition helper that preserves another middleware's response while forwarding AuthKit request headers:
const { requestHeaders, responseHeaders } = partitionAuthkitHeaders(request, authkitHeaders);
const intlResponse = intlMiddleware(request);

// New helper: merges requestHeaders into intlResponse's forwarded request headers
return mergeAuthkitIntoResponse(request, requestHeaders, responseHeaders, intlResponse);
  1. Or, update the composable middleware documentation with a clear, future-proof pattern showing how to manually merge forwarded request headers when combining with other middleware that also uses NextResponse.next({ request: { headers } }).

The core challenge is that Next.js doesn't expose a stable API to read/merge forwarded request headers from an existing NextResponse (they're encoded in internal x-middleware-* headers), making composition tricky without library support.


Edit: Found a better workaround

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions