Hello,
I'm having some trouble registering a custom SPI using modules and I've been struggling for several days with no success at all. If I use the keycloak deployer, I'm able to see my provider, but it crashes because it cannot find some dependencies. In the documentation it sais "If you are creating a custom SPI you will need to deploy it as a module, otherwise we recommend using the Keycloak deployer approach."
I run keycloak in a docker container. Here's my docker compose file:
docker-compose.yml
version: '3'
volumes:
postgres_data:
driver: local
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
keycloak:
environment:
DB_VENDOR: POSTGRES
DB_ADDR: postgres
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_USER: cristina
KEYCLOAK_PASSWORD: cristina
ports:
- 8080:8080
depends_on:
- postgres
I've created a java project from scratch with maven. This is my pom.xml:
pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>org.cristina</groupId>
<artifactId>cristina-validator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<finalName>cristinaValidator</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptors>
<descriptor>src/assembly/assemblyModule.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>12.0.2</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>12.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<version>12.0.2</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>12.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
<version>4.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-spi</artifactId>
<version>12.0.2</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
I've created the package org.cristina.authentication.forms inside src/main/java. Inside this folder, I've added the java class CristinaRegistration.java, which is an implementation of FormAction and FormActionFactory.
CristinaRegistration.java
package org.cristina.authentication.forms;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.Config;
import org.keycloak.authentication.FormAction;
import org.keycloak.authentication.FormActionFactory;
import org.keycloak.authentication.FormContext;
import org.keycloak.authentication.forms.RegistrationPage;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation;
public class CristinaRegistration implements FormAction, FormActionFactory {
public static final String PROVIDER_ID = "cristina-registration-action";
...
}
Here's what I've added in standalone.xml, inside the keycloak server subsystem:
standalone.xml
<providers>
<provider>
classpath:${jboss.home.dir}/providers/*
</provider>
<provider>
module:org.cristina.authentication.forms
</provider>
</providers>
As far as I know, I have to create a configuration file so that keycloak can scan mi provider. The file is inside src/main/resources/META-INF/services folder:
org.keycloak.authentication.FormActionFactory
org.cristina.authentication.forms.CristinaRegistration
I've created a folder named opt/jboss/keycloak/modules/org/cristina/authentication/forms/main inside my keycloak container and I've placed my jar cristinaValidator.jar and this module.xml file:
module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.3" name="org.cristina.authentication.forms">
<resources>
<resource-root path="registerProvider.jar"/>
</resources>
<dependencies>
<module name="org.keycloak.keycloak-server-spi" services="import"/>
<module name="org.keycloak.keycloak-server-spi-private" services="import"/>
<module name="org.keycloak.keycloak-services"/>
<module name="org.jboss.resteasy.resteasy-core-spi"/>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-core"/>
<module name="javax.ws.rs-api"/>
</dependencies>
</module>
Then, I restart my container, go to the administration console, I sign in with the admin credentials which are username: cristina pwd: cristina. I go to Authentication, I select the registration flow, I create a copy from it and I select "add executions". The problem is that I cannot see my registered providers in the providers list.
Thanks for your time.
Regards,
Cristina