apereo/cas · error · FailedLoginException
Radius authentication failed for user
Error message
Radius authentication failed for user
What it means
RadiusUtils.authenticateUsernamePassword throws FailedLoginException when every configured RADIUS server rejects the credentials and failoverOnAuthenticationFailure is false. The message carries the username that failed RADIUS authentication.
Solutions
- Verify the username/password credentials are correct against the RADIUS backend
- Check the RADIUS shared secret, server host/port and NAS identifier in cas.authn.radius.* settings
- Set failoverOnAuthenticationFailure=true (or add secondary servers) if transient rejects should fall over to another server
- Inspect the RADIUS server logs for the Access-Reject reason
Example fix
// before
throw new FailedLoginException("Radius authentication failed for user " + username);
// after (config-level fix): cas.authn.radius.failover-authentication-failure=true
// so RadiusUtils tries the next server instead of failing immediately Defensive patterns
Strategy: try-catch
Try / catch
try {
RadiusUtils.authenticateUsernamePassword(...);
} catch (FailedLoginException e) {
LOG.warn("RADIUS rejected user {}", username); // surface bad-credential UI
} catch (Exception e) {
LOG.error("RADIUS transport failure", e); // distinct retry path
} Prevention
- Test shared secret and NAS config with radtest before pointing CAS at the server
- Configure at least two RADIUS servers with failover enabled
- Monitor RADIUS server reject logs
When it happens
Trigger: RadiusClient authentication against all configured servers returns failure; failoverOnAuthenticationFailure=false so instead of trying the next server the method aborts with FailedLoginException for that username.
Common situations: Wrong password entered at the CAS login page; RADIUS shared secret mismatch or wrong NAS IP causing server-side Access-Reject; user unknown to the RADIUS backend; only one server configured so 'failover' never has a next server.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Radius authentication failed for user
- Radius authentication failed for user
- Radius authentication failed
- MultifactorAuthenticationProviderAbsentException
- AccountNotFoundException
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/504c36cf5ad5b295.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-radius-core/src/main/java/org/apereo/cas/adaptors/radius/RadiusUtils.java:51
public static Pair<Boolean, Optional<Map<String, Object>>> authenticate(final String username,
final String password,
final List<RadiusServer> servers,
final boolean failoverOnAuthenticationFailure,
final boolean failoverOnException,
final Optional state) throws Exception {
for (val radiusServer : servers) {
LOGGER.debug("Attempting to authenticate [{}] at [{}]", username, radiusServer);
try {
val response = radiusServer.authenticate(username, password, state);
if (response != null) {
val attributes = response.attributes()
.stream()
.collect(Collectors.toMap(RadiusAttribute::getAttributeName, RadiusAttribute::getValue, (__, b) -> b, () -> new HashMap<String, Object>()));
return Pair.of(Boolean.TRUE, Optional.of(attributes));
}
if (!failoverOnAuthenticationFailure) {
throw new FailedLoginException("Radius authentication failed for user " + username);
}
LOGGER.debug("failoverOnAuthenticationFailure enabled -- trying next server");
} catch (final Exception e) {
if (!failoverOnException) {
throw e;
}
LoggingUtils.warn(LOGGER, "failoverOnException enabled -- trying next server.", e);
}
}
return Pair.of(Boolean.FALSE, Optional.empty());
}
}
View on GitHub (pinned to e7288fc434)