Dans Keycloak, quand vous avez besoin de personnalisé un flow de connexion suivant certaines conditions non prévue de base par Keycloak (User configured et User Attribute), la manière de procéder est d’implémenter un ConditionalAuthenticator
Prérequis
Nous allons avoir besoin des dépendances suivantes :
Keycloak utilise le mécanisme Java standard des SPIs pour définir ses providers. Nous devons donc créer notre factory permettant à Keycloak d’initialiser notre provider.
publicclassCustomConditionalAuthenticatorFactoryimplementsConditionalAuthenticationFactory{publicstaticfinalStringPROVIDER_ID="custom-authenticator";publicstaticfinalStringCONFIG_CONDITION="foo";privatestaticfinalAuthenticationExecutionModel.Requirement[]REQUIREMENT_CHOICES={AuthenticationExecutionModel.Requirement.REQUIRED,AuthenticationExecutionModel.Requirement.DISABLED};Overridepublicvoidinit(Config.Scopescope){}@OverridepublicvoidpostInit(KeycloakSessionFactorykeycloakSessionFactory){}@Overridepublicvoidclose(){}@OverridepublicStringgetId(){returnPROVIDER_ID;}@OverridepublicStringgetDisplayType(){return"Condition - Custom Authenticator";}@OverridepublicbooleanisConfigurable(){returntrue;}@OverridepublicAuthenticationExecutionModel.Requirement[]getRequirementChoices(){returnREQUIREMENT_CHOICES;}@OverridepublicbooleanisUserSetupAllowed(){returnfalse;}@OverridepublicStringgetHelpText(){return"Flow is executed if condition is validated.";}@OverridepublicList<ProviderConfigProperty>getConfigProperties(){ProviderConfigPropertycondition=newProviderConfigProperty();condition.setName(CONFIG_CONDITION);condition.setLabel("Custom Condition");condition.setHelpText("Set a value to be validated");condition.setType(STRING_TYPE);condition.setDefaultValue("");}@OverridepublicConditionalAuthenticatorgetSingleton(){returnCustomConditionalAuthenticator.SINGLETON;}}
Nombre de méthodes ne sont pas utilisées pour un authenticator conditionnel. Notre factory est en charge de l’instanciation du provider et de la gestion de la configuration dans l’interface de Keycloak.
Dans notre cas, nous avons une condition de type String ayant pour nom foo. Notre factory définie aussi le type d’exécution possible. Ici, nous laisser le choix pour l’état Disabled ou Required.
La méthode getConfigurationProvider est utilisée pour permettre la configuration du provider depuis l’interface d’administration de Keycloak.
Création du provider
Le provider est la classe contenant la logique de notre implémentation.
publicclassCustonContidionalAuthenticatorimplementsConditionalAuthenticator{privatestaticfinalLoggerlogger=Logger.getLogger(ThreatmetrixConditionalAuthenticator.class);@OverridepublicbooleanmatchCondition(AuthenticationFlowContextcontext){Map<String,String>config=context.getAuthenticatorConfig().getConfig();if(!config.containsKey(CustomConditionalAuthenticatorFactory.CONFIG_CONDITION)){thrownewAuthenticationFlowException(AuthenticationFlowError.valueOf("Missing url for Threatmetrix configuration."));}Stringcondition=config.get(CustomConditionalAuthenticatorFactory.CONFIG_CONDITION);returnevaluate(condition)}@Overridepublicvoidaction(AuthenticationFlowContextauthenticationFlowContext){}@OverridepublicbooleanrequiresUser(){}@OverridepublicvoidsetRequiredActions(KeycloakSessionkeycloakSession,RealmModelrealmModel,UserModeluserModel){}@Overridepublicvoidclose(){}
matchCondition est la seule méthode utilisée. Elle permet d’évaluer si la condition sera positive ou négative. Pour simplifier le code, notre implémentation appelle la méthode evaluate en charge d’évaluer notre condition. C’est ici que sera définir le traitement souhaité pour l’implémentation.
Référencement de notre provider dans Keycoak
Il ne nous reste plus qu’à référencer notre provider dans Keycloak en créant le fichier resources/META-INF/services/org.keycloak.authentication.AuthenticationFactory avec le FQDN de notre factory.
Le création d’un authenticator personnalisé est simple et ne demande que l’implémentation de deux classes, la factory et le provider. Une fois le jar créé, il suffit de le déposer dans le dossier /opt/keycloak/providers puis de se rendre dans le menu Authentication et sélectionner un flow personnalisé pour ajouter notre nouvelle condition.