From 311f892a6c6abca1ac7d050cab641a165c1c3f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Xalambr=C3=AD?= Date: Fri, 25 Nov 2022 11:32:21 -0500 Subject: [PATCH] Keep original error in AuthorizationError#cause (#204) --- src/error.ts | 6 +++++- src/strategy.ts | 5 +++-- test/authenticator.test.ts | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/error.ts b/src/error.ts index 4c54758..4d11dd2 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1 +1,5 @@ -export class AuthorizationError extends Error {} +export class AuthorizationError extends Error { + constructor(message?: string, public cause?: Error) { + super(message); + } +} diff --git a/src/strategy.ts b/src/strategy.ts index 4b6ffa7..9ff9c1f 100644 --- a/src/strategy.ts +++ b/src/strategy.ts @@ -117,11 +117,12 @@ export abstract class Strategy { message: string, request: Request, sessionStorage: SessionStorage, - options: AuthenticateOptions + options: AuthenticateOptions, + cause?: Error ): Promise { // if a failureRedirect is not set, we throw a 401 Response or an error if (!options.failureRedirect) { - if (options.throwOnError) throw new AuthorizationError(message); + if (options.throwOnError) throw new AuthorizationError(message, cause); throw json<{ message: string }>({ message }, 401); } diff --git a/test/authenticator.test.ts b/test/authenticator.test.ts index 953619b..e38025d 100644 --- a/test/authenticator.test.ts +++ b/test/authenticator.test.ts @@ -3,7 +3,12 @@ import { redirect, SessionStorage, } from "@remix-run/server-runtime"; -import { AuthenticateOptions, Authenticator, Strategy } from "../src"; +import { + AuthenticateOptions, + Authenticator, + AuthorizationError, + Strategy, +} from "../src"; class MockStrategy extends Strategy> { name = "mock"; @@ -19,7 +24,8 @@ class MockStrategy extends Strategy> { "Invalid credentials", request, sessionStorage, - options + options, + new Error("Invalid credentials") ); } } @@ -90,6 +96,7 @@ describe(Authenticator, () => { expect(strategy).toBe("mock"); } }); + test("should store the provided strategy name in the session", async () => { let user = { id: "123" }; let session = await sessionStorage.getSession(); @@ -190,4 +197,25 @@ describe(Authenticator, () => { ).rejects.toEqual(response); }); }); + + describe("authenticate", () => { + test("should throw an error if throwOnError is enabled", async () => { + let request = new Request("/"); + let authenticator = new Authenticator(sessionStorage); + + authenticator.use(new MockStrategy(async () => null)); + + let error = await authenticator + .authenticate("mock", request, { + throwOnError: true, + }) + .catch((error) => error); + + expect(error).toEqual(new AuthorizationError("Invalid credentials")); + + expect((error as AuthorizationError).cause).toEqual( + new TypeError("Invalid credentials") + ); + }); + }); });