diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
index 7568e04cef..eb34666604 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -978,7 +978,7 @@ module.config([ '$routeProvider', function($routeProvider) {
},
clients : function(ClientListLoader) {
return ClientListLoader();
- },
+ }
},
controller : 'UserFederationMapperCtrl'
})
@@ -1066,6 +1066,36 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'RealmPasswordPolicyCtrl'
})
+ .when('/realms/:realm/authentication/config/:provider/:config', {
+ templateUrl : resourceUrl + '/partials/authenticator-config.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ configType : function(AuthenticationConfigDescriptionLoader) {
+ return AuthenticationConfigDescriptionLoader();
+ },
+ config : function(AuthenticationConfigLoader) {
+ return AuthenticationConfigLoader();
+ }
+ },
+ controller : 'AuthenticationConfigCtrl'
+ })
+ .when('/create/authentication/:realm/execution/:executionId/provider/:provider', {
+ templateUrl : resourceUrl + '/partials/authenticator-config.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ configType : function(AuthenticationConfigDescriptionLoader) {
+ return AuthenticationConfigDescriptionLoader();
+ },
+ execution : function(ExecutionIdLoader) {
+ return ExecutionIdLoader();
+ }
+ },
+ controller : 'AuthenticationConfigCreateCtrl'
+ })
.when('/server-info', {
templateUrl : resourceUrl + '/partials/server-info.html'
})
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 93e7cc3b8e..e9341b329b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1634,6 +1634,93 @@ module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions
});
+module.controller('AuthenticationConfigCtrl', function($scope, realm, configType, config, AuthenticationConfig, Notifications, Dialog, $location) {
+ $scope.realm = realm;
+ $scope.configType = configType;
+ $scope.create = false;
+ $scope.config = angular.copy(config);
+ $scope.changed = false;
+
+ $scope.$watch(function() {
+ return $location.path();
+ }, function() {
+ $scope.path = $location.path().substring(1).split("/");
+ });
+
+ $scope.$watch('config', function() {
+ if (!angular.equals($scope.config, config)) {
+ $scope.changed = true;
+ }
+ }, true);
+
+ $scope.save = function() {
+ AuthenticationConfig.update({
+ realm : realm.realm,
+ config : config.id
+ }, $scope.config, function() {
+ $scope.changed = false;
+ config = angular.copy($scope.config);
+ $location.url("/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + config.id);
+ Notifications.success("Your changes have been saved.");
+ });
+ };
+
+ $scope.reset = function() {
+ $scope.config = angular.copy(config);
+ $scope.changed = false;
+ };
+
+ $scope.cancel = function() {
+ //$location.url("/realms");
+ window.history.back();
+ };
+
+ $scope.remove = function() {
+ Dialog.confirmDelete($scope.config.alias, 'config', function() {
+ AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() {
+ Notifications.success("The config has been deleted.");
+ $location.url("/realms/" + realm.realm + '/authentication/flows');
+ });
+ });
+ };
+
+});
+
+module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, configType, execution, AuthenticationExecutionConfig, Notifications, Dialog, $location) {
+ $scope.realm = realm;
+ $scope.create = true;
+ $scope.config = { config: {}};
+ $scope.configType = configType;
+
+ $scope.$watch(function() {
+ return $location.path();
+ }, function() {
+ $scope.path = $location.path().substring(1).split("/");
+ });
+
+ $scope.save = function() {
+ AuthenticationExecutionConfig.save({
+ realm : realm.realm,
+ execution: execution
+ }, $scope.config, function(data, headers) {
+ var l = headers().location;
+ var id = l.substring(l.lastIndexOf("/") + 1);
+ var url = "/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + id;
+ console.log('redirect url: ' + url);
+ $location.url(url);
+ Notifications.success("Config has been created.");
+ });
+ };
+
+ $scope.cancel = function() {
+ //$location.url("/realms");
+ window.history.back();
+ };
+
+
+});
+
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
index da41b3c05a..72c6b8cef0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
@@ -348,5 +348,29 @@ module.factory('AuthenticationFlowsLoader', function(Loader, AuthenticationFlows
});
});
+module.factory('AuthenticationConfigDescriptionLoader', function(Loader, AuthenticationConfigDescription, $route, $q) {
+ return Loader.get(AuthenticationConfigDescription, function () {
+ return {
+ realm: $route.current.params.realm,
+ provider: $route.current.params.provider
+ }
+ });
+});
+
+module.factory('ExecutionIdLoader', function($route) {
+ return function() { return $route.current.params.executionId; };
+});
+
+module.factory('AuthenticationConfigLoader', function(Loader, AuthenticationConfig, $route, $q) {
+ return Loader.get(AuthenticationConfig, function () {
+ return {
+ realm: $route.current.params.realm,
+ config: $route.current.params.config
+ }
+ });
+});
+
+
+
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index 6f25efb012..f3c4475495 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -1094,5 +1094,28 @@ module.factory('AuthenticationFlows', function($resource) {
realm : '@realm'
});
});
+module.factory('AuthenticationConfigDescription', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/config-description/:provider', {
+ realm : '@realm',
+ provider: '@provider'
+ });
+});
+
+module.factory('AuthenticationConfig', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/config/:config', {
+ realm : '@realm',
+ config: '@config'
+ }, {
+ update: {
+ method : 'PUT'
+ }
+ });
+});
+module.factory('AuthenticationExecutionConfig', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution/config', {
+ realm : '@realm',
+ execution: '@execution'
+ });
+});
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
index 5084ab93fe..4c65931f8c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
@@ -6,7 +6,7 @@
-
+ |
|
@@ -49,6 +50,10 @@
|
+
+ Configure
+ Configure
+ |
No executions available |
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
new file mode 100755
index 0000000000..a093240616
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
@@ -0,0 +1,64 @@
+
+
+
+ - Authentication Flows
+ - Create Authenticator Config
+ - {{config.alias}}
+
+
+
Create Authenticator Config
+
{{config.alias|capitalize}}
+
+
+
+
+
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/register.ftl b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
index 75a48fc738..cf7bd1d1ad 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/register.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
@@ -110,7 +110,7 @@
<#if recaptchaRequired??>
#if>
diff --git a/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java b/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
index 44b8982e00..9b60192848 100755
--- a/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
+++ b/model/api/src/main/java/org/keycloak/models/AuthenticatorConfigModel.java
@@ -32,6 +32,8 @@ public class AuthenticatorConfigModel implements Serializable {
this.alias = alias;
}
+
+
public Map getConfig() {
return config;
}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
index f928bea1fd..5f32b410d6 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorFactory.java
@@ -9,7 +9,7 @@ import org.keycloak.provider.ProviderFactory;
* @author Bill Burke
* @version $Revision: 1 $
*/
-public interface AuthenticatorFactory extends ProviderFactory, ConfiguredProvider, ConfigurableAuthenticatorFactory {
+public interface AuthenticatorFactory extends ProviderFactory, ConfigurableAuthenticatorFactory {
Authenticator create();
}
diff --git a/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
index cca47c6d84..529767458f 100755
--- a/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/ConfigurableAuthenticatorFactory.java
@@ -1,12 +1,13 @@
package org.keycloak.authentication;
import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.provider.ConfiguredProvider;
/**
* @author Bill Burke
* @version $Revision: 1 $
*/
-public interface ConfigurableAuthenticatorFactory {
+public interface ConfigurableAuthenticatorFactory extends ConfiguredProvider {
String getDisplayType();
/**
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
index 123c4b405f..cee4f7df12 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/UsernamePasswordFormFactory.java
@@ -57,7 +57,7 @@ public class UsernamePasswordFormFactory implements AuthenticatorFactory {
@Override
public boolean isConfigurable() {
- return true;
+ return false;
}
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
index 90657fe6e3..4b64333c9f 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPage.java
@@ -8,8 +8,10 @@ import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
import javax.ws.rs.core.Response;
+import java.util.List;
/**
* @author Bill Burke
@@ -41,6 +43,16 @@ public class RegistrationPage implements FormAuthenticator, FormAuthenticatorFac
return "Registration Page";
}
+ @Override
+ public String getHelpText() {
+ return null;
+ }
+
+ @Override
+ public List getConfigProperties() {
+ return null;
+ }
+
@Override
public String getReferenceCategory() {
return null;
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
index f20b3ebdd2..648f9de97e 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationPassword.java
@@ -16,6 +16,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
+import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation;
@@ -31,6 +32,16 @@ import java.util.List;
public class RegistrationPassword implements FormAction, FormActionFactory {
public static final String PROVIDER_ID = "registration-password-action";
+ @Override
+ public String getHelpText() {
+ return null;
+ }
+
+ @Override
+ public List getConfigProperties() {
+ return null;
+ }
+
@Override
public void validate(ValidationContext context) {
MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters();
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
index f67fbeae86..5ac7341fb7 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationProfile.java
@@ -14,6 +14,7 @@ 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;
@@ -28,6 +29,15 @@ import java.util.List;
public class RegistrationProfile implements FormAction, FormActionFactory {
public static final String PROVIDER_ID = "registration-profile-action";
+ @Override
+ public String getHelpText() {
+ return null;
+ }
+
+ @Override
+ public List getConfigProperties() {
+ return null;
+ }
@Override
public void validate(ValidationContext context) {
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
index 3e8d19102a..7009704418 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
@@ -23,6 +23,7 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.services.messages.Messages;
@@ -43,6 +44,8 @@ import java.util.Map;
public class RegistrationRecaptcha implements FormAction, FormActionFactory, ConfiguredProvider {
public static final String G_RECAPTCHA_RESPONSE = "g-recaptcha-response";
public static final String RECAPTCHA_REFERENCE_CATEGORY = "recaptcha";
+ public static final String SITE_KEY = "site.key";
+ public static final String SITE_SECRET = "secret";
protected static Logger logger = Logger.getLogger(RegistrationRecaptcha.class);
public static final String PROVIDER_ID = "registration-recaptcha-action";
@@ -74,13 +77,13 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
public void buildPage(FormContext context, LoginFormsProvider form) {
AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
if (captchaConfig == null || captchaConfig.getConfig() == null
- || captchaConfig.getConfig().get("site.key") == null
- || captchaConfig.getConfig().get("secret") == null
+ || captchaConfig.getConfig().get(SITE_KEY) == null
+ || captchaConfig.getConfig().get(SITE_SECRET) == null
) {
form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED));
return;
}
- String siteKey = captchaConfig.getConfig().get("site.key");
+ String siteKey = captchaConfig.getConfig().get(SITE_KEY);
form.setAttribute("recaptchaRequired", true);
form.setAttribute("recaptchaSiteKey", siteKey);
List scripts = new LinkedList<>();
@@ -98,7 +101,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
String captcha = formData.getFirst(G_RECAPTCHA_RESPONSE);
if (!Validation.isBlank(captcha)) {
AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
- String secret = captchaConfig.getConfig().get("secret");
+ String secret = captchaConfig.getConfig().get(SITE_SECRET);
HttpClient httpClient = context.getSession().getProvider(HttpClientProvider.class).getHttpClient();
HttpPost post = new HttpPost("https://www.google.com/recaptcha/api/siteverify");
@@ -185,8 +188,28 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
return null;
}
+ private static final List configProperties = new ArrayList();
+
+ static {
+ ProviderConfigProperty property;
+ property = new ProviderConfigProperty();
+ property.setName(SITE_KEY);
+ property.setLabel("Recaptcha Site Key");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ property.setHelpText("Google Recaptcha Site Key");
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(SITE_SECRET);
+ property.setLabel("Recaptcha Secret");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ property.setHelpText("Google Recaptcha Secret");
+ configProperties.add(property);
+
+ }
+
+
@Override
public List getConfigProperties() {
- return null;
+ return configProperties;
}
}
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
index 28d62392fb..75f2818f1f 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
@@ -16,6 +16,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.AttributeFormDataProcessor;
import org.keycloak.services.validation.Validation;
@@ -32,6 +33,16 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
public static final String PROVIDER_ID = "registration-user-creation";
+ @Override
+ public String getHelpText() {
+ return null;
+ }
+
+ @Override
+ public List getConfigProperties() {
+ return null;
+ }
+
@Override
public void validate(ValidationContext context) {
MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index fa221c386c..39ef7c3914 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -8,24 +8,29 @@ import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.authentication.AuthenticatorUtil;
import org.keycloak.authentication.ConfigurableAuthenticatorFactory;
-import org.keycloak.authentication.DefaultAuthenticationFlow;
import org.keycloak.authentication.FormAction;
import org.keycloak.authentication.FormActionFactory;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -42,6 +47,9 @@ public class AuthenticationManagementResource {
private final KeycloakSession session;
private RealmAuth auth;
private AdminEventBuilder adminEvent;
+ @Context
+ private UriInfo uriInfo;
+
private static Logger logger = Logger.getLogger(AuthenticationManagementResource.class);
public AuthenticationManagementResource(RealmModel realm, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
@@ -53,19 +61,21 @@ public class AuthenticationManagementResource {
}
public static class AuthenticationExecutionRepresentation {
- protected String execution;
+ protected String id;
protected String referenceType;
protected String requirement;
protected List requirementChoices;
protected Boolean configurable;
protected Boolean subFlow;
+ protected String providerId;
+ protected String authenticationConfig;
- public String getExecution() {
- return execution;
+ public String getId() {
+ return id;
}
- public void setExecution(String execution) {
- this.execution = execution;
+ public void setId(String execution) {
+ this.id = execution;
}
public String getReferenceType() {
@@ -107,6 +117,22 @@ public class AuthenticationManagementResource {
public void setSubFlow(Boolean subFlow) {
this.subFlow = subFlow;
}
+
+ public String getProviderId() {
+ return providerId;
+ }
+
+ public void setProviderId(String providerId) {
+ this.providerId = providerId;
+ }
+
+ public String getAuthenticationConfig() {
+ return authenticationConfig;
+ }
+
+ public void setAuthenticationConfig(String authenticationConfig) {
+ this.authenticationConfig = authenticationConfig;
+ }
}
@Path("/flows")
@@ -150,27 +176,30 @@ public class AuthenticationManagementResource {
} else if (AuthenticationFlow.FORM_FLOW.equals(flowRef.getProviderId())) {
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.REQUIRED.name());
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.DISABLED.name());
+ rep.setProviderId(execution.getAuthenticator());
+ rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
+
}
rep.setReferenceType(flowRef.getAlias());
rep.setConfigurable(false);
- rep.setExecution(execution.getId());
+ rep.setId(execution.getId());
rep.setRequirement(execution.getRequirement().name());
result.add(rep);
} else {
if (!flow.getId().equals(execution.getParentFlow())) {
rep.setSubFlow(true);
}
- ConfigurableAuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, execution.getAuthenticator());
- if (factory == null) {
- factory = (FormActionFactory)session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, execution.getAuthenticator());
- }
+ String providerId = execution.getAuthenticator();
+ ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(providerId);
rep.setReferenceType(factory.getDisplayType());
rep.setConfigurable(factory.isConfigurable());
for (AuthenticationExecutionModel.Requirement choice : factory.getRequirementChoices()) {
rep.getRequirementChoices().add(choice.name());
}
- rep.setExecution(execution.getId());
+ rep.setId(execution.getId());
rep.setRequirement(execution.getRequirement().name());
+ rep.setProviderId(execution.getAuthenticator());
+ rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
result.add(rep);
}
@@ -179,6 +208,14 @@ public class AuthenticationManagementResource {
return Response.ok(result).build();
}
+ public ConfigurableAuthenticatorFactory getConfigurableAuthenticatorFactory(String providerId) {
+ ConfigurableAuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, providerId);
+ if (factory == null) {
+ factory = (FormActionFactory)session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, providerId);
+ }
+ return factory;
+ }
+
@Path("/flows/{flowAlias}/executions")
@PUT
@NoCache
@@ -192,7 +229,7 @@ public class AuthenticationManagementResource {
throw new NotFoundException("flow not found");
}
- AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(rep.getExecution());
+ AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(rep.getId());
if (model == null) {
session.getTransaction().setRollbackOnly();
throw new NotFoundException("Illegal execution");
@@ -204,6 +241,39 @@ public class AuthenticationManagementResource {
}
}
+ @Path("/executions/{executionId}/config")
+ @POST
+ @NoCache
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response newExecutionConfig(@PathParam("executionId") String execution, AuthenticatorConfigModel config) {
+ this.auth.requireManage();
+
+ AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
+ if (model == null) {
+ session.getTransaction().setRollbackOnly();
+ throw new NotFoundException("Illegal execution");
+
+ }
+ config = realm.addAuthenticatorConfig(config);
+ model.setAuthenticatorConfig(config.getId());
+ realm.updateAuthenticatorExecution(model);
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
+ }
+
+ @Path("/executions/{executionId}/config/{id}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ public AuthenticatorConfigModel getAuthenticatorConfig(@PathParam("executionId") String execution,@PathParam("id") String id) {
+ AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
+ if (config == null) {
+ throw new NotFoundException("Could not find authenticator config");
+
+ }
+ return config;
+ }
+
+
public static class RequiredActionProviderRepresentation {
private String alias;
private String name;
@@ -256,6 +326,7 @@ public class AuthenticationManagementResource {
@Path("required-actions")
@GET
@Produces(MediaType.APPLICATION_JSON)
+ @NoCache
public List getRequiredActions() {
List list = new LinkedList<>();
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
@@ -278,6 +349,7 @@ public class AuthenticationManagementResource {
@Path("required-actions/{alias}")
@GET
@Produces(MediaType.APPLICATION_JSON)
+ @NoCache
public RequiredActionProviderRepresentation getRequiredAction(@PathParam("alias") String alias) {
RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
if (model == null) {
@@ -316,5 +388,131 @@ public class AuthenticationManagementResource {
realm.removeRequiredActionProvider(model);
}
+ public class AuthenticatorConfigDescription {
+ protected String name;
+ protected String providerId;
+ protected String helpText;
+
+ protected List properties;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getHelpText() {
+ return helpText;
+ }
+
+ public String getProviderId() {
+ return providerId;
+ }
+
+ public void setProviderId(String providerId) {
+ this.providerId = providerId;
+ }
+
+ public void setHelpText(String helpText) {
+ this.helpText = helpText;
+ }
+
+ public List getProperties() {
+ return properties;
+ }
+
+ public void setProperties(List properties) {
+ this.properties = properties;
+ }
+ }
+
+
+ @Path("config-description/{providerId}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ public AuthenticatorConfigDescription getAuthenticatorConfigDescription(@PathParam("providerId") String providerId) {
+ ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(providerId);
+ if (factory == null) {
+ throw new NotFoundException("Could not find authenticator provider");
+ }
+ AuthenticatorConfigDescription rep = new AuthenticatorConfigDescription();
+ rep.setProviderId(providerId);
+ rep.setName(factory.getDisplayType());
+ rep.setHelpText(factory.getHelpText());
+ rep.setProperties(new LinkedList());
+ List configProperties = factory.getConfigProperties();
+ for (ProviderConfigProperty prop : configProperties) {
+ ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
+ propRep.setName(prop.getName());
+ propRep.setLabel(prop.getLabel());
+ propRep.setType(prop.getType());
+ propRep.setDefaultValue(prop.getDefaultValue());
+ propRep.setHelpText(prop.getHelpText());
+ rep.getProperties().add(propRep);
+ }
+ return rep;
+ }
+
+ @Path("config")
+ @POST
+ @NoCache
+ public Response createAuthenticatorConfig(AuthenticatorConfigModel config) {
+ config = realm.addAuthenticatorConfig(config);
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
+ }
+
+ @Path("config/{id}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ public AuthenticatorConfigModel getAuthenticatorConfig(@PathParam("id") String id) {
+ AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
+ if (config == null) {
+ throw new NotFoundException("Could not find authenticator config");
+
+ }
+ return config;
+ }
+ @Path("config/{id}")
+ @DELETE
+ @NoCache
+ public void removeAuthenticatorConfig(@PathParam("id") String id) {
+ AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
+ if (config == null) {
+ throw new NotFoundException("Could not find authenticator config");
+
+ }
+ List flows = new LinkedList<>();
+ for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
+ for (AuthenticationExecutionModel exe : realm.getAuthenticationExecutions(flow.getId())) {
+ if (id.equals(exe.getAuthenticatorConfig())) {
+ exe.setAuthenticatorConfig(null);
+ realm.updateAuthenticatorExecution(exe);
+ }
+ }
+ }
+
+ realm.removeAuthenticatorConfig(config);
+ }
+ @Path("config/{id}")
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @NoCache
+ public void updateAuthenticatorConfig(@PathParam("id") String id, AuthenticatorConfigModel config) {
+ AuthenticatorConfigModel exists = realm.getAuthenticatorConfigById(id);
+ if (exists == null) {
+ throw new NotFoundException("Could not find authenticator config");
+
+ }
+ exists.setAlias(config.getAlias());
+ exists.setConfig(config.getConfig());
+ realm.updateAuthenticatorConfig(exists);
+ }
+
+
+
}
\ No newline at end of file