diff --git a/backend/__tests__/middlewares/auth.spec.ts b/backend/__tests__/middlewares/auth.spec.ts index 836c28a2a..3caeb80e4 100644 --- a/backend/__tests__/middlewares/auth.spec.ts +++ b/backend/__tests__/middlewares/auth.spec.ts @@ -3,6 +3,9 @@ import * as Auth from "../../src/middlewares/auth"; import { DecodedIdToken } from "firebase-admin/lib/auth/token-verifier"; import { NextFunction, Request, Response } from "express"; import { getCachedConfiguration } from "../../src/init/configuration"; +import * as ApeKeys from "../../src/dal/ape-keys"; +import { ObjectId } from "mongodb"; +import { hashSync } from "bcrypt"; const mockDecodedToken: DecodedIdToken = { uid: "123456789", @@ -10,9 +13,21 @@ const mockDecodedToken: DecodedIdToken = { iat: 0, } as DecodedIdToken; -jest.spyOn(AuthUtils, "verifyIdToken").mockImplementation(async (_token) => { - return mockDecodedToken; -}); +jest.spyOn(AuthUtils, "verifyIdToken").mockResolvedValue(mockDecodedToken); + +const mockApeKey = { + _id: new ObjectId(), + uid: "123", + name: "test", + hash: hashSync("key", 5), + createdOn: Date.now(), + modifiedOn: Date.now(), + lastUsedOn: Date.now(), + useCount: 0, + enabled: true, +}; +jest.spyOn(ApeKeys, "getApeKey").mockResolvedValue(mockApeKey); +jest.spyOn(ApeKeys, "updateLastUsedOn").mockResolvedValue(); describe("middlewares/auth", () => { let mockRequest: Partial; @@ -20,6 +35,9 @@ describe("middlewares/auth", () => { let nextFunction: NextFunction; beforeEach(async () => { + let config = await getCachedConfiguration(true); + config.apeKeys.acceptKeys = true; + mockRequest = { baseUrl: "/api/v1", route: { @@ -29,7 +47,7 @@ describe("middlewares/auth", () => { authorization: "Bearer 123456789", }, ctx: { - configuration: await getCachedConfiguration(true), + configuration: config, decodedToken: { type: "None", uid: "", @@ -93,5 +111,85 @@ describe("middlewares/auth", () => { expect(decodedToken?.uid).toBe(mockDecodedToken.uid); expect(nextFunction).toHaveBeenCalledTimes(1); }); + it("should allow the request if apeKey is supported", async () => { + mockRequest.headers = { + authorization: "ApeKey aWQua2V5", + }; + + const authenticateRequest = Auth.authenticateRequest({ + acceptApeKeys: true, + }); + + await authenticateRequest( + mockRequest as Request, + mockResponse as Response, + nextFunction + ); + + const decodedToken = mockRequest?.ctx?.decodedToken; + + expect(decodedToken?.type).toBe("ApeKey"); + expect(decodedToken?.email).toBe(""); + expect(decodedToken?.uid).toBe("123"); + expect(nextFunction).toHaveBeenCalledTimes(1); + }); + it("should allow the request with authentation on public endpoint", async () => { + const authenticateRequest = Auth.authenticateRequest({ + isPublic: true, + }); + + await authenticateRequest( + mockRequest as Request, + mockResponse as Response, + nextFunction + ); + + const decodedToken = mockRequest?.ctx?.decodedToken; + expect(decodedToken?.type).toBe("Bearer"); + expect(decodedToken?.email).toBe(mockDecodedToken.email); + expect(decodedToken?.uid).toBe(mockDecodedToken.uid); + expect(nextFunction).toHaveBeenCalledTimes(1); + }); + it("should allow the request without authentication on public endpoint", async () => { + mockRequest.headers = {}; + + const authenticateRequest = Auth.authenticateRequest({ + isPublic: true, + }); + + await authenticateRequest( + mockRequest as Request, + mockResponse as Response, + nextFunction + ); + + const decodedToken = mockRequest?.ctx?.decodedToken; + expect(decodedToken?.type).toBe("None"); + expect(decodedToken?.email).toBe(""); + expect(decodedToken?.uid).toBe(""); + expect(nextFunction).toHaveBeenCalledTimes(1); + }); + it("should allow the request with apeKey on public endpoint", async () => { + mockRequest.headers = { + authorization: "ApeKey aWQua2V5", + }; + + const authenticateRequest = Auth.authenticateRequest({ + isPublic: true, + }); + + await authenticateRequest( + mockRequest as Request, + mockResponse as Response, + nextFunction + ); + + const decodedToken = mockRequest?.ctx?.decodedToken; + + expect(decodedToken?.type).toBe("ApeKey"); + expect(decodedToken?.email).toBe(""); + expect(decodedToken?.uid).toBe("123"); + expect(nextFunction).toHaveBeenCalledTimes(1); + }); }); });