feat(auth) : sync Sudloh profiles and validate sessions
This commit is contained in:
+18
-3
@@ -19,6 +19,7 @@ import { isAuthorizedAdmin, type SessionUserLike } from "./authorization";
|
||||
import { HttpError } from "@/lib/security/http";
|
||||
import { consumeRateLimit } from "@/lib/security/rate-limit";
|
||||
import { sendAuthEmail } from "./email";
|
||||
import { bindSudlohSession, validateSudlohSession } from "./sudloh";
|
||||
|
||||
function required(name: string): string {
|
||||
const value = process.env[name];
|
||||
@@ -63,6 +64,11 @@ function createAuth() {
|
||||
},
|
||||
transaction: true,
|
||||
}),
|
||||
...(oidcOnly ? { databaseHooks: { session: { create: { after: async (
|
||||
session: { id: string; userId: string }, context: { path: string } | null,
|
||||
) => {
|
||||
if (context?.path.endsWith("/callback/sudloh")) await bindSudlohSession(session.userId, session.id);
|
||||
} } } } } : {}),
|
||||
baseURL: required("BETTER_AUTH_URL"),
|
||||
trustedOrigins: process.env.BETTER_AUTH_TRUSTED_ORIGINS
|
||||
?.split(",")
|
||||
@@ -125,6 +131,7 @@ function createAuth() {
|
||||
requireIdTokenVerification: true,
|
||||
requireEmailVerification: true,
|
||||
disableProviderLogout: true,
|
||||
overrideUserInfo: true,
|
||||
}] })] : []),
|
||||
...(!oidcOnly ? [emailOTP({
|
||||
sendVerificationOnSignUp: true,
|
||||
@@ -159,13 +166,22 @@ export interface AdminSession {
|
||||
session: { id: string };
|
||||
}
|
||||
|
||||
export const getVerifiedSession = cache(async () => {
|
||||
if (!hasAuthConfiguration()) return null;
|
||||
const session = await getAuth().api.getSession({ headers: await headers() });
|
||||
if (!session?.session) return null;
|
||||
if (isSudlohOidcEnabled() && process.env.SUDLOH_OIDC_ONLY === "true" &&
|
||||
!await validateSudlohSession(session.user.id, session.session.id)) return null;
|
||||
return session;
|
||||
});
|
||||
|
||||
export const getAdminSession = cache(async (): Promise<AdminSession | null> => {
|
||||
// Public pages can be prerendered without the runtime auth secret. In that
|
||||
// case the header simply omits the admin link; auth routes still fail loudly
|
||||
// through getAuth() when authentication is actually used.
|
||||
if (!hasAuthConfiguration()) return null;
|
||||
|
||||
const session = await getAuth().api.getSession({ headers: await headers() });
|
||||
const session = await getVerifiedSession();
|
||||
if (
|
||||
!session?.session ||
|
||||
!isAuthorizedAdmin(session.user)
|
||||
@@ -192,8 +208,7 @@ export async function requireAdmin(): Promise<AdminSession> {
|
||||
}
|
||||
|
||||
export const getCustomerSession = cache(async () => {
|
||||
if (!hasAuthConfiguration()) return null;
|
||||
const session = await getAuth().api.getSession({ headers: await headers() });
|
||||
const session = await getVerifiedSession();
|
||||
if (!session?.session) return null;
|
||||
return { user: session.user, session: { id: session.session.id } };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user