Skip to content

Conversation

@abedshaaban
Copy link

@abedshaaban abedshaaban commented Dec 19, 2025

This feature introduces a main change:

  • improved authkitMiddleware to be able to merge multiple middlewares in Nextjs and be able to modify them.

Usage examples:

For middlewares

import { authkitMiddleware } from '@workos-inc/authkit-nextjs'

export default authkitMiddleware(async (auth, request, event) => {
  const session = await auth()
  
  if (isProtectedRoute(request) && !session.user) {
    // Handle protection logic
  }
  
  // Chain with other middleware (e.g., i18n)
  return handleI18nRouting(request)
})

@abedshaaban abedshaaban requested a review from a team as a code owner December 19, 2025 19:16
@abedshaaban abedshaaban changed the title feat: enhance onSuccess callback to support redirect responses in handleAuth function feat: enhance onSuccess callback and middleware request Dec 19, 2025
@abedshaaban abedshaaban marked this pull request as draft December 19, 2025 19:17
@abedshaaban abedshaaban marked this pull request as ready for review December 20, 2025 10:54
@nicknisi
Copy link
Member

Hey @abedshaaban thanks for this! I have a couple of questions.

onSuccess changes

Forcing onSuccess to return a Response really overloads this callback. Its initial intent was to allow for reacting to successful authentication as a side-effect hook - returning void is by design. Changing that would be a breaking change for existing users.

Is there something you can't accomplish without this? For example, with the current API you can:

  • Log or track auth events: onSuccess: (data) => analytics.track('login', data.user)
  • Store additional data: onSuccess: async (data) => await db.users.updateLastLogin(data.user.id)
  • Modify the session: onSuccess: async (data) => await saveSession({ ...data, customField: 'value' }, request)

If you need dynamic redirects based on user data, that could be solved by making returnPathname accept a callback, or handling the routing logic on the destination page. What's the specific use case you're trying to solve?

Composable middleware

We actually have this already! See the Composing middleware section of the README. However, I agree it's a bit complicated - I opened #348 to simplify this with helpers that ensure headers are merged correctly.

@abedshaaban
Copy link
Author

Thank you @nicknisi for your feedback. Making returnPathname a callback or a string is a great suggestion for not modifying the response and introducing breaking changes.

For the middleware I am trying to combine next-intl with workos. It works locally but breaks on Netlify and returns in the logs "You are calling 'withAuth' on a route that isn't covered by the AuthKit middleware."

import { NextRequest } from 'next/server'
import { defaultLocale, locales } from '@repo/constants/internationalization'
import { authkit } from '@workos-inc/authkit-nextjs'
import createNextIntlMiddleware from 'next-intl/middleware'

const i18nMiddleware = createNextIntlMiddleware({
  locales,
  defaultLocale
})

export async function middleware(request: NextRequest) {
  // Run the i18n middleware first
  const intlResponse = i18nMiddleware(request)

  // Run AuthKit middleware
  const { headers: authkitHeaders } = await authkit(request)

  // Copy Set-Cookie and cache control headers to the response, but exclude the internal
  // x-workos-session header which contains encrypted session data and should never appear
  // in HTTP responses (it's only used to pass session data between middleware and page handlers)
  for (const [key, value] of authkitHeaders) {
    if (key.toLowerCase() === 'x-workos-session') {
      continue // Internal header - must not leak to response
    }
    if (key.toLowerCase() === 'set-cookie') {
      intlResponse.headers.append(key, value)
    } else {
      intlResponse.headers.set(key, value)
    }
  }

  return intlResponse
}

…and adjust handleAuth function to align with new type
@nicknisi
Copy link
Member

Ah, interesting! And the fixes in this PR get it working on Netlify? I need to look into this.

@abedshaaban
Copy link
Author

Not 100% sure but I tried to implement it as clerk does in their middleware to combine middlewares.

@abedshaaban abedshaaban marked this pull request as draft December 24, 2025 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants