mirror of
https://github.com/lukevella/rallly.git
synced 2025-06-06 04:31:50 +02:00
🔥 Remove support for legacy sessions (#1654)
This commit is contained in:
parent
0bdceb7bbe
commit
13e078cb88
5 changed files with 0 additions and 219 deletions
|
@ -4,12 +4,6 @@ import NextAuth from "next-auth";
|
|||
|
||||
import { nextAuthConfig } from "@/next-auth.config";
|
||||
|
||||
import {
|
||||
deleteLegacyCookie,
|
||||
getLegacySession,
|
||||
migrateLegacyJWT,
|
||||
} from "../legacy/next-auth-cookie-migration";
|
||||
|
||||
const { auth } = NextAuth(nextAuthConfig);
|
||||
|
||||
export const withAuth = (
|
||||
|
@ -24,20 +18,6 @@ export const withAuth = (
|
|||
console.error(e);
|
||||
}
|
||||
|
||||
let isLegacySession = false;
|
||||
let isExpiredLegacySession = false;
|
||||
|
||||
if (!session) {
|
||||
try {
|
||||
session = await getLegacySession();
|
||||
if (session) {
|
||||
isLegacySession = true;
|
||||
}
|
||||
} catch {
|
||||
isExpiredLegacySession = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await nextAuthConfig.callbacks.authorized({
|
||||
request,
|
||||
|
@ -55,20 +35,6 @@ export const withAuth = (
|
|||
|
||||
const middlewareRes = await middleware(request);
|
||||
|
||||
if (isLegacySession) {
|
||||
console.warn("Found legacy session, migrating…");
|
||||
try {
|
||||
await migrateLegacyJWT(middlewareRes);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (isExpiredLegacySession) {
|
||||
console.warn("Found expired legacy session, deleting…");
|
||||
deleteLegacyCookie(middlewareRes);
|
||||
}
|
||||
|
||||
return middlewareRes;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import hkdf from "@panva/hkdf";
|
||||
import { jwtDecrypt } from "jose";
|
||||
import type { JWT } from "next-auth/jwt";
|
||||
|
||||
/** Decodes a NextAuth.js issued JWT. */
|
||||
export async function decodeLegacyJWT(token: string): Promise<JWT | null> {
|
||||
if (!token) return null;
|
||||
const encryptionSecret = await getDerivedEncryptionKey(
|
||||
process.env.SECRET_PASSWORD,
|
||||
"",
|
||||
);
|
||||
const { payload } = await jwtDecrypt(token, encryptionSecret, {
|
||||
clockTolerance: 15,
|
||||
});
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function getDerivedEncryptionKey(
|
||||
keyMaterial: string | Uint8Array,
|
||||
salt: string,
|
||||
) {
|
||||
return await hkdf(
|
||||
"sha256",
|
||||
keyMaterial,
|
||||
salt,
|
||||
`NextAuth.js Generated Encryption Key${salt ? ` (${salt})` : ""}`,
|
||||
32,
|
||||
);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
import { absoluteUrl } from "@rallly/utils/absolute-url";
|
||||
import { cookies } from "next/headers";
|
||||
import type { NextResponse } from "next/server";
|
||||
import type { Session } from "next-auth";
|
||||
import type { JWT } from "next-auth/jwt";
|
||||
import { encode } from "next-auth/jwt";
|
||||
|
||||
import { decodeLegacyJWT } from "./helpers/jwt";
|
||||
|
||||
const isSecureCookie = absoluteUrl().startsWith("https://");
|
||||
|
||||
const prefix = isSecureCookie ? "__Secure-" : "";
|
||||
|
||||
const oldCookieName = prefix + "next-auth.session-token";
|
||||
const newCookieName = prefix + "authjs.session-token";
|
||||
|
||||
export async function getLegacySession(): Promise<Session | null> {
|
||||
const cookieStore = cookies();
|
||||
const legacySessionCookie = cookieStore.get(oldCookieName);
|
||||
if (legacySessionCookie && legacySessionCookie.value) {
|
||||
const decodedCookie = await decodeLegacyJWT(legacySessionCookie.value);
|
||||
|
||||
if (decodedCookie?.sub) {
|
||||
const { sub: id, ...rest } = decodedCookie;
|
||||
return {
|
||||
user: { id, ...rest },
|
||||
expires: decodedCookie.exp
|
||||
? new Date(decodedCookie.exp * 1000).toISOString()
|
||||
: new Date(Date.now() + 30 * 60 * 60 * 1000).toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getLegacyJWT() {
|
||||
const cookieStore = cookies();
|
||||
const legacySessionCookie = cookieStore.get(oldCookieName);
|
||||
if (legacySessionCookie) {
|
||||
const decodedCookie = await decodeLegacyJWT(legacySessionCookie.value);
|
||||
if (decodedCookie) {
|
||||
return decodedCookie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function deleteLegacyCookie(res: NextResponse) {
|
||||
const cookieStore = cookies();
|
||||
const oldCookie = cookieStore.get(oldCookieName);
|
||||
if (oldCookie) {
|
||||
// Delete the old cookie
|
||||
res.cookies.set(oldCookieName, oldCookie.value, {
|
||||
httpOnly: true,
|
||||
secure: isSecureCookie,
|
||||
expires: new Date(0),
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function setNewSessionCookie(res: NextResponse, jwt: JWT) {
|
||||
const newJWT = await encode({
|
||||
token: jwt,
|
||||
secret: process.env.SECRET_PASSWORD,
|
||||
salt: newCookieName,
|
||||
});
|
||||
|
||||
// Set new session cookie
|
||||
res.cookies.set(newCookieName, newJWT, {
|
||||
httpOnly: true,
|
||||
secure: isSecureCookie,
|
||||
expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7),
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the old legacy cookie with the new one
|
||||
*/
|
||||
export async function migrateLegacyJWT(res: NextResponse) {
|
||||
const legacyJWT = await getLegacyJWT();
|
||||
|
||||
if (legacyJWT) {
|
||||
await setNewSessionCookie(res, legacyJWT);
|
||||
deleteLegacyCookie(res);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import z from "zod";
|
|||
import { CustomPrismaAdapter } from "./auth/adapters/prisma";
|
||||
import { isEmailBanned, isEmailBlocked } from "./auth/helpers/is-email-blocked";
|
||||
import { mergeGuestsIntoUser } from "./auth/helpers/merge-user";
|
||||
import { getLegacySession } from "./auth/legacy/next-auth-cookie-migration";
|
||||
import { EmailProvider } from "./auth/providers/email";
|
||||
import { GoogleProvider } from "./auth/providers/google";
|
||||
import { GuestProvider } from "./auth/providers/guest";
|
||||
|
@ -203,12 +202,6 @@ const auth = cache(async () => {
|
|||
} catch (e) {
|
||||
console.error("FAILED TO GET SESSION", e);
|
||||
}
|
||||
|
||||
try {
|
||||
return await getLegacySession();
|
||||
} catch (e) {
|
||||
console.error("FAILED TO GET LEGACY SESSION", e);
|
||||
}
|
||||
});
|
||||
|
||||
const requireUser = async () => {
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { prisma } from "@rallly/database";
|
||||
|
||||
import { encode } from "./helpers/next-auth-v4";
|
||||
|
||||
const legacyGuestId = "user-1234";
|
||||
|
||||
test.describe.serial(() => {
|
||||
test.beforeAll(async () => {
|
||||
await prisma.poll.create({
|
||||
data: {
|
||||
id: "legacy-guest-poll",
|
||||
title: "Test Poll",
|
||||
adminUrlId: "admin-url-id",
|
||||
participantUrlId: "participant-url-id",
|
||||
guestId: legacyGuestId,
|
||||
},
|
||||
});
|
||||
});
|
||||
test.afterAll(async () => {
|
||||
await prisma.poll.delete({
|
||||
where: {
|
||||
id: "legacy-guest-poll",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should see poll on login page", async ({ page }) => {
|
||||
const context = page.context();
|
||||
const legacyToken = await encode({
|
||||
token: {
|
||||
sub: legacyGuestId,
|
||||
},
|
||||
secret: process.env.SECRET_PASSWORD,
|
||||
});
|
||||
|
||||
// set cookie to simulate legacy guest
|
||||
await context.addCookies([
|
||||
{
|
||||
name: "next-auth.session-token",
|
||||
value: legacyToken,
|
||||
httpOnly: true,
|
||||
expires: Date.now() / 1000 + 60 * 60 * 24 * 7,
|
||||
secure: false,
|
||||
sameSite: "Lax",
|
||||
domain: "localhost",
|
||||
path: "/",
|
||||
},
|
||||
]);
|
||||
|
||||
// For some reason it doesn't work unless we need to redirect
|
||||
await page.goto("/login");
|
||||
|
||||
// Check if the poll title exists in the page content
|
||||
await expect(page.getByText("Test Poll")).toBeVisible();
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue