Compare commits

..

2 commits

Author SHA1 Message Date
7343f993ee Merge pull request 'fix(web): resolve display name from userInfo, not just claims (#70)' (#89) from issue-70-harmonize-display-name into master 2026-05-30 18:52:22 +00:00
le king fu
3637879f90 fix(web): resolve display name from userInfo, not just claims (#70)
getAuthenticatedUser only read ID token claims, where `name` is often
absent, so the web app showed the user's email instead of their name
after SSO. Fetch the userInfo endpoint and resolve the display name with
the same fallback order as the vitrine (la-compagnie-maximus#80):
userInfo.name -> userInfo.username -> claims.name -> claims.username,
with the email fallback applied in the layout. Email now also prefers
userInfo over claims.

Single source of truth in auth.ts (only producer of `name`, consumed
solely by layout.tsx -> Header). layout.tsx and Header.tsx verified,
left unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 14:10:14 -04:00

View file

@ -4,16 +4,26 @@ import { logtoConfig } from './logto';
export const getAuthenticatedUser = cache(async () => {
try {
const context = await getLogtoContext(logtoConfig);
const context = await getLogtoContext(logtoConfig, { fetchUserInfo: true });
if (!context.isAuthenticated || !context.claims?.sub) {
return null;
}
const { claims, userInfo } = context;
// Mirror the vitrine's display-name resolution (la-compagnie-maximus#80):
// prefer the userInfo endpoint over ID token claims, falling back to email
// in the layout. The `name` claim is often absent from the ID token while
// present in userInfo, which is why the user saw their email instead of "Max".
return {
userId: context.claims.sub,
email: context.claims.email,
name: context.claims.name,
userId: claims.sub,
email: userInfo?.email || claims.email,
name:
userInfo?.name ||
userInfo?.username ||
claims.name ||
claims.username,
};
} catch (error) {
console.error('[auth] getLogtoContext error:', error);