Files
appointment-booking-software/src/lib/server/auth/__tests__/jwt-utils.test.ts
T
2025-07-25 12:21:22 +02:00

164 lines
5.2 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
generateAccessToken,
generateRefreshToken,
verifyAccessToken,
verifyRefreshToken,
generateTokens,
isTokenExpired
} from "../jwt-utils";
import type { SelectUser } from "$lib/server/db/central-schema";
const mockUser: SelectUser = {
id: "test-user-id",
email: "test@example.com",
name: "Test User",
role: "GLOBAL_ADMIN",
tenantId: null,
createdAt: new Date(),
updatedAt: new Date(),
lastLoginAt: new Date(),
isActive: true,
confirmed: true,
token: null,
tokenValidUntil: null,
passphraseHash: null,
recoveryPassphrase: null,
language: "de"
};
describe("JWT Utils", () => {
const sessionId = "test-session-id";
describe("generateAccessToken", () => {
it("should generate a valid access token", async () => {
const token = await generateAccessToken(mockUser, sessionId);
expect(token).toBeDefined();
expect(typeof token).toBe("string");
expect(token.split(".")).toHaveLength(3);
});
it("should include user data in token payload", async () => {
const token = await generateAccessToken(mockUser, sessionId);
const payload = await verifyAccessToken(token);
expect(payload).toBeDefined();
expect(payload!.userId).toBe(mockUser.id);
expect(payload!.email).toBe(mockUser.email);
expect(payload!.name).toBe(mockUser.name);
expect(payload!.role).toBe(mockUser.role);
expect(payload!.sessionId).toBe(sessionId);
});
});
describe("generateRefreshToken", () => {
it("should generate a valid refresh token", async () => {
const token = await generateRefreshToken(mockUser.id, sessionId);
expect(token).toBeDefined();
expect(typeof token).toBe("string");
expect(token.split(".")).toHaveLength(3);
});
it("should include user and session data in token payload", async () => {
const token = await generateRefreshToken(mockUser.id, sessionId);
const payload = await verifyRefreshToken(token);
expect(payload).toBeDefined();
expect(payload!.userId).toBe(mockUser.id);
expect(payload!.sessionId).toBe(sessionId);
});
});
describe("verifyAccessToken", () => {
it("should verify a valid access token", async () => {
const token = await generateAccessToken(mockUser, sessionId);
const payload = await verifyAccessToken(token);
expect(payload).toBeDefined();
expect(payload!.userId).toBe(mockUser.id);
});
it("should reject invalid tokens", async () => {
const payload = await verifyAccessToken("invalid.token.here");
expect(payload).toBeNull();
});
it("should reject malformed tokens", async () => {
const payload = await verifyAccessToken("invalid-token");
expect(payload).toBeNull();
});
});
describe("verifyRefreshToken", () => {
it("should verify a valid refresh token", async () => {
const token = await generateRefreshToken(mockUser.id, sessionId);
const payload = await verifyRefreshToken(token);
expect(payload).toBeDefined();
expect(payload!.userId).toBe(mockUser.id);
expect(payload!.sessionId).toBe(sessionId);
});
it("should reject invalid tokens", async () => {
const payload = await verifyRefreshToken("invalid.token.here");
expect(payload).toBeNull();
});
it("should reject access tokens as refresh tokens", async () => {
const accessToken = await generateAccessToken(mockUser, sessionId);
const payload = await verifyRefreshToken(accessToken);
expect(payload).toBeNull();
});
});
describe("generateTokens", () => {
it("should generate both access and refresh tokens", async () => {
const tokens = await generateTokens(mockUser, sessionId);
expect(tokens.accessToken).toBeDefined();
expect(tokens.refreshToken).toBeDefined();
expect(typeof tokens.accessToken).toBe("string");
expect(typeof tokens.refreshToken).toBe("string");
});
it("should generate verifiable tokens", async () => {
const tokens = await generateTokens(mockUser, sessionId);
const accessPayload = await verifyAccessToken(tokens.accessToken);
const refreshPayload = await verifyRefreshToken(tokens.refreshToken);
expect(accessPayload).toBeDefined();
expect(refreshPayload).toBeDefined();
expect(accessPayload!.userId).toBe(mockUser.id);
expect(refreshPayload!.userId).toBe(mockUser.id);
});
});
describe("isTokenExpired", () => {
it("should return false for valid tokens", async () => {
const token = await generateAccessToken(mockUser, sessionId);
expect(await isTokenExpired(token)).toBe(false);
});
it("should return true for malformed tokens", async () => {
expect(await isTokenExpired("invalid-token")).toBe(true);
});
it("should return true for empty tokens", async () => {
expect(await isTokenExpired("")).toBe(true);
});
});
describe("Token expiration", () => {
it("should respect token expiration", async () => {
// Test with an obviously expired token (JWT with past exp claim)
// This is a manually crafted expired JWT for testing purposes
const expiredToken =
"eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJ0ZXN0LXVzZXItaWQiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20iLCJuYW1lIjoiVGVzdCBVc2VyIiwicm9sZSI6IkdMT0JBTF9BRE1JTiIsInNlc3Npb25JZCI6InRlc3Qtc2Vzc2lvbi1pZCIsImlhdCI6MTYwMDAwMDAwMCwiZXhwIjoxNjAwMDAwOTAwfQ.";
const payload = await verifyAccessToken(expiredToken);
expect(payload).toBeNull();
});
});
});