diff --git a/src/authkit-callback-route.spec.ts b/src/authkit-callback-route.spec.ts index 665fc42..aae887b 100644 --- a/src/authkit-callback-route.spec.ts +++ b/src/authkit-callback-route.spec.ts @@ -276,6 +276,22 @@ describe('authkit-callback-route', () => { expect(session?.accessToken).toBe(newAccessToken); }); + it('should allow onSuccess redirect using NextResponse', async () => { + jest.mocked(workos.userManagement.authenticateWithCode).mockResolvedValue(mockAuthResponse); + + // Set up request with code + request.nextUrl.searchParams.set('code', 'test-code'); + + const handler = handleAuth({ + onSuccess: async (data) => { + return NextResponse.redirect('https://example.com/dashboard'); + }, + }); + + const response = await handler(request); + expect(response.headers.get('Location')).toBe('https://example.com/dashboard'); + }); + it('should pass custom state data to onSuccess callback', async () => { jest.mocked(workos.userManagement.authenticateWithCode).mockResolvedValue(mockAuthResponse); diff --git a/src/authkit-callback-route.ts b/src/authkit-callback-route.ts index e826a9f..8c2a7d4 100644 --- a/src/authkit-callback-route.ts +++ b/src/authkit-callback-route.ts @@ -96,7 +96,7 @@ export function handleAuth(options: HandleAuthOptions = {}) { await saveSession({ accessToken, refreshToken, user, impersonator }, request); if (onSuccess) { - await onSuccess({ + const onSuccessResponse = await onSuccess({ accessToken, refreshToken, user, @@ -106,6 +106,10 @@ export function handleAuth(options: HandleAuthOptions = {}) { organizationId, state: customState, }); + + if (onSuccessResponse) { + return onSuccessResponse; + } } return response; diff --git a/src/interfaces.ts b/src/interfaces.ts index d3f6ecd..197d51e 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -1,10 +1,10 @@ import type { AuthenticationResponse, OauthTokens, User } from '@workos-inc/node'; -import { type NextRequest } from 'next/server'; +import { NextResponse, type NextRequest } from 'next/server'; export interface HandleAuthOptions { returnPathname?: string; baseURL?: string; - onSuccess?: (data: HandleAuthSuccessData) => void | Promise; + onSuccess?: (data: HandleAuthSuccessData) => void | Promise | Promise; onError?: (params: { error?: unknown; request: NextRequest }) => Response | Promise; }