package org.apereo.cas.config.support.authentication;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.adaptors.yubikey.YubiKeyAccountRegistry;
import org.apereo.cas.adaptors.yubikey.YubiKeyAuthenticationHandler;
import org.apereo.cas.adaptors.yubikey.YubiKeyMultifactorAuthenticationProvider;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
import org.apereo.cas.authentication.AuthenticationMetaDataPopulator;
import org.apereo.cas.authentication.metadata.AuthenticationContextAttributeMetaDataPopulator;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.support.mfa.MultifactorAuthenticationProperties;
import org.apereo.cas.services.DefaultMultifactorAuthenticationProviderBypass;
import org.apereo.cas.services.MultifactorAuthenticationProvider;
import org.apereo.cas.services.MultifactorAuthenticationProviderBypass;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.util.http.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* This is {@link YubiKeyAuthenticationEventExecutionPlanConfiguration}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
@Configuration("yubikeyAuthenticationEventExecutionPlanConfiguration")
public class YubiKeyAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer {
@Autowired
private CasConfigurationProperties casProperties;
@Autowired(required = false)
@Qualifier("yubiKeyAccountRegistry")
private YubiKeyAccountRegistry registry;
@Autowired
@Qualifier("servicesManager")
private ServicesManager servicesManager;
@Autowired
@Qualifier("noRedirectHttpClient")
private HttpClient httpClient;
@Bean
@RefreshScope
public AuthenticationMetaDataPopulator yubikeyAuthenticationMetaDataPopulator() {
final String authenticationContextAttribute = casProperties.getAuthn().getMfa().getAuthenticationContextAttribute();
return new AuthenticationContextAttributeMetaDataPopulator(authenticationContextAttribute,
yubikeyAuthenticationHandler(),
yubikeyAuthenticationProvider());
}
@Bean
@RefreshScope
public MultifactorAuthenticationProviderBypass yubikeyBypassEvaluator() {
return new DefaultMultifactorAuthenticationProviderBypass(casProperties.getAuthn().getMfa().getYubikey().getBypass());
}
@ConditionalOnMissingBean(name = "yubikeyPrincipalFactory")
@Bean
public PrincipalFactory yubikeyPrincipalFactory() {
return new DefaultPrincipalFactory();
}
@Bean
@RefreshScope
public YubiKeyAuthenticationHandler yubikeyAuthenticationHandler() {
final MultifactorAuthenticationProperties.YubiKey yubi = this.casProperties.getAuthn().getMfa().getYubikey();
if (StringUtils.isBlank(yubi.getSecretKey())) {
throw new IllegalArgumentException("Yubikey secret key cannot be blank");
}
if (yubi.getClientId() <= 0) {
throw new IllegalArgumentException("Yubikey client id is undefined");
}
final YubiKeyAuthenticationHandler handler = new YubiKeyAuthenticationHandler(yubi.getName(), servicesManager, yubikeyPrincipalFactory(),
yubi.getClientId(), yubi.getSecretKey(), this.registry);
if (!casProperties.getAuthn().getMfa().getYubikey().getApiUrls().isEmpty()) {
final String[] urls = casProperties.getAuthn().getMfa().getYubikey().getApiUrls().toArray(new String[]{});
handler.getClient().setWsapiUrls(urls);
}
return handler;
}
@Bean
@RefreshScope
public MultifactorAuthenticationProvider yubikeyAuthenticationProvider() {
final YubiKeyMultifactorAuthenticationProvider p = new YubiKeyMultifactorAuthenticationProvider(
yubikeyAuthenticationHandler(),
this.httpClient);
p.setBypassEvaluator(yubikeyBypassEvaluator());
p.setGlobalFailureMode(casProperties.getAuthn().getMfa().getGlobalFailureMode());
p.setOrder(casProperties.getAuthn().getMfa().getYubikey().getRank());
p.setId(casProperties.getAuthn().getMfa().getYubikey().getId());
return p;
}
@Override
public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
final MultifactorAuthenticationProperties.YubiKey yubi = casProperties.getAuthn().getMfa().getYubikey();
if (yubi.getClientId() > 0 && StringUtils.isNotBlank(yubi.getSecretKey())) {
plan.registerAuthenticationHandler(yubikeyAuthenticationHandler());
plan.registerMetadataPopulator(yubikeyAuthenticationMetaDataPopulator());
}
}
}