All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apereo.cas.config.CasOidcJwksJpaAutoConfiguration Maven / Gradle / Ivy

package org.apereo.cas.config;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.features.CasFeatureModule;
import org.apereo.cas.configuration.model.support.jpa.JpaConfigurationContext;
import org.apereo.cas.configuration.support.JpaBeans;
import org.apereo.cas.jpa.JpaBeanFactory;
import org.apereo.cas.jpa.JpaPersistenceProviderConfigurer;
import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreEntity;
import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreGeneratorService;
import org.apereo.cas.oidc.jwks.generator.jpa.OidcJpaJsonWebKeystoreGeneratorService;
import org.apereo.cas.util.CollectionUtils;
import org.apereo.cas.util.spring.beans.BeanCondition;
import org.apereo.cas.util.spring.beans.BeanContainer;
import org.apereo.cas.util.spring.beans.BeanSupplier;
import org.apereo.cas.util.spring.boot.ConditionalOnFeatureEnabled;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.jooq.lambda.Unchecked;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.integration.transaction.PseudoTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.spi.PersistenceProvider;
import javax.sql.DataSource;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * This is {@link CasOidcJwksJpaAutoConfiguration}.
 *
 * @author Misagh Moayyed
 * @since 6.5.0
 */
@EnableConfigurationProperties(CasConfigurationProperties.class)
@Slf4j
@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.OpenIDConnect, module = "jpa")
@AutoConfiguration
public class CasOidcJwksJpaAutoConfiguration {
    private static final BeanCondition CONDITION = BeanCondition.on("cas.authn.oidc.jwks.jpa.url");
    @Bean
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    @ConditionalOnMissingBean(name = "transactionManagerOidcJwks")
    public PlatformTransactionManager transactionManagerOidcJwks(
        final ConfigurableApplicationContext applicationContext,
        @Qualifier("oidcJwksEntityManagerFactory")
        final ObjectProvider emf) {

        return BeanSupplier.of(PlatformTransactionManager.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .and(() -> Objects.nonNull(emf.getIfAvailable()))
            .supply(() -> {
                val mgmr = new JpaTransactionManager();
                mgmr.setEntityManagerFactory(emf.getObject());
                return mgmr;
            })
            .otherwise(PseudoTransactionManager::new)
            .get();
    }

    @Bean
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    @ConditionalOnMissingBean(name = "oidcJwksJpaPersistenceProviderConfigurer")
    public JpaPersistenceProviderConfigurer oidcJwksJpaPersistenceProviderConfigurer(
        final ConfigurableApplicationContext applicationContext) {
        return BeanSupplier.of(JpaPersistenceProviderConfigurer.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> context -> {
                val entities = CollectionUtils.wrapList(OidcJsonWebKeystoreEntity.class.getName());
                context.getIncludeEntityClasses().addAll(entities);
            })
            .otherwiseProxy()
            .get();
    }

    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    @Bean
    public PersistenceProvider oidcJwksJpaPersistenceProvider(
        final ConfigurableApplicationContext applicationContext,
        final CasConfigurationProperties casProperties,
        @Qualifier(JpaBeanFactory.DEFAULT_BEAN_NAME) final JpaBeanFactory jpaBeanFactory) {
        return BeanSupplier.of(PersistenceProvider.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> jpaBeanFactory.newPersistenceProvider(casProperties.getAuthn().getOidc().getJwks().getJpa()))
            .otherwiseProxy()
            .get();
    }

    @Bean
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    @ConditionalOnMissingBean(name = "oidcJwksEntityManagerFactory")
    public FactoryBean oidcJwksEntityManagerFactory(
        @Qualifier("oidcJwksJpaPersistenceProvider")
        final PersistenceProvider oidcJwksPersistenceProvider,
        final ConfigurableApplicationContext applicationContext,
        @Qualifier("jpaOidcJwksVendorAdapter")
        final JpaVendorAdapter jpaOidcJwksVendorAdapter,
        @Qualifier("dataSourceOidcJwks")
        final DataSource dataSourceOidcJwks,
        @Qualifier("jpaOidcJwksPackagesToScan")
        final BeanContainer jpaOidcJwksPackagesToScan,
        @Qualifier(JpaBeanFactory.DEFAULT_BEAN_NAME)
        final JpaBeanFactory jpaBeanFactory,
        final CasConfigurationProperties casProperties) {
        return BeanSupplier.of(FactoryBean.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(Unchecked.supplier(() -> {
                val ctx = JpaConfigurationContext.builder()
                    .jpaVendorAdapter(jpaOidcJwksVendorAdapter)
                    .persistenceUnitName(OidcJpaJsonWebKeystoreGeneratorService.PERSISTENCE_UNIT_NAME)
                    .dataSource(dataSourceOidcJwks)
                    .packagesToScan(jpaOidcJwksPackagesToScan.toSet())
                    .persistenceProvider(oidcJwksPersistenceProvider)
                    .build();
                return jpaBeanFactory.newEntityManagerFactoryBean(ctx,
                    casProperties.getAuthn().getOidc().getJwks().getJpa());
            }))
            .otherwiseProxy()
            .get();
    }

    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    @Bean
    @ConditionalOnMissingBean(name = "jpaOidcJwksVendorAdapter")
    public JpaVendorAdapter jpaOidcJwksVendorAdapter(
        final ConfigurableApplicationContext applicationContext,
        @Qualifier(JpaBeanFactory.DEFAULT_BEAN_NAME)
        final JpaBeanFactory jpaBeanFactory,
        final CasConfigurationProperties casProperties) {
        return BeanSupplier.of(JpaVendorAdapter.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> jpaBeanFactory.newJpaVendorAdapter(casProperties.getJdbc()))
            .otherwiseProxy()
            .get();
    }

    @Bean
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    public BeanContainer jpaOidcJwksPackagesToScan(final ConfigurableApplicationContext applicationContext) {
        return BeanSupplier.of(BeanContainer.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> BeanContainer.of(CollectionUtils.wrapSet(OidcJsonWebKeystoreEntity.class.getPackage().getName())))
            .otherwise(BeanContainer::empty)
            .get();
    }

    @Bean
    @ConditionalOnMissingBean(name = "dataSourceOidcJwks")
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    public DataSource dataSourceOidcJwks(
        final ConfigurableApplicationContext applicationContext,
        final CasConfigurationProperties casProperties) {
        return BeanSupplier.of(DataSource.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> JpaBeans.newDataSource(casProperties.getAuthn().getOidc().getJwks().getJpa()))
            .otherwiseProxy()
            .get();
    }

    @Bean
    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
    public Supplier jpaJsonWebKeystoreGeneratorService(
        final ConfigurableApplicationContext applicationContext,
        @Qualifier("transactionManagerOidcJwks")
        final PlatformTransactionManager transactionManagerOidcJwks,
        final CasConfigurationProperties casProperties) {
        return BeanSupplier.of(Supplier.class)
            .when(CONDITION.given(applicationContext.getEnvironment()))
            .supply(() -> {
                val oidc = casProperties.getAuthn().getOidc();
                LOGGER.info("Managing JWKS via a relational database at [{}]", oidc.getJwks().getJpa().getUrl());
                val transactionTemplate = new TransactionTemplate(transactionManagerOidcJwks);
                return () -> new OidcJpaJsonWebKeystoreGeneratorService(oidc, transactionTemplate, applicationContext);
            })
            .otherwiseProxy()
            .get();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy