[keycloak-user] UserStorageProvider for an external database

Bart Lievens bart.lievens at unifiedpost.com
Mon Dec 10 06:05:23 EST 2018


Hello,
I think you are not understanding the solution fully,  the configuration values are not in code at all.
The static strings are just the names of the configuration variables, not actual username or password.
They can be set from Keycloak admin pages (User Federation) or  as part of the realm configuration json,  you should also be able to inject them that way using the Admin API’s.
The values will be store in the keycloak db like other configurations in keycloak.


> On 10 Dec 2018, at 10:40, Steffen Kreutz <brushmate at gmail.com> wrote:
> 
> Hi,
> 
> that's surely possible, but I absolutely don't want to have the configuration in my code (especially not the password). Thus I somehow have to inject the configuration 'from the outside'.
> 
> Best,
> 
> Steffen
> 
> Am So., 9. Dez. 2018 um 13:27 Uhr schrieb Bart Lievens <bart.lievens at unifiedpost.com <mailto:bart.lievens at unifiedpost.com>>:
> Hello, 
> 
> I solved the problem not by adding a datasource to WildFly but by adding the configuration parameters to the UserStorageProviderFactory 
> and creating the EntityManager inside the UserStorageProviderFactory and then passing it on when creating a UserStorageProvider.
> 
> My UserStorageProviderFactory looks something like (with 4.6.0.Final & 4.7.0.Final) :
> public class ExternalUserStorageProviderFactory implements UserStorageProviderFactory<ExternalUserStorageProvider> {
>     private static final transient Logger logger = LoggerFactory.getLogger(ExternalUserStorageProviderFactory.class);
>     private static final String CONF_NAME_JDBC_URL = "jdbcUrl";
>     private static final String CONF_NAME_JDBC_USER = "user";
>     private static final String CONF_NAME_JDBC_PASSWORD = "password";
> 
>     protected static final List<ProviderConfigProperty> configMetadata;
>     private Map<String, EntityManager> entityManagers = new HashMap<>();
> 
>     static {
>         ProviderConfigurationBuilder builder = ProviderConfigurationBuilder.create();
>         builder.property().name(CONF_NAME_JDBC_URL).type(ProviderConfigProperty.STRING_TYPE).label("Jdbc Url")
>                .defaultValue("jdbc:postgresql://host:port/database")
>                .helpText("Postgres JDBC Connection URL to external user db")
>                .add();
>         builder.property().name(CONF_NAME_JDBC_USER).type(ProviderConfigProperty.STRING_TYPE).label("Jdbc User")
>                .helpText("JDBC Connection User")
>                .add();
>         builder.property().name(CONF_NAME_JDBC_PASSWORD).type(ProviderConfigProperty.PASSWORD).label("Jdbc Password")
>                .helpText("JDBC Connection Password")
>                .add();
>         configMetadata = builder.build();
>     }
> 
>     @Override
>     public List<ProviderConfigProperty> getConfigProperties() {
>         return configMetadata;
>     }
> 
>     @Override
>     public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel componentModel) throws ComponentValidationException {
>         if (componentModel.getConfig().getFirst(CONF_NAME_JDBC_URL) == null
>             || componentModel.getConfig().getFirst(CONF_NAME_JDBC_USER) == null
>             || componentModel.getConfig().getFirst(CONF_NAME_JDBC_PASSWORD) == null) {
>             throw new ComponentValidationException("The jdbc Url, User and Password are requirec");
>         }
>         try {
>             createEntityManager(componentModel);
>         } catch (Exception e) {
>             logger.warn("Invalid configuration {}", e.getCause() == null ? e.getMessage() : e.getCause().getMessage());
>             throw new ComponentValidationException("Could not setup jdbc connection : " + (e.getCause() == null ? e.getMessage() : e.getCause().getMessage()));
>         }
>     }
> 
>     @Override
>     public ExternalUserStorageProvider create(KeycloakSession session, ComponentModel model) {
>         try {
>             if (entityManagers.get(model.getId()) == null) {
>                 createEntityManager(model);
>             }
>             return new ExternalUserStorageProvider(entityManagers.get(model.getId()), model, session);
>         } catch (Exception e) {
>             throw new RuntimeException(e);
>         }
>     }
> 
>     @Override
>     public String getId() {
>         return "external-user-db";
>     }
> 
>     @Override
>     public String getHelpText() {
>         return "External User Database Storage Provider";
>     }
> 
>     private void createEntityManager(ComponentModel model) {
>         logger.info <http://logger.info/>("creating entityManager for {}", model.getName());
>         Properties properties = getProperties(model);
>         EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("external-user-storage", properties);
>         entityManagers.put(model.getId(), entityManagerFactory.createEntityManager());
>     }
> 
>     private Properties getProperties(ComponentModel model) {
>         Properties properties = new Properties();
>         // Add class loader needed to find persistence.xml
>         properties.put(AvailableSettings.CLASSLOADERS, Arrays.asList(this.getClass().getClassLoader()));
>         // Set JPA properties
>         properties.put(AvailableSettings.JPA_PERSISTENCE_PROVIDER, HibernatePersistenceProvider.class.getName());
>         properties.put(AvailableSettings.JPA_TRANSACTION_TYPE, PersistenceUnitTransactionType.JTA.name <http://persistenceunittransactiontype.jta.name/>());
>         // postgresql jdbc connection config 
>         properties.put(AvailableSettings.JPA_JDBC_DRIVER, "org.postgresql.Driver");
>         properties.put(AvailableSettings.JPA_JDBC_URL, EnvUtil.replace(model.getConfig().getFirst(CONF_NAME_JDBC_URL)));
>         properties.put(AvailableSettings.JPA_JDBC_USER, EnvUtil.replace(model.getConfig().getFirst(CONF_NAME_JDBC_USER)));
>         properties.put(AvailableSettings.JPA_JDBC_PASSWORD, EnvUtil.replace(model.getConfig().getFirst(CONF_NAME_JDBC_PASSWORD)));
>         // hibernate
>         properties.put(AvailableSettings.DIALECT, org.hibernate.dialect.PostgreSQL95Dialect.class.getName());
>         properties.put(AvailableSettings.SHOW_SQL, Boolean.FALSE);
>         // set JTA properties
>         properties.put(AvailableSettings.JTA_PLATFORM, JBossAppServerJtaPlatform.class.getName());
>         return properties;
>     }
> }
> 
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org <mailto:keycloak-user at lists.jboss.org>
> https://lists.jboss.org/mailman/listinfo/keycloak-user <https://lists.jboss.org/mailman/listinfo/keycloak-user>

-- 
Bart Lievens | Manager Classic Taskforce
 
UnifiedPost Group
Avenue Reine Astrid 92A, 1310 La Hulpe, Belgium
T: +32 2 634 06 28 | M: +32 495 279 559
W: www.unifiedpost.com <http://www.unifiedpost.com/> | E: Bart.Lievens at unifiedpost.com <mailto:Bart.Lievens at unifiedpost.com> 






More information about the keycloak-user mailing list