Skip to content
Open
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
9 changes: 9 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,19 @@ jobs:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/geev_test
run: npx prisma migrate deploy

- name: Check production config secrets
run: |
if [ -z "${{ secrets.NEXTAUTH_SECRET }}" ]; then
echo "Error: NEXTAUTH_SECRET is missing from repository secrets."
echo "It must be present for production deployments."
exit 1
fi

- name: Run tests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/geev_test
JWT_SECRET: test-secret-key
NEXTAUTH_SECRET: test-secret-key
NODE_ENV: test
run: npm run test:ci

Expand Down
7 changes: 2 additions & 5 deletions app/app/(auth)/logout/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,10 @@ export async function POST(request: Request) {
expires: new Date(0), // Set to epoch to ensure expiration
};

// 1. Clear the legacy auth-token
response.cookies.set("auth-token", "", cookieOptions);

// 2. Clear Auth.js session token (standard)
// 1. Clear Auth.js session token (standard)
response.cookies.set("next-auth.session-token", "", cookieOptions);

// 3. Clear Auth.js session token (secure version used in production/HTTPS)
// 2. Clear Auth.js session token (secure version used in production/HTTPS)
response.cookies.set("__Secure-next-auth.session-token", "", cookieOptions);

return response;
Expand Down
80 changes: 0 additions & 80 deletions app/app/(auth)/session/route.ts

This file was deleted.

21 changes: 6 additions & 15 deletions app/lib/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { SignJWT, jwtVerify } from "jose";

const secret = new TextEncoder().encode(
process.env.NEXTAUTH_SECRET || "your-secret-key-change-in-production",
);
const secretValue = process.env.NEXTAUTH_SECRET;
if (!secretValue) {
throw new Error("NEXTAUTH_SECRET is missing. It must be set in production config.");
}

const secret = new TextEncoder().encode(secretValue);

export interface JWTPayload {
userId: string;
Expand Down Expand Up @@ -47,17 +50,5 @@ export function getTokenFromRequest(request: Request): string | null {
return authHeader.slice(7);
}

// Try to get from cookies
const cookieHeader = request.headers.get("cookie");
if (cookieHeader) {
const cookies = cookieHeader.split(";");
for (const cookie of cookies) {
const [name, value] = cookie.trim().split("=");
if (name === "token" || name === "auth-token") {
return value;
}
}
}

return null;
}
9 changes: 4 additions & 5 deletions app/tests/auth.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { test, expect, describe } from "vitest";
import { test, expect, describe, vi } from "vitest";

vi.stubEnv("NEXTAUTH_SECRET", "test-secret-key");

import { createToken, verifyToken } from "@/lib/jwt";

describe("Authentication System", () => {
Expand Down Expand Up @@ -58,13 +61,9 @@ describe("Authentication System", () => {
const response = await POST(request);
const cookies = response.cookies.getAll();

expect(cookies.some(c => c.name === "auth-token")).toBe(true);
expect(cookies.some(c => c.name === "next-auth.session-token")).toBe(true);
expect(response.status).toBe(200);
});
test.skip("GET /api/auth/session should return 401 without token", async () => {
// Skipped
});
});

describe("Authentication Middleware", () => {
Expand Down
25 changes: 25 additions & 0 deletions app/tests/jwt-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { test, expect, describe, vi, beforeEach } from "vitest";

describe("JWT Configuration Fail-Fast", () => {
beforeEach(() => {
vi.resetModules(); // Ensure we get a fresh import of jwt.ts each time
});

test("should throw an Error on import if NEXTAUTH_SECRET is missing", async () => {
// Explicitly unset the secret to simulate missing production config
vi.stubEnv("NEXTAUTH_SECRET", "");

await expect(async () => {
await import("@/lib/jwt");
}).rejects.toThrow("NEXTAUTH_SECRET is missing. It must be set in production config.");
});

test("should successfully import if NEXTAUTH_SECRET is provided", async () => {
// Provide a valid secret
vi.stubEnv("NEXTAUTH_SECRET", "valid-secret-for-test");

const jwt = await import("@/lib/jwt");
expect(jwt.createToken).toBeDefined();
expect(jwt.verifyToken).toBeDefined();
});
});
Loading