package org.apereo.cas.adaptors.radius.authentication.handler.support; import org.apache.commons.lang3.tuple.Pair; import org.apereo.cas.adaptors.radius.RadiusServer; import org.apereo.cas.adaptors.radius.RadiusUtils; import org.apereo.cas.authentication.HandlerResult; import org.apereo.cas.authentication.PreventedException; import org.apereo.cas.authentication.UsernamePasswordCredential; import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.services.ServicesManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.login.FailedLoginException; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; /** * Authentication Handler to authenticate a user against a RADIUS server. * * @author Scott Battaglia * @since 3.0.0 */ public class RadiusAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RadiusAuthenticationHandler.class); /** * Array of RADIUS servers to authenticate against. */ private final List<RadiusServer> servers; /** * Determines whether to fail over to the next configured RadiusServer if * there was an exception. */ private final boolean failoverOnException; /** * Determines whether to fail over to the next configured RadiusServer if * there was an authentication failure. */ private final boolean failoverOnAuthenticationFailure; /** * Instantiates a new Radius authentication handler. * * @param name the name * @param servicesManager the services manager * @param principalFactory the principal factory * @param servers RADIUS servers to authenticate against. * @param failoverOnException boolean on whether to failover or not. * @param failoverOnAuthenticationFailure boolean on whether to failover or not. */ public RadiusAuthenticationHandler(final String name, final ServicesManager servicesManager, final PrincipalFactory principalFactory, final List<RadiusServer> servers, final boolean failoverOnException, final boolean failoverOnAuthenticationFailure) { super(name, servicesManager, principalFactory, null); LOGGER.debug("Using [{}]", getClass().getSimpleName()); this.servers = servers; this.failoverOnException = failoverOnException; this.failoverOnAuthenticationFailure = failoverOnAuthenticationFailure; } @Override protected HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential, final String originalPassword) throws GeneralSecurityException, PreventedException { try { final String username = credential.getUsername(); final Pair<Boolean, Optional<Map<String, Object>>> result = RadiusUtils.authenticate(username, credential.getPassword(), this.servers, this.failoverOnAuthenticationFailure, this.failoverOnException); if (result.getKey()) { return createHandlerResult(credential, this.principalFactory.createPrincipal(username, result.getValue().get()), new ArrayList<>()); } throw new FailedLoginException("Radius authentication failed for user " + username); } catch (final Exception e) { throw new FailedLoginException("Radius authentication failed " + e.getMessage()); } } }