Skip to content

Commit f00fbaf

Browse files
jsell-rhclaude
andcommitted
fix(frontend): store idToken in separate cookie to avoid size limit
iron-session's cookie limit (4096 bytes) is exceeded when idToken is included alongside accessToken and refreshToken — especially with Keycloak identity brokering which produces large tokens. Store idToken in a dedicated httpOnly oidc_id_token cookie. Logout reads it from there for id_token_hint. Session type no longer includes idToken. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 235bc38 commit f00fbaf

4 files changed

Lines changed: 15 additions & 5 deletions

File tree

components/frontend/src/app/api/auth/sso/callback/route.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export async function GET(request: NextRequest) {
3939
const session = await getSession();
4040
session.accessToken = tokens.accessToken;
4141
session.refreshToken = tokens.refreshToken;
42-
session.idToken = tokens.idToken;
4342
session.expiresAt = tokens.expiresAt;
4443
await session.save();
4544

@@ -50,7 +49,17 @@ export async function GET(request: NextRequest) {
5049
const origin = process.env.SSO_REDIRECT_URI
5150
? new URL(process.env.SSO_REDIRECT_URI).origin
5251
: request.nextUrl.origin;
53-
return NextResponse.redirect(new URL(returnTo, origin));
52+
const response = NextResponse.redirect(new URL(returnTo, origin));
53+
if (tokens.idToken) {
54+
response.cookies.set("oidc_id_token", tokens.idToken, {
55+
httpOnly: true,
56+
secure: process.env.NODE_ENV === "production",
57+
sameSite: "lax",
58+
path: "/",
59+
maxAge: 86400,
60+
});
61+
}
62+
return response;
5463
} catch (err) {
5564
console.error("OIDC callback failed:", err instanceof Error ? err.message : err);
5665
cookieStore.delete("oidc_code_verifier");

components/frontend/src/app/api/auth/sso/e2e-login/route.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export async function POST(request: NextRequest) {
2121
const session = await getSession();
2222
session.accessToken = token;
2323
session.refreshToken = "";
24-
session.idToken = "";
2524
session.expiresAt = Math.floor(Date.now() / 1000) + 86400;
2625
await session.save();
2726

components/frontend/src/app/api/auth/sso/logout/route.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { NextRequest, NextResponse } from "next/server";
2+
import { cookies } from "next/headers";
23
import { getSession } from "@/lib/session";
34
import { getEndSessionUrl } from "@/lib/oidc";
45

56
export async function GET(request: NextRequest) {
7+
const cookieStore = await cookies();
8+
const idToken = cookieStore.get("oidc_id_token")?.value;
69
const session = await getSession();
7-
const idToken = session.idToken || undefined;
810
session.destroy();
11+
cookieStore.delete("oidc_id_token");
912

1013
const postLogoutRedirectUri = process.env.SSO_REDIRECT_URI
1114
? new URL(process.env.SSO_REDIRECT_URI).origin

components/frontend/src/lib/session.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { cookies } from "next/headers";
44
export interface SessionData {
55
accessToken: string;
66
refreshToken: string;
7-
idToken: string;
87
expiresAt: number;
98
}
109

0 commit comments

Comments
 (0)