refactor(frontend): make SessionUser fields non-null and normalize claims at boundary

This commit is contained in:
2026-07-05 23:45:18 +02:00
parent 539fad1d22
commit b9d14412e6
4 changed files with 27 additions and 14 deletions
+2 -2
View File
@@ -35,10 +35,10 @@
<span
class="grid h-7 w-7 place-items-center rounded-full bg-neutral-700 text-xs font-semibold uppercase"
>
{(user.name ?? user.email ?? '?').charAt(0)}
{user.name.charAt(0)}
</span>
{/if}
<span class="hidden sm:inline">{user.name ?? user.email}</span>
<span class="hidden sm:inline">{user.name}</span>
</a>
<form method="POST" action="/logout">
<button
+20 -5
View File
@@ -70,17 +70,32 @@ export async function decodeSession(token: string | undefined): Promise<Session
}
}
function claimString(value: unknown): string | undefined {
return typeof value === 'string' && value.length > 0 ? value : undefined;
}
export function toSessionUser(claims: Record<string, unknown>, fallback?: SessionUser): SessionUser {
const sub = claimString(claims.sub) ?? fallback?.sub ?? '';
return {
sub,
name:
claimString(claims.name) ??
claimString(claims.preferred_username) ??
fallback?.name ??
claimString(claims.email) ??
sub,
email: claimString(claims.email) ?? fallback?.email ?? '',
picture: claimString(claims.picture) ?? fallback?.picture ?? ''
};
}
export async function refreshSession(session: Session): Promise<Session | null> {
if (!session.refreshToken) return null;
try {
const config = await getOidcConfig();
const tokens = await client.refreshTokenGrant(config, session.refreshToken);
const claims = tokens.claims();
return {
sub: session.sub,
name: (claims?.name as string | undefined) ?? session.name,
email: (claims?.email as string | undefined) ?? session.email,
picture: (claims?.picture as string | undefined) ?? session.picture,
...toSessionUser(tokens.claims() ?? {}, session),
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token ?? session.refreshToken,
idToken: tokens.id_token ?? session.idToken,
+3 -3
View File
@@ -1,6 +1,6 @@
export interface SessionUser {
sub: string;
name?: string;
email?: string;
picture?: string;
name: string;
email: string;
picture: string;
}