fix(auth): refresh the session cookie cache after first-admin promotion

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Sonnet 5.5 committed 2026-10-04 17:10:49 -04:00
1 parent d42a022a30
commit 98fd236b5c
3 files changed
+29 -2

No files matched your search

+2
View File
@@ -27,6 +27,8 @@ export const admin = oo.spec(
base.middleware(async ({ context, next }) => {
const sessionData = await auth.api.getSession({
headers: context.headers,
// Bypass the 5-minute cookie cache so role changes take effect immediately.
query: { disableCookieCache: true },
});
if (!sessionData?.session || !sessionData?.user) {
throw new ORPCError("UNAUTHORIZED");
+5 -1
View File
@@ -9,7 +9,11 @@ const app = new Hono();
app.get("/:filename", async (c) => {
// Auth + admin check
const session = await auth.api.getSession({ headers: c.req.raw.headers });
const session = await auth.api.getSession({
headers: c.req.raw.headers,
// Bypass the 5-minute cookie cache so role changes take effect immediately.
query: { disableCookieCache: true },
});
if (!session) {
return c.json({ error: "Unauthorized" }, 401);
}
+22 -1
View File
@@ -1,8 +1,9 @@
import { drizzleAdapter } from "@better-auth/drizzle-adapter";
import { expo } from "@better-auth/expo";
import { APIError, createAuthMiddleware } from "better-auth/api";
import { setCookieCache } from "better-auth/cookies";
import { type BetterAuthOptions, betterAuth } from "better-auth/minimal";
import { admin, genericOAuth } from "better-auth/plugins";
import { admin, genericOAuth, type UserWithRole } from "better-auth/plugins";
import { claimInitialAdmin, isRegistrationOpen } from "@sofa/core/settings";
import { db } from "@sofa/db/client";
@@ -106,6 +107,26 @@ export const auth = betterAuth({
}
}
}),
after: createAuthMiddleware(async (ctx) => {
// The first user is promoted to admin by a create.after database hook, which
// Better Auth runs after the sign-up transaction commits — i.e. after the
// session cookie (including its cached user) was already written with
// role "user". Re-read the user and refresh the cache cookie if it changed.
const newSession = ctx.context.newSession;
if (!newSession) return;
try {
const fresh = (await ctx.context.internalAdapter.findUserById(
newSession.user.id,
)) as UserWithRole | null;
const cachedRole = (newSession.user as UserWithRole).role;
if (!fresh || fresh.role === cachedRole) return;
const user = { ...newSession.user, role: fresh.role };
await setCookieCache(ctx, { session: newSession.session, user }, false);
} catch (err) {
// Never turn a successful sign-in into an error over a cache refresh.
authLog.warn("Failed to refresh session cookie cache:", err);
}
}),
},
databaseHooks: {
user: {