@ConditionalOnMissingBean(name = "mfaTrustStorageCleaner") @Bean public MultifactorAuthenticationTrustStorageCleaner mfaTrustStorageCleaner() { return new MultifactorAuthenticationTrustStorageCleaner( casProperties.getAuthn().getMfa().getTrusted(), mfaTrustEngine()); }
@Bean public Action mfaVerifyTrustAction() { return new MultifactorAuthenticationVerifyTrustAction(mfaTrustEngine.getIfAvailable(), deviceFingerprintStrategy.getIfAvailable(), casProperties.getAuthn().getMfa().getTrusted()); } }
@ConditionalOnMissingBean(name = BEAN_DEVICE_FINGERPRINT_STRATEGY) @Bean(BEAN_DEVICE_FINGERPRINT_STRATEGY) @RefreshScope public DeviceFingerprintStrategy deviceFingerprintStrategy(final List<DeviceFingerprintComponentExtractor> extractors) { val properties = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint(); return new DefaultDeviceFingerprintStrategy(extractors, properties.getComponentSeparator()); }
@ConditionalOnMissingBean(name = "yubiMultifactorTrustWebflowConfigurer") @Bean @DependsOn("defaultWebflowConfigurer") public CasWebflowConfigurer yubiMultifactorTrustWebflowConfigurer() { val deviceRegistrationEnabled = casProperties.getAuthn().getMfa().getTrusted().isDeviceRegistrationEnabled(); return new YubiKeyMultifactorTrustWebflowConfigurer(flowBuilderServices, deviceRegistrationEnabled, loginFlowDefinitionRegistry.getIfAvailable(), applicationContext, casProperties); }
@Bean @ConditionalOnEnabledEndpoint public MultifactorTrustedDevicesReportEndpoint mfaTrustedDevicesReportEndpoint() { return new MultifactorTrustedDevicesReportEndpoint(mfaTrustEngine(), casProperties.getAuthn().getMfa().getTrusted()); }
@Bean public Action mfaSetTrustAction() { return new MultifactorAuthenticationSetTrustAction(mfaTrustEngine.getIfAvailable(), deviceFingerprintStrategy.getIfAvailable(), casProperties.getAuthn().getMfa().getTrusted()); }
@Bean @RefreshScope public DeviceFingerprintComponentExtractor deviceFingerprintClientIpComponent() { val properties = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint().getClientIp(); if (properties.isEnabled()) { val component = new ClientIpDeviceFingerprintComponentExtractor(); component.setOrder(properties.getOrder()); return component; } LOGGER.info("The client ip is not being included when creating MFA Trusted Device Fingerprints"); return DeviceFingerprintComponentExtractor.noOp(); }
@Bean @RefreshScope public DeviceFingerprintComponentExtractor deviceFingerprintUserAgentComponent() { val properties = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint().getUserAgent(); if (properties.isEnabled()) { val component = new UserAgentDeviceFingerprintComponentExtractor(); component.setOrder(properties.getOrder()); return component; } LOGGER.info("User-Agent is not being included when creating MFA Trusted Device Fingerprints"); return DeviceFingerprintComponentExtractor.noOp(); }
@Bean @RefreshScope public DeviceFingerprintComponentExtractor deviceFingerprintCookieComponent() { val properties = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint().getCookie(); if (properties.isEnabled()) { val component = new CookieDeviceFingerprintComponentExtractor( deviceFingerprintCookieGenerator(), deviceFingerprintCookieRandomStringGenerator()); component.setOrder(properties.getOrder()); return component; } LOGGER.info("A persistent cookie is not being generated when creating MFA Trusted Device Fingerprints"); return DeviceFingerprintComponentExtractor.noOp(); }
@ConditionalOnMissingBean(name = BEAN_DEVICE_FINGERPRINT_COOKIE_GENERATOR) @Bean(BEAN_DEVICE_FINGERPRINT_COOKIE_GENERATOR) @RefreshScope public CookieRetrievingCookieGenerator deviceFingerprintCookieGenerator() { val cookie = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint().getCookie(); return new TrustedDeviceCookieRetrievingCookieGenerator( cookie.getName(), cookie.getPath(), cookie.getMaxAge(), cookie.isSecure(), cookie.getDomain(), cookie.isHttpOnly(), deviceFingerprintCookieValueManager() ); }
@ConditionalOnMissingBean(name = "mfaTrustEngine") @Bean @RefreshScope public MultifactorAuthenticationTrustStorage mfaTrustEngine() { val trusted = casProperties.getAuthn().getMfa().getTrusted(); final LoadingCache<String, MultifactorAuthenticationTrustRecord> storage = Caffeine.newBuilder() .initialCapacity(INITIAL_CACHE_SIZE) .maximumSize(MAX_CACHE_SIZE) .expireAfterWrite(trusted.getExpiration(), trusted.getTimeUnit()) .build(s -> { LOGGER.error("Load operation of the cache is not supported."); return null; }); storage.asMap(); val m = FunctionUtils.doIf(trusted.getJson().getLocation() != null, () -> { LOGGER.debug("Storing trusted device records inside the JSON resource [{}]", trusted.getJson().getLocation()); return new JsonMultifactorAuthenticationTrustStorage(trusted.getJson().getLocation()); }, () -> { LOGGER.warn("Storing trusted device records in runtime memory. Changes and records will be lost upon CAS restarts"); return new InMemoryMultifactorAuthenticationTrustStorage(storage); }).get(); m.setCipherExecutor(mfaTrustCipherExecutor()); return m; }
@ConditionalOnMissingBean(name = BEAN_DEVICE_FINGERPRINT_COOKIE_CIPHER_EXECUTOR) @Bean(BEAN_DEVICE_FINGERPRINT_COOKIE_CIPHER_EXECUTOR) @RefreshScope public CipherExecutor deviceFingerprintCookieCipherExecutor() { val crypto = casProperties.getAuthn().getMfa().getTrusted().getDeviceFingerprint().getCookie().getCrypto(); var enabled = crypto.isEnabled(); if (!enabled && StringUtils.isNotBlank(crypto.getEncryption().getKey()) && StringUtils.isNotBlank(crypto.getSigning().getKey())) { LOGGER.warn("Token encryption/signing is not enabled explicitly in the configuration, yet " + "signing/encryption keys are defined for operations. CAS will proceed to enable the cookie " + "encryption/signing functionality."); enabled = true; } if (enabled) { return new CookieDeviceFingerprintComponentCipherExecutor( crypto.getEncryption().getKey(), crypto.getSigning().getKey(), crypto.getAlg(), crypto.getSigning().getKeySize(), crypto.getEncryption().getKeySize()); } return CipherExecutor.noOp(); } }
@Bean @RefreshScope public CipherExecutor mfaTrustCipherExecutor() { val crypto = casProperties.getAuthn().getMfa().getTrusted().getCrypto(); if (crypto.isEnabled()) { return new MultifactorAuthenticationTrustCipherExecutor( crypto.getEncryption().getKey(), crypto.getSigning().getKey(), crypto.getAlg(), crypto.getSigning().getKeySize(), crypto.getEncryption().getKeySize()); } LOGGER.info("Multifactor trusted authentication record 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 " + "trusted authentication records for MFA"); return CipherExecutor.noOp(); }