{"record":{"id":"dc4c97596027bac1","repo":"theonedev/onedev","slug":"email-address-0-used-by-account-1","errorCode":null,"errorMessage":"Email address \"{0}\" used by account \"{1}\"","messagePattern":"Email address \"(.+?)\" used by account \"(.+?)\"","errorType":"exception","errorClass":"AuthenticationException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/web/page/security/SsoProcessPage.java","lineNumber":169,"sourceCode":"\t\t\t\t\t\t\tssoAccountService.delete(ssoAccount);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (authenticated.getEmail() != null) {\n\t\t\t\t\t\t\t\tvar emailAddress = emailAddressService.findByValue(authenticated.getEmail());\n\t\t\t\t\t\t\t\tif (emailAddress == null) {\n\t\t\t\t\t\t\t\t\temailAddress = new EmailAddress();\n\t\t\t\t\t\t\t\t\temailAddress.setValue(authenticated.getEmail());\n\t\t\t\t\t\t\t\t\temailAddress.setVerificationCode(null);\n\t\t\t\t\t\t\t\t\tuser.addEmailAddress(emailAddress);\n\t\t\t\t\t\t\t\t\temailAddressService.create(emailAddress);\n\t\t\t\t\t\t\t\t} else if (emailAddress.getOwner().equals(user)) {\n\t\t\t\t\t\t\t\t\temailAddress.setVerificationCode(null);\n\t\t\t\t\t\t\t\t\temailAddressService.update(emailAddress);\n\t\t\t\t\t\t\t\t} else if (!emailAddress.isVerified()) {\n\t\t\t\t\t\t\t\t\temailAddress.setVerificationCode(null);\n\t\t\t\t\t\t\t\t\tuser.addEmailAddress(emailAddress);\n\t\t\t\t\t\t\t\t\temailAddressService.update(emailAddress);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthrow new AuthenticationException(MessageFormat.format(_T(\"Email address \\\"{0}\\\" used by account \\\"{1}\\\"\"), authenticated.getEmail(), user.getName()));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsyncGroupsAndSshKeys(user, false);\n\t\t\t\t\t\t\treturn user;\n\t\t\t\t\t\t}\n\t\t\t\t\t} \n\t\t\t\t\tif (authenticated.getEmail() != null) {\n\t\t\t\t\t\tvar emailAddress = emailAddressService.findByValue(authenticated.getEmail());\n\t\t\t\t\t\tif (emailAddress != null) {\n\t\t\t\t\t\t\tvar user = emailAddress.getOwner();\n\t\t\t\t\t\t\tif (emailAddress.isVerified()) {\n\t\t\t\t\t\t\t\tif (user.getType() != ORDINARY) {\n\t\t\t\t\t\t\t\t\temailAddressService.delete(emailAddress);\n\t\t\t\t\t\t\t\t} else if (user.isDisabled()) {\n\t\t\t\t\t\t\t\t\tthrow new AuthenticationException(MessageFormat.format(_T(\"Email address \\\"{0}\\\" used by disabled account \\\"{1}\\\"\"), authenticated.getEmail(), user.getName()));\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tssoAccount = new SsoAccount();\n\t\t\t\t\t\t\t\t\tssoAccount.setUser(user);","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/page/security/SsoProcessPage.java#L151-L187","documentation":"During SSO (e.g. OIDC/SAML) login, OneDev matches the email address returned by the identity provider against existing verified email addresses. If the email belongs to a different ordinary user's account and is already verified there, the login is rejected with this AuthenticationException instead of silently binding the SSO subject to an account controlled by someone else.","triggerScenarios":"SSO callback in SsoProcessPage finds a verified email address equal to authenticated.getEmail() owned by another user (whose type is ORDINARY and account differs from the resolved user); the else branch at SsoProcessPage.java:169 throws.","commonSituations":"Two users in the identity provider share/claim the same email; an admin earlier registered the email under a local account; the IdP was reconfigured to send a different (already taken) email attribute such as mail vs. UPN; after merging identity providers emails collide.","solutions":["In the IdP, change the user's email attribute to the unique verified email that matches the OneDev account.","Free the email in OneDev: as admin, remove or unverify the conflicting email address on the other account.","Verify the SSO connector is configured to return the correct email claim (e.g. email vs. preferred_username).","If the other owner is a non-ordinary (system/build) user, update OneDev — that case auto-deletes the email instead of throwing; check user types in the DB."],"exampleFix":"// before (IdP claim mapping)\nemail -> userPrincipalName\n\n// after\nemail -> mail  // claim that carries the verified OneDev email","handlingStrategy":"validation","validationCode":"// Before linking SSO, check the email is not claimed by another account\nvar existing = OneDev.getInstance(EmailAddressService.class).findByEmailAddress(authenticated.getEmail());\nif (existing != null && existing.isVerified() && !existing.getOwner().equals(user))\n    throw new AuthenticationException(\"Email already bound to another account: \" + authenticated.getEmail());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guarantee email uniqueness in the identity provider before enabling SSO.","Map the correct, verified email claim in the SSO connector configuration.","Audit OneDev email addresses for duplicates before switching a login method to SSO."],"tags":["sso","email-conflict","authentication"],"backgroundTag":"email-already-in-use","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}