Skip to content
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

Add onError callback for customizing error handling in handleAuth #193

Merged
merged 4 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const GET = handleAUth({
| `returnPathname` | `/` | The pathname to redirect the user to after signing in |
| `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 |
| `onSuccess` | `undefined` | A function that receives successful authentication data and can be used for side-effects like persisting tokens |
| `onError` | `undefined` | A function that can receive the error and the request and handle the error in its own way. |

### Middleware

Expand Down
20 changes: 20 additions & 0 deletions __tests__/authkit-callback-route.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@ describe('authkit-callback-route', () => {
expect(data.error.message).toBe('Something went wrong');
});

it('should handle authentication failure with custom onError handler', async () => {
// Mock authentication failure
jest.mocked(workos.userManagement.authenticateWithCode).mockRejectedValue('Auth failed');
request.nextUrl.searchParams.set('code', 'invalid-code');

const handler = handleAuth({
onError: ({ error }) => {
return new Response(JSON.stringify({ error: { message: 'Custom error' } }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
},
});
const response = await handler(request);

expect(response.status).toBe(500);
const data = await response.json();
expect(data.error.message).toBe('Custom error');
});

it('should handle missing code parameter', async () => {
const handler = handleAuth();
const response = await handler(request);
Expand Down
20 changes: 12 additions & 8 deletions src/authkit-callback-route.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { NextRequest } from 'next/server';
import { cookies } from 'next/headers';
import { workos } from './workos.js';
import { NextRequest } from 'next/server';
import { getCookieOptions } from './cookie.js';
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_NAME } from './env-variables.js';
import { HandleAuthOptions } from './interfaces.js';
import { encryptSession } from './session.js';
import { errorResponseWithFallback, redirectWithFallback } from './utils.js';
import { getCookieOptions } from './cookie.js';
import { HandleAuthOptions } from './interfaces.js';
import { workos } from './workos.js';

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

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

console.error(errorRes);

return errorResponse();
return errorResponse(request, error);
}
}

return errorResponse();
return errorResponse(request);
};

function errorResponse() {
function errorResponse(request: NextRequest, error?: unknown) {
if (onError) {
return onError({ error, request });
}

return errorResponseWithFallback({
error: {
message: 'Something went wrong',
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { OauthTokens, User } from '@workos-inc/node';
import { type NextRequest } from 'next/server';

export interface HandleAuthOptions {
returnPathname?: string;
baseURL?: string;
onSuccess?: (data: HandleAuthSuccessData) => void | Promise<void>;
onError?: (params: { error?: unknown; request: NextRequest }) => Response | Promise<Response>;
}

export interface HandleAuthSuccessData extends Session {
Expand Down