theonedev/onedev · error · AuthenticationException

Unsolicited OIDC authentication response

Error message

Unsolicited OIDC authentication response

What it means

After a successful SSO login, SsoProcessPage.afterLogin redirects to the URL stored in the session under SESSION_ATTR_REDIRECT_URL, which the login flow sets when it initiates SSO. If that attribute is missing/blank when the OIDC response arrives, the page assumes the response was not solicited by this server and throws this AuthenticationException.

Source

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

		var groupNames = authenticated.getGroupNames();
		if (forNewUser && groupNames == null) 
			groupNames = new HashSet<String>();
		if (groupNames != null) {
			if (getProvider().getDefaultGroup() != null)
				groupNames.add(getProvider().getDefaultGroup().getName());
			if (settingService.getSecuritySetting().getDefaultGroupName() != null)
				groupNames.add(settingService.getSecuritySetting().getDefaultGroupName());
			membershipService.syncMemberships(user, groupNames);
		}
		
		if (authenticated.getSshKeys() != null)
			sshKeyService.syncSshKeys(user, authenticated.getSshKeys());									
	}

	private void afterLogin(User user) {		
		String redirectUrlAfterLogin = (String) getSession().getAttribute(SESSION_ATTR_REDIRECT_URL);
		if (StringUtils.isBlank(redirectUrlAfterLogin))
			throw new AuthenticationException(_T("Unsolicited OIDC authentication response"));

		SecurityUtils.getSubject().runAs(user.getPrincipals());
		WebSession.get().setSsoLogoutUrl(
				getProvider().getConnector().buildLogoutUrl(getProvider().getName()));

		throw new RedirectToUrlException(redirectUrlAfterLogin);	
	}

	private SsoProvider getProvider() {
		return providerModel.getObject();
	}

	@Override
	protected void onInitialize() {
		super.onInitialize();

		List<Tab> tabs = new ArrayList<>();
					

View on GitHub (pinned to d44925c47c)

Solutions

  1. Restart the SSO login from OneDev (click the login link again) so a fresh session and redirect URL are established.
  2. Ensure the callback URL is only reached via the IdP redirect initiated from OneDev; remove bookmarks/probes to the callback endpoint.
  3. Fix session persistence on the server (sticky sessions / shared session store) if sessions are being lost behind a proxy.
  4. Increase OneDev session timeout or reduce IdP login-page dwell time.

Example fix

// before: bookmarked direct access to callback
GET https://onedev/~sso/process?code=...

// after: always start from OneDev
GET https://onedev/  -> click 'Sign in with SSO'
Defensive patterns

Strategy: retry

Validate before calling

// Client-side: only call the callback via the IdP redirect; check session cookie exists
if (!cookies.contains("onedev-session")) restartLoginFromOneDev();

Try / catch

try {
    ssoLogin();
} catch (AuthenticationException e) {
    if (e.getMessage().contains("Unsolicited")) {
        // session lost: restart the SSO flow from scratch
        restartLoginFromOneDev();
    } else throw e;
}

Prevention

When it happens

Trigger: OIDC provider posts the authentication response to the callback URL while no OneDev session attribute 'redirectUrlAfterLogin' exists — e.g. session expired between request start and callback, callback URL was hit directly (bookmarked/health-check), or the response is replayed/duplicated.

Common situations: User sat on the IdP login page long enough for the OneDev session to expire; reverse proxy/load balancer session stickiness issues losing the Wicket session; a monitoring probe or crawler hitting the callback URL; user re-submitting the OIDC response via browser refresh.

Understand the failure class

Related errors


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