-
Notifications
You must be signed in to change notification settings - Fork 50
feat: add composable proxy/middleware helpers #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
50149a9 to
1a9b2bb
Compare
The manual header-handling example was superseded by the handleAuthkitHeaders helper documented earlier in Setup.
| export default async function proxy(request: NextRequest) { | ||
| // For Next.js ≤15, use: export default async function middleware(request: NextRequest) { | ||
| // Get session, headers, and the WorkOS authorization URL for sign-in redirects | ||
| const { session, headers, authorizationUrl } = await authkit(request); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a silly question!
I'm looking at Vercel's example for setting headers in a proxy. The general shape of proxies seems to be do some stuff and then return a Response or NextResponse. It feels like we're hiding that a bit here with handleAuthkitHandlers.
What's preventing us from having authkit return headers that we can use directly in a more conventional-looking proxy? I'm sure this is missing something, but at a high level I'm thinking something more like...
export default async function proxy(request: NextRequest) {
const {
session,
requestHeaders,
responseHeaders,
authorizationUrl
} = await authkit(request);
const { pathname } = request.nextUrl;
// Redirect unauthenticated users on protected routes
if (pathname.startsWith('/app') && !session.user && authorizationUrl) {
return NextResponse.redirect(authorizationUrl)
}
return NextResponse.next({ request: { headers: requestHeaders} }, headers: responseHeaders })
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a silly question at all!
You can do exactly what you're describing! We export the primitives:
import { authkit, partitionAuthkitHeaders, applyResponseHeaders } from '@workos-inc/authkit-nextjs';
export default async function proxy(request: NextRequest) {
const { session, headers, authorizationUrl } = await authkit(request);
const { requestHeaders, responseHeaders } = partitionAuthkitHeaders(request, headers);
if (!session.user && authorizationUrl) {
return applyResponseHeaders(NextResponse.redirect(authorizationUrl), responseHeaders);
}
return applyResponseHeaders(
NextResponse.next({ request: { headers: requestHeaders } }),
responseHeaders
);
}handleAuthkitHeaders() is just a convenience wrapper around this pattern.
As for why authkit() doesn't return requestHeaders/responseHeaders directly - it already returns headers and changing that would be a breaking change. We could add them alongside headers and deprecate, but that felt like more complexity than the helper approach.
The reason applyResponseHeaders() exists at all is Set-Cookie handling - you need append() not set(), otherwise only the last cookie survives. Easy footgun.
Should we update the README to show both approaches? Happy to make handleAuthkitHeaders feel less like a black box.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation! Good to know about the Set-Cookie footgun. I think the README is good as-is. Just wanted a gut check on whether this approach would feel at least somewhat familiar to folks used to writing Next.js proxies.
| export default async function proxy(request: NextRequest) { | ||
| // For Next.js ≤15, use: export default async function middleware(request: NextRequest) { | ||
| // Get session, headers, and the WorkOS authorization URL for sign-in redirects | ||
| const { session, headers, authorizationUrl } = await authkit(request); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation! Good to know about the Set-Cookie footgun. I think the README is good as-is. Just wanted a gut check on whether this approach would feel at least somewhat familiar to folks used to writing Next.js proxies.
Summary
handleAuthkitHeaders(),partitionAuthkitHeaders(), andapplyResponseHeaders()helpers for composing custom proxy/middleware with AuthKitsession.tsto use new helpers internally (dogfooding)Why
authkitMiddleware()is opaque. Users could not inject custom logic (rate limiting, redirects, A/B testing) while preserving AuthKit's session handling. This caused:NextResponsex-workos-session) leaked to browserSet-Cookierequiresappend(), notset())Cache-Control: no-storewhen cookies presentUsage