apereo/cas · error · FailedLoginException
Radius authentication failed
Error message
Radius authentication failed ${e.message} What it means
The catch-all in RadiusAuthenticationHandler.authenticateUsernamePasswordInternal: any Throwable escaping the RADIUS exchange (network failure, protocol error, null response, etc.) is logged and rethrown as FailedLoginException('Radius authentication failed ' + cause message). The original exception type is lost, only its message survives.
Solutions
- Read the logged cause (LoggingUtils.error output) and fix the underlying RADIUS connectivity/configuration
- Check network reachability: telnet/nc to the RADIUS host and authentication port
- Verify the shared secret length and exact match; verify port 1812 (auth) vs 1813 (acct)
- Enable failoverOnException=true to fail over to other servers on exceptions
Example fix
// before (config) // cas.authn.radius.failover-exception=false // after // cas.authn.radius.failover-exception=true // and add a secondary server: cas.authn.radius.servers[1].address=radius2.example.com
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check reachability before auth attempt new Socket().connect(new InetSocketAddress(radiusHost, 1812), 3000);
Try / catch
try {
authHandler.authenticate(credential);
} catch (FailedLoginException e) {
if (e.getMessage() != null && !e.getMessage().isBlank()) {
// inspect embedded cause message: timeout / refused / secret
}
} Prevention
- Monitor RADIUS host/port reachability
- Use shared secrets >=16 characters
- Use correct auth (1812) vs acct (1813) ports
- Enable failoverOnException
When it happens
Trigger: RadiusClient throws inside RadiusUtils (socket timeout, unknown host, shared-secret/encoding error, response parse issue) and failoverOnException is false, so the exception bubbles into this catch block and is converted to FailedLoginException with e.getMessage().
Common situations: RADIUS server down or firewalled (timeout); DNS failure for the RADIUS hostname; shared secret too short (RFC 2865 requires >=16 chars) causing client-side rejection; wrong port (1812 auth vs 1813 accounting).
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
- 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 for user
- MultifactorAuthenticationProviderAbsentException
- failoverOnException enabled -- trying next server.
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/276103580955079b.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-radius/src/main/java/org/apereo/cas/adaptors/radius/authentication/handler/support/RadiusAuthenticationHandler.java:66
@Override
protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential,
final String originalPassword) throws GeneralSecurityException {
try {
val username = credential.getUsername();
val result = RadiusUtils.authenticate(username, credential.toPassword(), this.servers,
this.failoverOnAuthenticationFailure, this.failoverOnException, Optional.empty());
if (result.getKey() && result.getValue().isPresent()) {
val attributes = CollectionUtils.toMultiValuedMap(result.getValue().get());
return createHandlerResult(credential,
principalFactory.createPrincipal(username, attributes),
new ArrayList<>());
}
throw new FailedLoginException("Radius authentication failed for user " + username);
} catch (final Throwable e) {
LoggingUtils.error(LOGGER, e);
throw new FailedLoginException("Radius authentication failed " + e.getMessage());
}
}
}
View on GitHub (pinned to e7288fc434)