fix(encryptid): persist verified email and fix OIDC re-prompt bug
Normalize emails to lowercase at all setUserEmail() call sites so case mismatches no longer break the OIDC allowedEmails check. Split the authorize error into email_required (shows verification form) vs access_denied (shows error message) so users with a verified email are never re-prompted unnecessarily. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fb9448681c
commit
82123937b3
|
|
@ -581,7 +581,7 @@ app.post('/api/register/complete', async (c) => {
|
|||
|
||||
// Set recovery email if provided during registration
|
||||
if (email && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
await setUserEmail(userId, email);
|
||||
await setUserEmail(userId, email.trim().toLowerCase());
|
||||
}
|
||||
|
||||
// Resolve the RP ID from the caller's origin
|
||||
|
|
@ -1203,7 +1203,7 @@ app.post('/api/account/email/verify', async (c) => {
|
|||
}
|
||||
|
||||
await markRecoveryTokenUsed(tokenKey);
|
||||
await setUserEmail(claims.sub as string, email);
|
||||
await setUserEmail(claims.sub as string, email.trim().toLowerCase());
|
||||
|
||||
return c.json({ success: true, email });
|
||||
});
|
||||
|
|
@ -1433,8 +1433,9 @@ app.post('/api/recovery/email/set', async (c) => {
|
|||
return c.json({ error: 'Valid email required' }, 400);
|
||||
}
|
||||
|
||||
await setUserEmail(payload.sub as string, email);
|
||||
return c.json({ success: true, email });
|
||||
const normalizedEmail = email.trim().toLowerCase();
|
||||
await setUserEmail(payload.sub as string, normalizedEmail);
|
||||
return c.json({ success: true, email: normalizedEmail });
|
||||
} catch {
|
||||
return c.json({ error: 'Unauthorized' }, 401);
|
||||
}
|
||||
|
|
@ -5441,10 +5442,14 @@ app.post('/oidc/authorize', async (c) => {
|
|||
if (!user) {
|
||||
return c.json({ error: 'User not found' }, 404);
|
||||
}
|
||||
const userEmail = user.email || user.profile_email;
|
||||
const userEmail = (user.email || user.profile_email || '').toLowerCase();
|
||||
if (client.allowedEmails.length > 0) {
|
||||
if (!userEmail || !client.allowedEmails.includes(userEmail)) {
|
||||
return c.json({ error: 'access_denied', message: 'You do not have access to this application.' }, 403);
|
||||
const allowedLower = client.allowedEmails.map((e: string) => e.toLowerCase());
|
||||
if (!userEmail) {
|
||||
return c.json({ error: 'email_required', message: 'Email verification is required for this application.' }, 403);
|
||||
}
|
||||
if (!allowedLower.includes(userEmail)) {
|
||||
return c.json({ error: 'access_denied', message: 'Your email is not authorized for this application.' }, 403);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5906,8 +5911,8 @@ function oidcAuthorizePage(appName: string, clientId: string, redirectUri: strin
|
|||
const authorizeResult = await authorizeRes.json();
|
||||
|
||||
if (authorizeResult.error) {
|
||||
if (authorizeResult.error === 'access_denied') {
|
||||
// Show email verification flow instead of dead-end error
|
||||
if (authorizeResult.error === 'email_required') {
|
||||
// User has no verified email — show email verification form
|
||||
loginBtn.style.display = 'none';
|
||||
statusEl.style.display = 'none';
|
||||
verifySection.style.display = 'block';
|
||||
|
|
|
|||
Loading…
Reference in New Issue