apereo/cas · error · FailedLoginException
not in allowed range.
Error message
not in allowed range.
What it means
RemoteAddressAuthenticationHandler authenticates purely by checking whether the client's IP address falls within the configured allowed IP ranges. When the address is known but outside every configured RemoteAddressIpRangePattern (or the host is unresolvable, swallowed as a debug UnknownHost), it throws FailedLoginException '<address> not in allowed range.'
Solutions
- Add the client's actual IP/subnet to cas.authn.remote-address.ip-range (e.g., 192.168.1.0/24)
- If behind a proxy, ensure the credential receives the forwarded client IP (configure the proxy/extractor to use X-Forwarded-For), not the proxy's address
- Verify range syntax in the configured RemoteAddressIpRangePattern entries (correct CIDR/netmask format)
- If a hostname was configured, confirm DNS resolution on the CAS host — unresolvable hosts are silently treated as failures
Example fix
// before (application.properties) cas.authn.remote-address.ip-range=10.0.0.0/24 // after — include the actual client subnet cas.authn.remote-address.ip-range=10.0.0.0/24,192.168.10.0/24
Defensive patterns
Strategy: validation
Validate before calling
// pre-check before invoking the handler
val ranges = casProps.getAuthn().getRemoteAddress().getIpRange();
val clientIp = request.getRemoteAddr();
if (ranges.stream().noneMatch(r -> new RemoteAddressIpRangePattern(r).matches(clientIp)))
LOGGER.warn("Client {} is outside configured remote-address ranges", clientIp); Try / catch
try {
result = remoteAddressHandler.authenticate(remoteCredential);
} catch (FailedLoginException e) {
return fallbackToPrimaryAuthHandler(credential);
} Prevention
- Configure ranges to cover all client subnets, including renumbering headroom
- Behind a proxy/LB, propagate the real client IP (X-Forwarded-For) into the credential
- Validate CIDR syntax when adding ip-range entries
- Prefer IP literals over hostnames, or guarantee DNS resolution on CAS hosts
When it happens
Trigger: authenticate() resolves the RemoteAuthenticationCredential's remote address, iterates the configured cas.authn.remote-address.ip-range patterns, none matches (or UnknownHostException is caught and dropped through), so the final statement throws FailedLoginException.
Common situations: CAS deployed behind a reverse proxy so the credential carries the proxy/load-balancer IP instead of the client's (X-Forwarded-For not honored); subnet/CIDR configured too narrowly; network renumbering moving clients out of the allowed range; DNS unable to resolve when the entry was configured as a hostname.
Related errors
- Grouper WS did not respond successfully. Ensure your…
- Authentication handler is disabled
- No user can be accepted because none is defined
- not found in backing map.
- Unable to authenticate
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/1d1d7d3adecda8f5.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-generic-remote-webflow/src/main/java/org/apereo/cas/adaptors/generic/remote/RemoteAddressAuthenticationHandler.java:93
LOGGER.debug("[{}] is in [{}]/[{}]", ip, network, netmask);
return true;
}
@Override
public AuthenticationHandlerExecutionResult authenticate(final Credential credential, final Service service) throws Throwable {
val addressCredential = (RemoteAuthenticationCredential) credential;
if (this.inetNetmask != null && this.inetNetworkRange != null) {
try {
val inetAddress = InetAddress.getByName(addressCredential.getRemoteAddress().trim());
if (containsAddress(this.inetNetworkRange, this.inetNetmask, inetAddress)) {
return new DefaultAuthenticationHandlerExecutionResult(this, addressCredential,
principalFactory.createPrincipal(addressCredential.getId()));
}
} catch (final UnknownHostException e) {
LOGGER.debug("Unknown host [{}]", addressCredential.getRemoteAddress());
}
}
throw new FailedLoginException(addressCredential.getRemoteAddress() + " not in allowed range.");
}
@Override
public boolean supports(final Credential credential) {
return credential instanceof RemoteAuthenticationCredential;
}
@Override
public boolean supports(final Class<? extends Credential> clazz) {
return RemoteAuthenticationCredential.class.isAssignableFrom(clazz);
}
/**
* Sets ip network range.
*
* @param ipAddressRange the IP address range that should be allowed trusted logins
*/
public void configureIpNetworkRange(final String ipAddressRange) {View on GitHub (pinned to e7288fc434)