theonedev/onedev · error · AuthenticationException

Email address "{0}" used by account "{1}"

Error message

Email address "{0}" used by account "{1}"

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/web/page/security/SsoProcessPage.java:169

							ssoAccountService.delete(ssoAccount);
						} else {
							if (authenticated.getEmail() != null) {
								var emailAddress = emailAddressService.findByValue(authenticated.getEmail());
								if (emailAddress == null) {
									emailAddress = new EmailAddress();
									emailAddress.setValue(authenticated.getEmail());
									emailAddress.setVerificationCode(null);
									user.addEmailAddress(emailAddress);
									emailAddressService.create(emailAddress);
								} else if (emailAddress.getOwner().equals(user)) {
									emailAddress.setVerificationCode(null);
									emailAddressService.update(emailAddress);
								} else if (!emailAddress.isVerified()) {
									emailAddress.setVerificationCode(null);
									user.addEmailAddress(emailAddress);
									emailAddressService.update(emailAddress);
								} else {
									throw new AuthenticationException(MessageFormat.format(_T("Email address \"{0}\" used by account \"{1}\""), authenticated.getEmail(), user.getName()));
								}
							}
							syncGroupsAndSshKeys(user, false);
							return user;
						}
					} 
					if (authenticated.getEmail() != null) {
						var emailAddress = emailAddressService.findByValue(authenticated.getEmail());
						if (emailAddress != null) {
							var user = emailAddress.getOwner();
							if (emailAddress.isVerified()) {
								if (user.getType() != ORDINARY) {
									emailAddressService.delete(emailAddress);
								} else if (user.isDisabled()) {
									throw new AuthenticationException(MessageFormat.format(_T("Email address \"{0}\" used by disabled account \"{1}\""), authenticated.getEmail(), user.getName()));
								} else {
									ssoAccount = new SsoAccount();
									ssoAccount.setUser(user);

View on GitHub (pinned to d44925c47c)

Solutions

  1. In the IdP, change the user's email attribute to the unique verified email that matches the OneDev account.
  2. Free the email in OneDev: as admin, remove or unverify the conflicting email address on the other account.
  3. Verify the SSO connector is configured to return the correct email claim (e.g. email vs. preferred_username).
  4. 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.

Example fix

// before (IdP claim mapping)
email -> userPrincipalName

// after
email -> mail  // claim that carries the verified OneDev email
Defensive patterns

Strategy: validation

Validate before calling

// Before linking SSO, check the email is not claimed by another account
var existing = OneDev.getInstance(EmailAddressService.class).findByEmailAddress(authenticated.getEmail());
if (existing != null && existing.isVerified() && !existing.getOwner().equals(user))
    throw new AuthenticationException("Email already bound to another account: " + authenticated.getEmail());

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/dc4c97596027bac1. Report an issue: GitHub.