Skip to content

Commit a0fb119

Browse files
authored
Add onError callback for customizing error handling in handleAuth (#193)
* add optional resolveErrorResponse resolver for callback error messages * update README to describe the resolveErrorResponse option * swap to onError handler for custsom error handling * format README
1 parent 2f6a2c7 commit a0fb119

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export const GET = handleAUth({
9797
| `returnPathname` | `/` | The pathname to redirect the user to after signing in |
9898
| `baseURL` | `undefined` | The base URL to use for the redirect URI instead of the one in the request. Useful if the app is being run in a container like docker where the hostname can be different from the one in the request |
9999
| `onSuccess` | `undefined` | A function that receives successful authentication data and can be used for side-effects like persisting tokens |
100+
| `onError` | `undefined` | A function that can receive the error and the request and handle the error in its own way. |
100101

101102
### Middleware
102103

__tests__/authkit-callback-route.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,26 @@ describe('authkit-callback-route', () => {
107107
expect(data.error.message).toBe('Something went wrong');
108108
});
109109

110+
it('should handle authentication failure with custom onError handler', async () => {
111+
// Mock authentication failure
112+
jest.mocked(workos.userManagement.authenticateWithCode).mockRejectedValue('Auth failed');
113+
request.nextUrl.searchParams.set('code', 'invalid-code');
114+
115+
const handler = handleAuth({
116+
onError: ({ error }) => {
117+
return new Response(JSON.stringify({ error: { message: 'Custom error' } }), {
118+
status: 500,
119+
headers: { 'Content-Type': 'application/json' },
120+
});
121+
},
122+
});
123+
const response = await handler(request);
124+
125+
expect(response.status).toBe(500);
126+
const data = await response.json();
127+
expect(data.error.message).toBe('Custom error');
128+
});
129+
110130
it('should handle missing code parameter', async () => {
111131
const handler = handleAuth();
112132
const response = await handler(request);

src/authkit-callback-route.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { NextRequest } from 'next/server';
21
import { cookies } from 'next/headers';
3-
import { workos } from './workos.js';
2+
import { NextRequest } from 'next/server';
3+
import { getCookieOptions } from './cookie.js';
44
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_NAME } from './env-variables.js';
5+
import { HandleAuthOptions } from './interfaces.js';
56
import { encryptSession } from './session.js';
67
import { errorResponseWithFallback, redirectWithFallback } from './utils.js';
7-
import { getCookieOptions } from './cookie.js';
8-
import { HandleAuthOptions } from './interfaces.js';
8+
import { workos } from './workos.js';
99

1010
export function handleAuth(options: HandleAuthOptions = {}) {
11-
const { returnPathname: returnPathnameOption = '/', baseURL, onSuccess } = options;
11+
const { returnPathname: returnPathnameOption = '/', baseURL, onSuccess, onError } = options;
1212

1313
// Throw early if baseURL is provided but invalid
1414
if (baseURL) {
@@ -83,14 +83,18 @@ export function handleAuth(options: HandleAuthOptions = {}) {
8383

8484
console.error(errorRes);
8585

86-
return errorResponse();
86+
return errorResponse(request, error);
8787
}
8888
}
8989

90-
return errorResponse();
90+
return errorResponse(request);
9191
};
9292

93-
function errorResponse() {
93+
function errorResponse(request: NextRequest, error?: unknown) {
94+
if (onError) {
95+
return onError({ error, request });
96+
}
97+
9498
return errorResponseWithFallback({
9599
error: {
96100
message: 'Something went wrong',

src/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { OauthTokens, User } from '@workos-inc/node';
2+
import { type NextRequest } from 'next/server';
23

34
export interface HandleAuthOptions {
45
returnPathname?: string;
56
baseURL?: string;
67
onSuccess?: (data: HandleAuthSuccessData) => void | Promise<void>;
8+
onError?: (params: { error?: unknown; request: NextRequest }) => Response | Promise<Response>;
79
}
810

911
export interface HandleAuthSuccessData extends Session {

0 commit comments

Comments
 (0)