@Bean @RefreshScope @ConditionalOnMissingBean(name = "yubikeyBypassEvaluator") public MultifactorAuthenticationProviderBypass yubikeyBypassEvaluator() { return MultifactorAuthenticationUtils.newMultifactorAuthenticationProviderBypass(casProperties.getAuthn().getMfa().getYubikey().getBypass()); }
@RefreshScope @Bean @ConditionalOnMissingBean(name = "yubicoClient") public YubicoClient yubicoClient() { val 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"); } val client = YubicoClient.getClient(yubi.getClientId(), yubi.getSecretKey()); if (!yubi.getApiUrls().isEmpty()) { val urls = yubi.getApiUrls().toArray(ArrayUtils.EMPTY_STRING_ARRAY); client.setWsapiUrls(urls); } return client; }
@ConditionalOnMissingBean(name = "yubikeyAuthenticationEventExecutionPlanConfigurer") @Bean public AuthenticationEventExecutionPlanConfigurer yubikeyAuthenticationEventExecutionPlanConfigurer() { return plan -> { val yubi = casProperties.getAuthn().getMfa().getYubikey(); if (yubi.getClientId() > 0 && StringUtils.isNotBlank(yubi.getSecretKey())) { plan.registerAuthenticationHandler(yubikeyAuthenticationHandler()); plan.registerAuthenticationMetadataPopulator(yubikeyAuthenticationMetaDataPopulator()); plan.registerAuthenticationHandlerResolver(new ByCredentialTypeAuthenticationHandlerResolver(YubiKeyCredential.class)); } }; } }
@Override protected void doInitialize() { registerMultifactorProviderAuthenticationWebflow(getLoginFlow(), MFA_YUBIKEY_EVENT_ID, this.yubikeyFlowRegistry, casProperties.getAuthn().getMfa().getYubikey().getId()); } }
@Bean @RefreshScope @ConditionalOnMissingBean(name = "yubikeyAuthenticationHandler") public AuthenticationHandler yubikeyAuthenticationHandler() { val yubi = this.casProperties.getAuthn().getMfa().getYubikey(); return new YubiKeyAuthenticationHandler(yubi.getName(), servicesManager.getIfAvailable(), yubikeyPrincipalFactory(), yubicoClient(), yubiKeyAccountRegistry(), yubi.getOrder()); }
@Bean @RefreshScope @ConditionalOnMissingBean(name = "yubiKeyAccountRegistry") public YubiKeyAccountRegistry yubiKeyAccountRegistry() { val yubi = casProperties.getAuthn().getMfa().getYubikey(); if (yubi.getJsonFile() != null) { LOGGER.debug("Using JSON resource [{}] as the YubiKey account registry", yubi.getJsonFile()); val registry = new JsonYubiKeyAccountRegistry(yubi.getJsonFile(), yubiKeyAccountValidator()); registry.setCipherExecutor(yubikeyAccountCipherExecutor.getIfAvailable()); return registry; } if (yubi.getAllowedDevices() != null) { LOGGER.debug("Using statically-defined devices for [{}] as the YubiKey account registry", yubi.getAllowedDevices().keySet()); val registry = new WhitelistYubiKeyAccountRegistry(yubi.getAllowedDevices(), yubiKeyAccountValidator()); registry.setCipherExecutor(yubikeyAccountCipherExecutor.getIfAvailable()); return registry; } LOGGER.warn("All credentials are considered eligible for YubiKey authentication. " + "Consider providing an account registry implementation via [{}]", YubiKeyAccountRegistry.class.getName()); val registry = new OpenYubiKeyAccountRegistry(new DefaultYubiKeyAccountValidator(yubicoClient())); registry.setCipherExecutor(yubikeyAccountCipherExecutor.getIfAvailable()); return registry; }
@Bean @RefreshScope public MultifactorAuthenticationProvider yubikeyMultifactorAuthenticationProvider() { val yubi = casProperties.getAuthn().getMfa().getYubikey(); val p = new YubiKeyMultifactorAuthenticationProvider(yubicoClient(), httpClient.getIfAvailable()); p.setBypassEvaluator(yubikeyBypassEvaluator()); p.setFailureMode(yubi.getFailureMode()); p.setOrder(yubi.getRank()); p.setId(yubi.getId()); return p; }
@Bean @RefreshScope public CipherExecutor yubikeyAccountCipherExecutor() { val crypto = casProperties.getAuthn().getMfa().getYubikey().getCrypto(); if (crypto.isEnabled()) { return new YubikeyAccountCipherExecutor( crypto.getEncryption().getKey(), crypto.getSigning().getKey(), crypto.getAlg(), crypto.getSigning().getKeySize(), crypto.getEncryption().getKeySize()); } LOGGER.info("YubiKey account encryption/signing is turned off and " + "MAY NOT be safe in a production environment. " + "Consider using other choices to handle encryption, signing and verification of " + "YubiKey accounts for MFA"); return CipherExecutor.noOp(); }