package org.apereo.cas.authentication;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.CredentialNotFoundException;
import javax.security.auth.login.FailedLoginException;
/**
* This is {@link SurrogateAuthenticationAspect}.
*
* @author Jonathan Johnson
* @author Misagh Moayyed
* @since 5.1.0
*/
@Aspect
public class SurrogateAuthenticationAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(SurrogateAuthenticationAspect.class);
private final PrincipalFactory principalFactory;
private final SurrogateAuthenticationService surrogateAuthenticationService;
public SurrogateAuthenticationAspect(final PrincipalFactory principalFactory,
final SurrogateAuthenticationService surrogateAuthenticationService) {
this.principalFactory = principalFactory;
this.surrogateAuthenticationService = surrogateAuthenticationService;
}
/**
* Handle surrogate principal creation post authentication.
*
* @param jp the jp
* @param credential the credential
* @return the object
* @throws Throwable the throwable
*/
@Around(value = "execution(public org.apereo.cas.authentication.HandlerResult "
+ "org.apereo.cas.authentication.AuthenticationHandler.authenticate(..)) "
+ "&& args(credential)")
public Object handleSurrogate(final ProceedingJoinPoint jp, final Credential credential) throws Throwable {
try {
if (!credential.getClass().equals(SurrogateUsernamePasswordCredential.class)) {
return jp.proceed();
}
final SurrogateUsernamePasswordCredential surrogateCredentials = (SurrogateUsernamePasswordCredential) credential;
final String targetUserId = surrogateCredentials.getSurrogateUsername();
if (StringUtils.isBlank(targetUserId)) {
LOGGER.error("No surrogate username was specified as part of the credential");
throw new CredentialNotFoundException("Missing surrogate username in credential");
}
final HandlerResult result = (HandlerResult) jp.proceed();
LOGGER.debug("Authenticated [{}] will be checked for surrogate eligibility next...", result.getPrincipal());
if (this.surrogateAuthenticationService.canAuthenticateAs(targetUserId, result.getPrincipal())) {
final Principal principal = this.principalFactory.createPrincipal(targetUserId);
final AuthenticationHandler handler = AuthenticationHandler.class.cast(jp.getTarget());
return new DefaultHandlerResult(handler, new BasicCredentialMetaData(credential), principal);
}
LOGGER.error("Principal [{}] is unable/unauthorized to authenticate as [{}]", result.getPrincipal(), targetUserId);
throw new FailedLoginException();
} catch (final Throwable e) {
throw e;
}
}
}