fix(auth): block OAuth linking for unverified accounts (#26598)
* fix(auth): sanitize unverified accounts during OAuth linking - Add AccountSanitizationService for secure account cleanup - Clear webhooks, API keys, credentials, and sessions for unverified accounts - Reset password and 2FA settings during OAuth conversion - Nullify redirect URLs on event types Only affects accounts that never completed email verification * fix(auth): block OAuth linking for unverified accounts Replace sanitization with simpler blocking approach: - Unverified CAL accounts cannot link to OAuth (Google/SAML) - Add user-friendly error message with recovery path - Remove AccountSanitizationService (no data loss risk)
This commit is contained in:
@@ -49,6 +49,8 @@ const ServerPage = async ({ searchParams }: PageProps) => {
|
||||
return t("account_managed_by_identity_provider_error", { provider: providerName });
|
||||
} else if (error === "saml-idp-not-authoritative") {
|
||||
return t("saml_idp_not_authoritative_error");
|
||||
} else if (error === "unverified-email") {
|
||||
return t("unverified_email_oauth_error");
|
||||
}
|
||||
return t("error_during_login") + (error ? ` Error code: ${error}` : "");
|
||||
};
|
||||
|
||||
@@ -4186,5 +4186,6 @@
|
||||
"audit_logs_permission_denied": "You do not have permission to view audit logs for this booking.",
|
||||
"audit_logs_permission_check_error": "An error occurred while checking permissions.",
|
||||
"account_already_exists_please_login": "An account with this email already exists. Please log in to accept the invitation.",
|
||||
"unverified_email_oauth_error": "Please verify your email address before signing in with Google or SAML. Sign in with your password to resend the verification email.",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -1075,6 +1075,11 @@ export const getOptions = ({
|
||||
existingUserWithEmail.identityProvider === IdentityProvider.CAL &&
|
||||
(idP === IdentityProvider.GOOGLE || idP === IdentityProvider.SAML)
|
||||
) {
|
||||
// Prevent account pre-hijacking: block OAuth linking for unverified accounts
|
||||
if (!existingUserWithEmail.emailVerified) {
|
||||
return "/auth/error?error=unverified-email";
|
||||
}
|
||||
|
||||
// Verify SAML IdP is authoritative before converting account
|
||||
if (idP === IdentityProvider.SAML) {
|
||||
const samlTenant = getSamlTenant();
|
||||
@@ -1086,7 +1091,6 @@ export const getOptions = ({
|
||||
|
||||
await prisma.user.update({
|
||||
where: { email: existingUserWithEmail.email },
|
||||
// also update email to the IdP email
|
||||
data: {
|
||||
email: user.email.toLowerCase(),
|
||||
identityProvider: idP,
|
||||
|
||||
Reference in New Issue
Block a user