From fe06a3e407c79a978a6b6e39176d59f815839eea Mon Sep 17 00:00:00 2001 From: Alberto Elias Date: Tue, 22 Oct 2024 19:59:11 +0200 Subject: [PATCH] Auth Server SDK: Stores new auth material cookies (#817) Stores new auth material cookies --- .changeset/pink-lobsters-raise.md | 5 ++ .changeset/slimy-chairs-serve.md | 5 ++ .changeset/thirty-birds-hunt.md | 5 ++ .../src/components/auth/AuthModal.tsx | 4 +- .../src/hooks/useRefreshToken.test.ts | 6 +- .../ui/react-ui/src/hooks/useRefreshToken.ts | 4 +- .../src/providers/CrossmintAuthProvider.tsx | 6 +- .../auth/src/services/CrossmintAuthService.ts | 4 +- .../common/auth/src/types/authmaterial.ts | 14 +++-- packages/common/auth/src/types/cookies.ts | 5 ++ packages/common/auth/src/types/index.ts | 1 + .../server/src/auth/CrossmintAuth.test.ts | 52 +++++++++++++++- packages/server/src/auth/CrossmintAuth.ts | 54 ++++++++++++++--- packages/server/src/auth/types/request.ts | 11 +++- .../server/src/auth/utils/cookies.test.ts | 60 ++++++++++++++++++- packages/server/src/auth/utils/cookies.ts | 39 +++++++++++- packages/server/src/auth/utils/jwt.test.ts | 4 +- packages/server/src/auth/utils/jwt.ts | 2 +- .../utils/{tokenAuth => }/publicKey.test.ts | 0 .../auth/utils/{tokenAuth => }/publicKey.ts | 0 20 files changed, 247 insertions(+), 34 deletions(-) create mode 100644 .changeset/pink-lobsters-raise.md create mode 100644 .changeset/slimy-chairs-serve.md create mode 100644 .changeset/thirty-birds-hunt.md create mode 100644 packages/common/auth/src/types/cookies.ts rename packages/server/src/auth/utils/{tokenAuth => }/publicKey.test.ts (100%) rename packages/server/src/auth/utils/{tokenAuth => }/publicKey.ts (100%) diff --git a/.changeset/pink-lobsters-raise.md b/.changeset/pink-lobsters-raise.md new file mode 100644 index 00000000..4c53e06d --- /dev/null +++ b/.changeset/pink-lobsters-raise.md @@ -0,0 +1,5 @@ +--- +"@crossmint/common-sdk-auth": patch +--- + +Improves type naming diff --git a/.changeset/slimy-chairs-serve.md b/.changeset/slimy-chairs-serve.md new file mode 100644 index 00000000..3098f340 --- /dev/null +++ b/.changeset/slimy-chairs-serve.md @@ -0,0 +1,5 @@ +--- +"@crossmint/server-sdk": minor +--- + +Adds storeAuthMaterial to store auth material in cookies and does so in getSession diff --git a/.changeset/thirty-birds-hunt.md b/.changeset/thirty-birds-hunt.md new file mode 100644 index 00000000..a1cd4479 --- /dev/null +++ b/.changeset/thirty-birds-hunt.md @@ -0,0 +1,5 @@ +--- +"@crossmint/client-sdk-react-ui": patch +--- + +Use new type names for auth diff --git a/packages/client/ui/react-ui/src/components/auth/AuthModal.tsx b/packages/client/ui/react-ui/src/components/auth/AuthModal.tsx index 3071abf8..764d13d5 100644 --- a/packages/client/ui/react-ui/src/components/auth/AuthModal.tsx +++ b/packages/client/ui/react-ui/src/components/auth/AuthModal.tsx @@ -5,7 +5,7 @@ import { z } from "zod"; import { IFrameWindow } from "@crossmint/client-sdk-window"; import type { UIConfig } from "@crossmint/common-sdk-base"; import { CrossmintInternalEvents } from "@crossmint/client-sdk-base"; -import type { AuthMaterial } from "@crossmint/common-sdk-auth"; +import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth"; import type { LoginMethod } from "@/providers"; import X from "../../icons/x"; @@ -25,7 +25,7 @@ type IncomingModalIframeEventsType = { type AuthModalProps = { setModalOpen: (open: boolean) => void; apiKey: string; - fetchAuthMaterial: (refreshToken: string) => Promise; + fetchAuthMaterial: (refreshToken: string) => Promise; baseUrl: string; appearance?: UIConfig; loginMethods?: LoginMethod[]; diff --git a/packages/client/ui/react-ui/src/hooks/useRefreshToken.test.ts b/packages/client/ui/react-ui/src/hooks/useRefreshToken.test.ts index d1bde355..0a4a356a 100644 --- a/packages/client/ui/react-ui/src/hooks/useRefreshToken.test.ts +++ b/packages/client/ui/react-ui/src/hooks/useRefreshToken.test.ts @@ -1,7 +1,7 @@ import { act, renderHook } from "@testing-library/react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { AuthMaterial } from "@crossmint/common-sdk-auth"; +import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth"; import { type CrossmintAuthService, getJWTExpiration } from "@crossmint/client-sdk-auth"; import { queueTask } from "@crossmint/client-sdk-base"; @@ -64,7 +64,7 @@ describe("useRefreshToken", () => { it("should refresh token if refresh token is present", async () => { const mockRefreshToken = "mock-refresh-token"; - const mockAuthMaterial: AuthMaterial = { + const mockAuthMaterial: AuthMaterialWithUser = { jwt: "mock-jwt-token", refreshToken: { secret: "mock-secret", @@ -98,7 +98,7 @@ describe("useRefreshToken", () => { it("should schedule next refresh before token expiration", async () => { const mockRefreshToken = "mock-refresh-token"; - const mockAuthMaterial: AuthMaterial = { + const mockAuthMaterial: AuthMaterialWithUser = { jwt: "mock-jwt-token", refreshToken: { secret: "mock-secret", diff --git a/packages/client/ui/react-ui/src/hooks/useRefreshToken.ts b/packages/client/ui/react-ui/src/hooks/useRefreshToken.ts index 31819777..a29da187 100644 --- a/packages/client/ui/react-ui/src/hooks/useRefreshToken.ts +++ b/packages/client/ui/react-ui/src/hooks/useRefreshToken.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useRef } from "react"; -import type { AuthMaterial } from "@crossmint/common-sdk-auth"; +import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth"; import type { CrossmintAuthService } from "@crossmint/client-sdk-auth"; import { getJWTExpiration } from "@crossmint/client-sdk-auth"; import { queueTask, type CancellableTask } from "@crossmint/client-sdk-base"; @@ -13,7 +13,7 @@ const TIME_BEFORE_EXPIRING_JWT_IN_SECONDS = 120; type UseAuthTokenRefreshProps = { crossmintAuthService: CrossmintAuthService; - setAuthMaterial: (authMaterial: AuthMaterial) => void; + setAuthMaterial: (authMaterial: AuthMaterialWithUser) => void; logout: () => void; }; diff --git a/packages/client/ui/react-ui/src/providers/CrossmintAuthProvider.tsx b/packages/client/ui/react-ui/src/providers/CrossmintAuthProvider.tsx index a2b2c948..31a17f8d 100644 --- a/packages/client/ui/react-ui/src/providers/CrossmintAuthProvider.tsx +++ b/packages/client/ui/react-ui/src/providers/CrossmintAuthProvider.tsx @@ -7,7 +7,7 @@ import { type UIConfig, validateApiKeyAndGetCrossmintBaseUrl } from "@crossmint/ import { SESSION_PREFIX, REFRESH_TOKEN_PREFIX, - type AuthMaterial, + type AuthMaterialWithUser, type SDKExternalUser, } from "@crossmint/common-sdk-auth"; @@ -71,7 +71,7 @@ export function CrossmintAuthProvider({ const crossmintBaseUrl = validateApiKeyAndGetCrossmintBaseUrl(crossmint.apiKey); const [modalOpen, setModalOpen] = useState(false); - const setAuthMaterial = (authMaterial: AuthMaterial) => { + const setAuthMaterial = (authMaterial: AuthMaterialWithUser) => { setCookie(SESSION_PREFIX, authMaterial.jwt); setCookie(REFRESH_TOKEN_PREFIX, authMaterial.refreshToken.secret, authMaterial.refreshToken.expiresAt); setJwt(authMaterial.jwt); @@ -123,7 +123,7 @@ export function CrossmintAuthProvider({ return "logged-out"; }; - const fetchAuthMaterial = async (refreshToken: string): Promise => { + const fetchAuthMaterial = async (refreshToken: string): Promise => { const authMaterial = await crossmintAuthService.refreshAuthMaterial(refreshToken); setAuthMaterial(authMaterial); return authMaterial; diff --git a/packages/common/auth/src/services/CrossmintAuthService.ts b/packages/common/auth/src/services/CrossmintAuthService.ts index a07cd90f..710bdfd9 100644 --- a/packages/common/auth/src/services/CrossmintAuthService.ts +++ b/packages/common/auth/src/services/CrossmintAuthService.ts @@ -1,7 +1,7 @@ import { APIErrorService, BaseCrossmintService } from "@crossmint/client-sdk-base"; import { authLogger } from "./logger"; -import type { AuthMaterial } from "@/types"; +import type { AuthMaterialWithUser } from "@/types"; export class CrossmintAuthService extends BaseCrossmintService { protected apiErrorService = new APIErrorService({}); @@ -11,7 +11,7 @@ export class CrossmintAuthService extends BaseCrossmintService { return `${this.crossmintBaseUrl}/.well-known/jwks.json`; } - async refreshAuthMaterial(refreshToken: string): Promise { + async refreshAuthMaterial(refreshToken: string): Promise { const result = await this.fetchCrossmintAPI( "2024-09-26/session/sdk/auth/refresh", { method: "POST", body: JSON.stringify({ refresh: refreshToken }) }, diff --git a/packages/common/auth/src/types/authmaterial.ts b/packages/common/auth/src/types/authmaterial.ts index 260e6743..0379ed9e 100644 --- a/packages/common/auth/src/types/authmaterial.ts +++ b/packages/common/auth/src/types/authmaterial.ts @@ -5,14 +5,12 @@ export type AuthMaterialBasic = { refreshToken: string; }; -interface RefreshToken { - secret: string; - expiresAt: string; -} - export type AuthMaterial = { jwt: string; refreshToken: RefreshToken; +}; + +export type AuthMaterialWithUser = AuthMaterial & { user: SDKExternalUser; }; @@ -24,5 +22,11 @@ export type AuthMaterialResponse = { export type AuthSession = { jwt: string; + refreshToken: RefreshToken; userId: string; }; + +interface RefreshToken { + secret: string; + expiresAt: string; +} diff --git a/packages/common/auth/src/types/cookies.ts b/packages/common/auth/src/types/cookies.ts new file mode 100644 index 00000000..09cdfa0a --- /dev/null +++ b/packages/common/auth/src/types/cookies.ts @@ -0,0 +1,5 @@ +export type CookieOptions = { + name: string; + value: string; + expiresAt?: string; +}; diff --git a/packages/common/auth/src/types/index.ts b/packages/common/auth/src/types/index.ts index 622b9f56..91408ef2 100644 --- a/packages/common/auth/src/types/index.ts +++ b/packages/common/auth/src/types/index.ts @@ -1,3 +1,4 @@ export * from "./user"; export * from "./authmaterial"; export * from "./errors"; +export * from "./cookies"; diff --git a/packages/server/src/auth/CrossmintAuth.test.ts b/packages/server/src/auth/CrossmintAuth.test.ts index af2e5432..f72de1ac 100644 --- a/packages/server/src/auth/CrossmintAuth.test.ts +++ b/packages/server/src/auth/CrossmintAuth.test.ts @@ -4,7 +4,7 @@ import { type Crossmint, CrossmintApiClient } from "@crossmint/common-sdk-base"; import { type AuthMaterialBasic, CrossmintAuthenticationError } from "@crossmint/common-sdk-auth"; import * as cookiesUtils from "./utils/cookies"; import * as jwtUtils from "./utils/jwt"; -import type { GenericRequest } from "./types/request"; +import type { GenericRequest, GenericResponse } from "./types/request"; vi.mock("@crossmint/common-sdk-base"); vi.mock("./utils/cookies"); @@ -15,6 +15,7 @@ describe("CrossmintAuth", () => { const mockCrossmint = { projectId: "test-project-id" }; const mockApiClient = { baseUrl: "https://api.crossmint.com", + get: vi.fn(), post: vi.fn(), }; @@ -72,6 +73,10 @@ describe("CrossmintAuth", () => { expect(result).toEqual({ jwt: "mock.jwt.token", + refreshToken: { + secret: "mock-refresh-token", + expiresAt: "", + }, userId: "user123", }); }); @@ -83,15 +88,23 @@ describe("CrossmintAuth", () => { json: () => Promise.resolve({ jwt: "new.jwt.token", - refresh: "new-refresh-token", + refresh: { + secret: "new-refresh-token", + expiresAt: "2023-12-31T23:59:59Z", + }, user: { id: "user456" }, }), + ok: true, }); const result = await crossmintAuth.getSession(mockRequest as GenericRequest); expect(result).toEqual({ jwt: "new.jwt.token", + refreshToken: { + secret: "new-refresh-token", + expiresAt: "2023-12-31T23:59:59Z", + }, userId: "user456", }); expect(mockApiClient.post).toHaveBeenCalledWith( @@ -124,4 +137,39 @@ describe("CrossmintAuth", () => { ); }); }); + + describe("getUser", () => { + it("should fetch user data for a given external user ID", async () => { + const mockExternalUserId = "external-user-123"; + const mockUserData = { id: "user456", email: "user@example.com" }; + mockApiClient.get.mockResolvedValue({ + json: () => Promise.resolve(mockUserData), + }); + + const result = await crossmintAuth.getUser(mockExternalUserId); + + expect(result).toEqual(mockUserData); + expect(mockApiClient.get).toHaveBeenCalledWith( + `api/2024-09-26/sdk/auth/user/${mockExternalUserId}`, + expect.any(Object) + ); + }); + }); + + describe("storeAuthMaterial", () => { + it("should call setAuthCookies with the provided response and auth material", () => { + const mockResponse = {} as GenericResponse; + const mockAuthMaterial = { + jwt: "new.jwt.token", + refreshToken: { + secret: "new-refresh-token", + expiresAt: "2023-12-31T23:59:59Z", + }, + }; + + crossmintAuth.storeAuthMaterial(mockResponse, mockAuthMaterial); + + expect(cookiesUtils.setAuthCookies).toHaveBeenCalledWith(mockResponse, mockAuthMaterial); + }); + }); }); diff --git a/packages/server/src/auth/CrossmintAuth.ts b/packages/server/src/auth/CrossmintAuth.ts index 73285e4e..413a2ff7 100644 --- a/packages/server/src/auth/CrossmintAuth.ts +++ b/packages/server/src/auth/CrossmintAuth.ts @@ -1,13 +1,14 @@ import { type Crossmint, CrossmintApiClient } from "@crossmint/common-sdk-base"; import { CrossmintAuthenticationError, - type AuthSession, type AuthMaterialBasic, - type AuthMaterial, + type AuthMaterialWithUser, type AuthMaterialResponse, + type AuthSession, + type AuthMaterial, } from "@crossmint/common-sdk-auth"; -import type { GenericRequest } from "./types/request"; -import { getAuthCookies } from "./utils/cookies"; +import type { GenericRequest, GenericResponse } from "./types/request"; +import { getAuthCookies, setAuthCookies } from "./utils/cookies"; import { verifyCrossmintJwt } from "./utils/jwt"; import { CROSSMINT_API_VERSION, SDK_NAME, SDK_VERSION } from "./utils/constants"; @@ -31,7 +32,10 @@ export class CrossmintAuth { return new CrossmintAuth(crossmint); } - public async getSession(options: GenericRequest | AuthMaterialBasic): Promise { + public async getSession( + options: GenericRequest | AuthMaterialBasic, + response?: GenericResponse + ): Promise { const { jwt, refreshToken } = "refreshToken" in options ? options : getAuthCookies(options); if (!refreshToken) { @@ -39,8 +43,17 @@ export class CrossmintAuth { } try { - return await this.validateOrRefreshSession(jwt, refreshToken); + return await this.validateOrRefreshSession(jwt, refreshToken, response); } catch (error) { + if (error instanceof CrossmintAuthenticationError && response != null) { + this.storeAuthMaterial(response, { + jwt: "", + refreshToken: { + secret: "", + expiresAt: "", + }, + }); + } console.error("Failed to get session", error); throw new CrossmintAuthenticationError("Failed to get session"); } @@ -65,11 +78,22 @@ export class CrossmintAuth { return `${this.apiClient.baseUrl}/.well-known/jwks.json`; } - private async refreshAuthMaterial(refreshToken: string): Promise { + public storeAuthMaterial(response: GenericResponse, authMaterial: AuthMaterial) { + setAuthCookies(response, authMaterial); + } + + private async refreshAuthMaterial(refreshToken: string): Promise { const result = await this.apiClient.post(`api/${CROSSMINT_API_VERSION}/session/sdk/auth/refresh`, { body: JSON.stringify({ refresh: refreshToken }), + headers: { + "Content-Type": "application/json", + }, }); + if (!result.ok) { + throw new CrossmintAuthenticationError(result.statusText); + } + const resultJson = (await result.json()) as AuthMaterialResponse; return { @@ -79,12 +103,20 @@ export class CrossmintAuth { }; } - private async validateOrRefreshSession(jwt: string | undefined, refreshToken: string): Promise { + private async validateOrRefreshSession( + jwt: string | undefined, + refreshToken: string, + response?: GenericResponse + ): Promise { if (jwt) { try { const decodedJwt = await this.verifyCrossmintJwt(jwt); return { jwt, + refreshToken: { + secret: refreshToken, + expiresAt: "", + }, userId: decodedJwt.sub as string, }; } catch (_) { @@ -93,8 +125,14 @@ export class CrossmintAuth { } const refreshedAuthMaterial = await this.refreshAuthMaterial(refreshToken); + + if (response != null) { + this.storeAuthMaterial(response, refreshedAuthMaterial); + } + return { jwt: refreshedAuthMaterial.jwt, + refreshToken: refreshedAuthMaterial.refreshToken, userId: refreshedAuthMaterial.user.id, }; } diff --git a/packages/server/src/auth/types/request.ts b/packages/server/src/auth/types/request.ts index f8f13b97..a365e062 100644 --- a/packages/server/src/auth/types/request.ts +++ b/packages/server/src/auth/types/request.ts @@ -1,6 +1,7 @@ -import type { IncomingMessage } from "http"; +import type { IncomingMessage, ServerResponse } from "http"; export type GenericRequest = IncomingMessage | Request; +export type GenericResponse = ServerResponse | Response; export function isNodeRequest(request: GenericRequest): request is IncomingMessage { return "httpVersion" in request; @@ -9,3 +10,11 @@ export function isNodeRequest(request: GenericRequest): request is IncomingMessa export function isFetchRequest(request: GenericRequest): request is Request { return "headers" in request && typeof request.headers.get === "function"; } + +export function isNodeResponse(response: GenericResponse): response is ServerResponse { + return "setHeader" in response; +} + +export function isFetchResponse(response: GenericResponse): response is Response { + return "headers" in response && typeof response.headers.append === "function"; +} diff --git a/packages/server/src/auth/utils/cookies.test.ts b/packages/server/src/auth/utils/cookies.test.ts index 40f04c86..0a5d1469 100644 --- a/packages/server/src/auth/utils/cookies.test.ts +++ b/packages/server/src/auth/utils/cookies.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { IncomingMessage } from "http"; +import type { IncomingMessage, ServerResponse } from "http"; import { CrossmintAuthenticationError, SESSION_PREFIX, REFRESH_TOKEN_PREFIX } from "@crossmint/common-sdk-auth"; -import { getAuthCookies } from "./cookies"; +import { getAuthCookies, setAuthCookies } from "./cookies"; vi.mock("@crossmint/common-sdk-auth", async () => { const actual = await vi.importActual("@crossmint/common-sdk-auth"); @@ -80,3 +80,59 @@ describe("getAuthCookies", () => { expect(() => getAuthCookies(mockRequest)).toThrow("Unsupported request type"); }); }); + +describe("setAuthCookies", () => { + const mockAuthMaterial = { + jwt: "mock-jwt-token", + refreshToken: { + secret: "mock-refresh-token", + expiresAt: new Date("2023-04-01T00:00:00Z").toString(), + }, + }; + + beforeEach(() => { + vi.resetAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("should set auth cookies for Node.js ServerResponse", () => { + const mockResponse = { + setHeader: vi.fn(), + } as unknown as ServerResponse; + + setAuthCookies(mockResponse, mockAuthMaterial); + + expect(mockResponse.setHeader).toHaveBeenCalledWith("Set-Cookie", [ + `${SESSION_PREFIX}=mock-jwt-token; path=/; SameSite=Lax;`, + `${REFRESH_TOKEN_PREFIX}=mock-refresh-token; path=/; SameSite=Lax; expires=Sat, 01 Apr 2023 00:00:00 GMT;`, + ]); + }); + + it("should set auth cookies for Fetch Response", () => { + const mockHeaders = new Headers(); + const appendSpy = vi.spyOn(mockHeaders, "append"); + + const mockResponse = { + headers: mockHeaders, + } as unknown as Response; + + setAuthCookies(mockResponse, mockAuthMaterial); + + expect(appendSpy).toHaveBeenCalledTimes(2); + expect(appendSpy).toHaveBeenCalledWith("Set-Cookie", `${SESSION_PREFIX}=mock-jwt-token; path=/; SameSite=Lax;`); + expect(appendSpy).toHaveBeenCalledWith( + "Set-Cookie", + `${REFRESH_TOKEN_PREFIX}=mock-refresh-token; path=/; SameSite=Lax; expires=Sat, 01 Apr 2023 00:00:00 GMT;` + ); + }); + + it("should throw CrossmintAuthenticationError for unsupported response type", () => { + const mockResponse = {} as any; + + expect(() => setAuthCookies(mockResponse, mockAuthMaterial)).toThrow(CrossmintAuthenticationError); + expect(() => setAuthCookies(mockResponse, mockAuthMaterial)).toThrow("Unsupported response type"); + }); +}); diff --git a/packages/server/src/auth/utils/cookies.ts b/packages/server/src/auth/utils/cookies.ts index df037ef7..4a836698 100644 --- a/packages/server/src/auth/utils/cookies.ts +++ b/packages/server/src/auth/utils/cookies.ts @@ -3,8 +3,17 @@ import { REFRESH_TOKEN_PREFIX, CrossmintAuthenticationError, type AuthMaterialBasic, + type AuthMaterial, + type CookieOptions, } from "@crossmint/common-sdk-auth"; -import { type GenericRequest, isNodeRequest, isFetchRequest } from "../types/request"; +import { + type GenericRequest, + isNodeRequest, + isFetchRequest, + type GenericResponse, + isNodeResponse, + isFetchResponse, +} from "../types/request"; export function getAuthCookies(request: GenericRequest): AuthMaterialBasic { const cookieHeader = getCookieHeader(request); @@ -12,6 +21,25 @@ export function getAuthCookies(request: GenericRequest): AuthMaterialBasic { return { jwt, refreshToken }; } +export function setAuthCookies(response: GenericResponse, authMaterial: AuthMaterial) { + const cookies = [ + createCookieString({ name: SESSION_PREFIX, value: authMaterial.jwt }), + createCookieString({ + name: REFRESH_TOKEN_PREFIX, + value: authMaterial.refreshToken.secret, + expiresAt: authMaterial.refreshToken.expiresAt, + }), + ]; + + if (isNodeResponse(response)) { + response.setHeader("Set-Cookie", cookies); + } else if (isFetchResponse(response)) { + cookies.forEach((cookie) => response.headers.append("Set-Cookie", cookie)); + } else { + throw new CrossmintAuthenticationError("Unsupported response type"); + } +} + function getCookieHeader(request: GenericRequest): string { let cookieHeader; @@ -39,3 +67,12 @@ function parseCookieHeader(cookieHeader: string): Record { {} as Record ); } + +function createCookieString(cookieOptions: CookieOptions): string { + const expiresInUtc = cookieOptions.expiresAt ? new Date(cookieOptions.expiresAt).toUTCString() : ""; + let cookieString = `${cookieOptions.name}=${cookieOptions.value}; path=/; SameSite=Lax;`; + if (expiresInUtc) { + cookieString += ` expires=${expiresInUtc};`; + } + return cookieString; +} diff --git a/packages/server/src/auth/utils/jwt.test.ts b/packages/server/src/auth/utils/jwt.test.ts index df953bc0..136973c9 100644 --- a/packages/server/src/auth/utils/jwt.test.ts +++ b/packages/server/src/auth/utils/jwt.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { verifyCrossmintJwt } from "./jwt"; -import { getPublicKey } from "./tokenAuth/publicKey"; +import { getPublicKey } from "./publicKey"; import jwt from "jsonwebtoken"; -vi.mock("./tokenAuth/publicKey"); +vi.mock("./publicKey"); vi.mock("jsonwebtoken"); diff --git a/packages/server/src/auth/utils/jwt.ts b/packages/server/src/auth/utils/jwt.ts index df300dc2..8441b94a 100644 --- a/packages/server/src/auth/utils/jwt.ts +++ b/packages/server/src/auth/utils/jwt.ts @@ -1,6 +1,6 @@ import jwt from "jsonwebtoken"; -import { getPublicKey } from "./tokenAuth/publicKey"; +import { getPublicKey } from "./publicKey"; export async function verifyCrossmintJwt(token: string, jwksUri: string) { try { diff --git a/packages/server/src/auth/utils/tokenAuth/publicKey.test.ts b/packages/server/src/auth/utils/publicKey.test.ts similarity index 100% rename from packages/server/src/auth/utils/tokenAuth/publicKey.test.ts rename to packages/server/src/auth/utils/publicKey.test.ts diff --git a/packages/server/src/auth/utils/tokenAuth/publicKey.ts b/packages/server/src/auth/utils/publicKey.ts similarity index 100% rename from packages/server/src/auth/utils/tokenAuth/publicKey.ts rename to packages/server/src/auth/utils/publicKey.ts