auth flow editing
This commit is contained in:
parent
de3a776b9a
commit
de940ccff9
19 changed files with 483 additions and 101 deletions
|
@ -1080,6 +1080,24 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
},
|
},
|
||||||
flows : function(AuthenticationFlowsLoader) {
|
flows : function(AuthenticationFlowsLoader) {
|
||||||
return AuthenticationFlowsLoader();
|
return AuthenticationFlowsLoader();
|
||||||
|
},
|
||||||
|
selectedFlow : function() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controller : 'AuthenticationFlowsCtrl'
|
||||||
|
})
|
||||||
|
.when('/realms/:realm/authentication/flows/:flow', {
|
||||||
|
templateUrl : resourceUrl + '/partials/authentication-flows.html',
|
||||||
|
resolve : {
|
||||||
|
realm : function(RealmLoader) {
|
||||||
|
return RealmLoader();
|
||||||
|
},
|
||||||
|
flows : function(AuthenticationFlowsLoader) {
|
||||||
|
return AuthenticationFlowsLoader();
|
||||||
|
},
|
||||||
|
selectedFlow : function($route) {
|
||||||
|
return $route.current.params.flow;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'AuthenticationFlowsCtrl'
|
controller : 'AuthenticationFlowsCtrl'
|
||||||
|
|
|
@ -1616,41 +1616,102 @@ module.controller('IdentityProviderMapperCreateCtrl', function($scope, realm, id
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, AuthenticationExecutions, Notifications, Dialog, $location) {
|
module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, selectedFlow,
|
||||||
|
AuthenticationFlowsCopy, AuthenticationFlowExecutions,
|
||||||
|
AuthenticationExecution, AuthenticationExecutionRaisePriority, AuthenticationExecutionLowerPriority,
|
||||||
|
$modal, Notifications, CopyDialog, $location) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.flows = flows;
|
$scope.flows = flows;
|
||||||
if (flows.length > 0) {
|
if (flows.length > 0) {
|
||||||
$scope.flow = flows[0];
|
$scope.flow = flows[0];
|
||||||
|
if (selectedFlow) {
|
||||||
|
for (var i = 0; i < flows.length; i++) {
|
||||||
|
if (flows[i].alias == selectedFlow) {
|
||||||
|
$scope.flow = flows[i];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var setupForm = function() {
|
var setupForm = function() {
|
||||||
AuthenticationExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
|
AuthenticationFlowExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
|
||||||
$scope.executions = data;
|
$scope.executions = data;
|
||||||
$scope.flowmax = 0;
|
$scope.flowmax = 0;
|
||||||
|
$scope.levelmax = 0;
|
||||||
for (var i = 0; i < $scope.executions.length; i++ ) {
|
for (var i = 0; i < $scope.executions.length; i++ ) {
|
||||||
execution = $scope.executions[i];
|
var execution = $scope.executions[i];
|
||||||
if (execution.requirementChoices.length > $scope.flowmax) {
|
if (execution.requirementChoices.length > $scope.flowmax) {
|
||||||
$scope.flowmax = execution.requirementChoices.length;
|
$scope.flowmax = execution.requirementChoices.length;
|
||||||
}
|
}
|
||||||
|
if (execution.level > $scope.levelmax) {
|
||||||
|
$scope.levelmax = execution.level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("levelmax: " + $scope.levelmax);
|
||||||
|
$scope.levelmaxempties = [];
|
||||||
|
for (j = 0; j < $scope.levelmax; j++) {
|
||||||
|
$scope.levelmaxempties.push(j);
|
||||||
|
|
||||||
}
|
}
|
||||||
for (var i = 0; i < $scope.executions.length; i++ ) {
|
for (var i = 0; i < $scope.executions.length; i++ ) {
|
||||||
execution = $scope.executions[i];
|
var execution = $scope.executions[i];
|
||||||
execution.empties = [];
|
execution.empties = [];
|
||||||
for (j = 0; j < $scope.flowmax - execution.requirementChoices.length; j++) {
|
for (j = 0; j < $scope.flowmax - execution.requirementChoices.length; j++) {
|
||||||
execution.empties.push(j);
|
execution.empties.push(j);
|
||||||
}
|
}
|
||||||
|
execution.levels = [];
|
||||||
|
for (j = 0; j < execution.level; j++) {
|
||||||
|
execution.levels.push(j);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.copyFlow = function() {
|
||||||
|
CopyDialog.open('Copy AuthenticationFlow', $scope.flow.alias, function(name) {
|
||||||
|
AuthenticationFlowsCopy.save({realm: realm.realm, alias: $scope.flow.alias}, {
|
||||||
|
newName: name
|
||||||
|
}, function() {
|
||||||
|
$location.url("/realms/" + realm.realm + '/authentication/flows/' + name);
|
||||||
|
Notifications.success("Flow copied.");
|
||||||
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updateExecution = function(execution) {
|
$scope.updateExecution = function(execution) {
|
||||||
var copy = angular.copy(execution);
|
var copy = angular.copy(execution);
|
||||||
delete copy.empties;
|
delete copy.empties;
|
||||||
AuthenticationExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
|
delete copy.levels;
|
||||||
|
AuthenticationFlowExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
|
||||||
Notifications.success("Auth requirement updated");
|
Notifications.success("Auth requirement updated");
|
||||||
setupForm();
|
setupForm();
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.removeExecution = function(execution) {
|
||||||
|
console.log('removeExecution: ' + execution.id);
|
||||||
|
AuthenticationExecution.remove({realm: realm.realm, execution: execution.id}, function() {
|
||||||
|
Notifications.success("Execution removed");
|
||||||
|
setupForm();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.raisePriority = function(execution) {
|
||||||
|
AuthenticationExecutionRaisePriority.save({realm: realm.realm, execution: execution.id}, function() {
|
||||||
|
Notifications.success("Priority raised");
|
||||||
|
setupForm();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.lowerPriority = function(execution) {
|
||||||
|
AuthenticationExecutionLowerPriority.save({realm: realm.realm, execution: execution.id}, function() {
|
||||||
|
Notifications.success("Priority lowered");
|
||||||
|
setupForm();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
$scope.setupForm = setupForm;
|
$scope.setupForm = setupForm;
|
||||||
|
|
||||||
setupForm();
|
setupForm();
|
||||||
|
@ -1658,7 +1719,7 @@ module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, Auth
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications, Dialog, $location) {
|
module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications) {
|
||||||
console.log('RequiredActionsCtrl');
|
console.log('RequiredActionsCtrl');
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.requiredActions = [];
|
$scope.requiredActions = [];
|
||||||
|
|
|
@ -94,6 +94,34 @@ module.service('Dialog', function($modal) {
|
||||||
return dialog
|
return dialog
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.service('CopyDialog', function($modal) {
|
||||||
|
var dialog = {};
|
||||||
|
dialog.open = function (title, suggested, success) {
|
||||||
|
var controller = function($scope, $modalInstance, title) {
|
||||||
|
$scope.title = title;
|
||||||
|
$scope.name = { value: 'Copy of ' + suggested };
|
||||||
|
$scope.ok = function () {
|
||||||
|
console.log('ok with name: ' + $scope.name);
|
||||||
|
$modalInstance.close();
|
||||||
|
success($scope.name.value);
|
||||||
|
};
|
||||||
|
$scope.cancel = function () {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
$modal.open({
|
||||||
|
templateUrl: resourceUrl + '/templates/kc-copy.html',
|
||||||
|
controller: controller,
|
||||||
|
resolve: {
|
||||||
|
title: function() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return dialog;
|
||||||
|
});
|
||||||
|
|
||||||
module.factory('Notifications', function($rootScope, $timeout) {
|
module.factory('Notifications', function($rootScope, $timeout) {
|
||||||
// time (in ms) the notifications are shown
|
// time (in ms) the notifications are shown
|
||||||
var delay = 5000;
|
var delay = 5000;
|
||||||
|
@ -1133,7 +1161,7 @@ module.factory('IdentityProviderMapper', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('AuthenticationExecutions', function($resource) {
|
module.factory('AuthenticationFlowExecutions', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/authentication/flows/:alias/executions', {
|
return $resource(authUrl + '/admin/realms/:realm/authentication/flows/:alias/executions', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
alias : '@alias'
|
alias : '@alias'
|
||||||
|
@ -1149,6 +1177,12 @@ module.factory('AuthenticationFlows', function($resource) {
|
||||||
realm : '@realm'
|
realm : '@realm'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
module.factory('AuthenticationFlowsCopy', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/authentication/flows/:alias/copy', {
|
||||||
|
realm : '@realm',
|
||||||
|
alias : '@alias'
|
||||||
|
});
|
||||||
|
});
|
||||||
module.factory('AuthenticationConfigDescription', function($resource) {
|
module.factory('AuthenticationConfigDescription', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/authentication/config-description/:provider', {
|
return $resource(authUrl + '/admin/realms/:realm/authentication/config-description/:provider', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
|
@ -1173,6 +1207,33 @@ module.factory('AuthenticationExecutionConfig', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.factory('AuthenticationExecution', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution', {
|
||||||
|
realm : '@realm',
|
||||||
|
execution : '@execution'
|
||||||
|
}, {
|
||||||
|
update : {
|
||||||
|
method : 'PUT'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.factory('AuthenticationExecutionRaisePriority', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution/raise-priority', {
|
||||||
|
realm : '@realm',
|
||||||
|
execution : '@execution'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.factory('AuthenticationExecutionLowerPriority', function($resource) {
|
||||||
|
return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution/lower-priority', {
|
||||||
|
realm : '@realm',
|
||||||
|
execution : '@execution'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.service('SelectRoleDialog', function($modal) {
|
module.service('SelectRoleDialog', function($modal) {
|
||||||
var dialog = {};
|
var dialog = {};
|
||||||
|
|
||||||
|
|
|
@ -6,43 +6,34 @@
|
||||||
<table class="table table-striped table-bordered">
|
<table class="table table-striped table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="6" class="kc-table-actions">
|
<th colspan="{{levelmax + 1 + flowmax + 4}}" class="kc-table-actions">
|
||||||
<div class="dropdown pull-left">
|
<div class="dropdown pull-left">
|
||||||
<select class="form-control" ng-model="flow"
|
<select class="form-control" ng-model="flow"
|
||||||
ng-options="(flow.alias|capitalize) for flow in flows"
|
ng-options="(flow.alias|capitalize) for flow in flows"
|
||||||
data-ng-change="setupForm()">
|
data-ng-change="setupForm()">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pull-right" data-ng-show="access.manageRealm">
|
||||||
|
<button class="btn btn-default" data-ng-click="newFlow()">New</button>
|
||||||
|
<button class="btn btn-default" data-ng-click="copyFlow()">Copy</button>
|
||||||
|
<button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="removeFlow()">Delete</button>
|
||||||
|
<button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="addExecution()">Add Execution</button>
|
||||||
|
<button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="addFlow()">Add Flow</button>
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr data-ng-hide="executions.length == 0">
|
<tr data-ng-hide="executions.length == 0">
|
||||||
<th colspan="2">Auth Type</th>
|
<th colspan="{{levelmax + 1}}">Auth Type</th>
|
||||||
<th colspan="{{flowmax}}">Requirement</th>
|
<th colspan="{{flowmax}}">Requirement</th>
|
||||||
<th></th>
|
<th colspan="3">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
|
<tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
|
||||||
<td ng-show="execution.subFlow"></td>
|
<td ng-repeat="lev in execution.levels"></td>
|
||||||
<td>{{execution.referenceType|capitalize}}</td>
|
<td><button data-ng-hide="flow.builtIn || $first" class="btn btn-default" data-ng-click="raisePriority(execution)"><i class="fa fa-angle-up"></i></button><button data-ng-hide="flow.builtIn || $last" class="btn btn-default" data-ng-click="lowerPriority(execution)"><i class="fa fa-angle-down"></i></button> {{execution.displayName|capitalize}}</td>
|
||||||
<td ng-hide="execution.subFlow"></td>
|
<td data-ng-show="execution.level == 0" ng-repeat="levmax in levelmaxempties"></td>
|
||||||
<td ng-repeat="choice in execution.requirementChoices">
|
<td ng-repeat="choice in execution.requirementChoices">
|
||||||
<!--
|
|
||||||
<div class="dropdown pull-left">
|
|
||||||
<select class="form-control"
|
|
||||||
ng-model="execution.requirement"
|
|
||||||
ng-options="choice for choice in execution.requirementChoices">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<!--
|
|
||||||
<div ng-repeat="choice in execution.requirementChoices">
|
|
||||||
<label >
|
|
||||||
<input type="radio" ng-model="execution.requirement" ng-value="choice">
|
|
||||||
{{choice}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<label >
|
<label >
|
||||||
<input type="radio" ng-model="execution.requirement" ng-value="choice" ng-change="updateExecution(execution)">
|
<input type="radio" ng-model="execution.requirement" ng-value="choice" ng-change="updateExecution(execution)">
|
||||||
{{choice}}
|
{{choice}}
|
||||||
|
@ -50,9 +41,20 @@
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td ng-repeat="emptee in execution.empties"></td>
|
<td ng-repeat="emptee in execution.empties"></td>
|
||||||
<td>
|
<td data-ng-hide="flow.builtIn" class="kc-action-cell">
|
||||||
<a data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default" href="#/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Configure</a>
|
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeExecution(execution)">Delete</button>
|
||||||
<a data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default" href="#/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Configure</a>
|
</td>
|
||||||
|
<td data-ng-hide="flow.builtIn || !execution.authenticationFlow" class="kc-action-cell">
|
||||||
|
<button class="btn btn-default btn-block btn-sm" data-ng-click="addSubFlowExecution(execution)">Add Execution</button>
|
||||||
|
</td>
|
||||||
|
<td data-ng-hide="flow.builtIn || !execution.authenticationFlow" class="kc-action-cell">
|
||||||
|
<button class="btn btn-default btn-block btn-sm" data-ng-click="addSubFlowExecution(execution)">Add Flow</button>
|
||||||
|
</td>
|
||||||
|
<td data-ng-show="execution.configurable && execution.authenticationConfig == null" class="kc-action-cell">
|
||||||
|
<button data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default btn-block btn-sm" kc-open="/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Config</button>
|
||||||
|
</td>
|
||||||
|
<td data-ng-show="execution.configurable && execution.authenticationConfig != null" class="kc-action-cell">
|
||||||
|
<button data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Config</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr data-ng-show="executions.length == 0">
|
<tr data-ng-show="executions.length == 0">
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" ng-click="cancel()">
|
||||||
|
<span class="pficon pficon-close"></span>
|
||||||
|
</button>
|
||||||
|
<h4 class="modal-title">Role Selector</h4>
|
||||||
|
</div>
|
||||||
<div style="padding: 15px 60px 75px 60px">
|
<div style="padding: 15px 60px 75px 60px">
|
||||||
<h2>Role Selector</h2>
|
|
||||||
<form>
|
<form>
|
||||||
<div data-ng-show="realmRoles.length > 0">
|
<div data-ng-show="realmRoles.length > 0">
|
||||||
<label class="control-label" for="available">Realm Roles</label>
|
<label class="control-label" for="available">Realm Roles</label>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" ng-click="cancel()">
|
||||||
|
<span class="pficon pficon-close"></span>
|
||||||
|
</button>
|
||||||
|
<h4 class="modal-title">{{title}}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form>
|
||||||
|
<div>
|
||||||
|
<label class="control-label" for="name">New name</label>
|
||||||
|
<input class="form-control" type="text" id="name" data-ng-model="name.value">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-primary" ng-click="ok()">Ok</button>
|
||||||
|
</div>
|
|
@ -23,7 +23,7 @@ public class AuthenticationExecutionModel implements Serializable {
|
||||||
private String authenticatorConfig;
|
private String authenticatorConfig;
|
||||||
private String authenticator;
|
private String authenticator;
|
||||||
private String flowId;
|
private String flowId;
|
||||||
private boolean autheticatorFlow;
|
private boolean authenticatorFlow;
|
||||||
private Requirement requirement;
|
private Requirement requirement;
|
||||||
private boolean userSetupAllowed;
|
private boolean userSetupAllowed;
|
||||||
private int priority;
|
private int priority;
|
||||||
|
@ -103,12 +103,12 @@ public class AuthenticationExecutionModel implements Serializable {
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isAutheticatorFlow() {
|
public boolean isAuthenticatorFlow() {
|
||||||
return autheticatorFlow;
|
return authenticatorFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutheticatorFlow(boolean autheticatorFlow) {
|
public void setAuthenticatorFlow(boolean authenticatorFlow) {
|
||||||
this.autheticatorFlow = autheticatorFlow;
|
this.authenticatorFlow = authenticatorFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Requirement {
|
public enum Requirement {
|
||||||
|
|
|
@ -2,13 +2,9 @@ package org.keycloak.models.utils;
|
||||||
|
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
import org.keycloak.models.AuthenticationFlowModel;
|
import org.keycloak.models.AuthenticationFlowModel;
|
||||||
import org.keycloak.models.AuthenticatorConfigModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RequiredCredentialModel;
|
import org.keycloak.models.RequiredCredentialModel;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
@ -60,7 +56,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("registration-page-form");
|
execution.setAuthenticator("registration-page-form");
|
||||||
execution.setPriority(10);
|
execution.setPriority(10);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(true);
|
execution.setAuthenticatorFlow(true);
|
||||||
execution.setFlowId(registrationFormFlow.getId());
|
execution.setFlowId(registrationFormFlow.getId());
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
|
@ -70,7 +66,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("registration-user-creation");
|
execution.setAuthenticator("registration-user-creation");
|
||||||
execution.setPriority(20);
|
execution.setPriority(20);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
execution = new AuthenticationExecutionModel();
|
execution = new AuthenticationExecutionModel();
|
||||||
|
@ -79,7 +75,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("registration-profile-action");
|
execution.setAuthenticator("registration-profile-action");
|
||||||
execution.setPriority(40);
|
execution.setPriority(40);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
execution = new AuthenticationExecutionModel();
|
execution = new AuthenticationExecutionModel();
|
||||||
|
@ -88,7 +84,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("registration-password-action");
|
execution.setAuthenticator("registration-password-action");
|
||||||
execution.setPriority(50);
|
execution.setPriority(50);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
//AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel();
|
//AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel();
|
||||||
|
@ -104,7 +100,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("registration-recaptcha-action");
|
execution.setAuthenticator("registration-recaptcha-action");
|
||||||
execution.setPriority(60);
|
execution.setPriority(60);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
//execution.setAuthenticatorConfig(captchaConfig.getId());
|
//execution.setAuthenticatorConfig(captchaConfig.getId());
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
|
@ -142,7 +138,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("direct-grant-validate-username");
|
execution.setAuthenticator("direct-grant-validate-username");
|
||||||
execution.setPriority(10);
|
execution.setPriority(10);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
// password
|
// password
|
||||||
|
@ -155,7 +151,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("direct-grant-validate-password");
|
execution.setAuthenticator("direct-grant-validate-password");
|
||||||
execution.setPriority(20);
|
execution.setPriority(20);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
// otp
|
// otp
|
||||||
|
@ -168,7 +164,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("direct-grant-validate-otp");
|
execution.setAuthenticator("direct-grant-validate-otp");
|
||||||
execution.setPriority(30);
|
execution.setPriority(30);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,7 +185,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("auth-cookie");
|
execution.setAuthenticator("auth-cookie");
|
||||||
execution.setPriority(10);
|
execution.setPriority(10);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
execution = new AuthenticationExecutionModel();
|
execution = new AuthenticationExecutionModel();
|
||||||
execution.setParentFlow(browser.getId());
|
execution.setParentFlow(browser.getId());
|
||||||
|
@ -201,7 +197,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("auth-spnego");
|
execution.setAuthenticator("auth-spnego");
|
||||||
execution.setPriority(20);
|
execution.setPriority(20);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,7 +214,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setFlowId(forms.getId());
|
execution.setFlowId(forms.getId());
|
||||||
execution.setPriority(30);
|
execution.setPriority(30);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(true);
|
execution.setAuthenticatorFlow(true);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
// forms
|
// forms
|
||||||
|
@ -229,7 +225,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("auth-username-password-form");
|
execution.setAuthenticator("auth-username-password-form");
|
||||||
execution.setPriority(10);
|
execution.setPriority(10);
|
||||||
execution.setUserSetupAllowed(false);
|
execution.setUserSetupAllowed(false);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
|
||||||
// otp processing
|
// otp processing
|
||||||
|
@ -244,7 +240,7 @@ public class DefaultAuthenticationFlows {
|
||||||
execution.setAuthenticator("auth-otp-form");
|
execution.setAuthenticator("auth-otp-form");
|
||||||
execution.setPriority(20);
|
execution.setPriority(20);
|
||||||
execution.setUserSetupAllowed(true);
|
execution.setUserSetupAllowed(true);
|
||||||
execution.setAutheticatorFlow(false);
|
execution.setAuthenticatorFlow(false);
|
||||||
realm.addAuthenticatorExecution(execution);
|
realm.addAuthenticatorExecution(execution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,7 +462,7 @@ public class ModelToRepresentation {
|
||||||
rep.setAuthenticatorConfig(config.getAlias());
|
rep.setAuthenticatorConfig(config.getAlias());
|
||||||
}
|
}
|
||||||
rep.setAuthenticator(model.getAuthenticator());
|
rep.setAuthenticator(model.getAuthenticator());
|
||||||
rep.setAutheticatorFlow(model.isAutheticatorFlow());
|
rep.setAutheticatorFlow(model.isAuthenticatorFlow());
|
||||||
if (model.getFlowId() != null) {
|
if (model.getFlowId() != null) {
|
||||||
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
|
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
|
||||||
rep.setFlowAlias(flow.getAlias());
|
rep.setFlowAlias(flow.getAlias());
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ public class RepresentationToModel {
|
||||||
model.setAuthenticatorConfig(config.getId());
|
model.setAuthenticatorConfig(config.getId());
|
||||||
}
|
}
|
||||||
model.setAuthenticator(rep.getAuthenticator());
|
model.setAuthenticator(rep.getAuthenticator());
|
||||||
model.setAutheticatorFlow(rep.isAutheticatorFlow());
|
model.setAuthenticatorFlow(rep.isAutheticatorFlow());
|
||||||
if (rep.getFlowAlias() != null) {
|
if (rep.getFlowAlias() != null) {
|
||||||
AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
|
AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
|
||||||
model.setFlowId(flow.getId());
|
model.setFlowId(flow.getId());
|
||||||
|
|
|
@ -1314,7 +1314,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
model.setAuthenticator(entity.getAuthenticator());
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
model.setParentFlow(entity.getParentFlow());
|
model.setParentFlow(entity.getParentFlow());
|
||||||
model.setFlowId(entity.getFlowId());
|
model.setFlowId(entity.getFlowId());
|
||||||
model.setAutheticatorFlow(entity.isAuthenticatorFlow());
|
model.setAuthenticatorFlow(entity.isAuthenticatorFlow());
|
||||||
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -1346,7 +1346,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
entity.setPriority(model.getPriority());
|
entity.setPriority(model.getPriority());
|
||||||
entity.setRequirement(model.getRequirement());
|
entity.setRequirement(model.getRequirement());
|
||||||
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
entity.setAuthenticatorFlow(model.isAutheticatorFlow());
|
entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
|
||||||
entity.setFlowId(model.getFlowId());
|
entity.setFlowId(model.getFlowId());
|
||||||
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
|
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
|
||||||
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
|
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
|
||||||
|
@ -1366,7 +1366,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entity == null) return;
|
if (entity == null) return;
|
||||||
entity.setAuthenticatorFlow(model.isAutheticatorFlow());
|
entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
|
||||||
entity.setAuthenticator(model.getAuthenticator());
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
entity.setPriority(model.getPriority());
|
entity.setPriority(model.getPriority());
|
||||||
entity.setRequirement(model.getRequirement());
|
entity.setRequirement(model.getRequirement());
|
||||||
|
|
|
@ -1075,7 +1075,6 @@ public class RealmAdapter implements RealmModel {
|
||||||
@Override
|
@Override
|
||||||
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
|
||||||
if (updated != null) return updated.getAuthenticationExecutions(flowId);
|
if (updated != null) return updated.getAuthenticationExecutions(flowId);
|
||||||
List<AuthenticationExecutionModel> models = new ArrayList<>();
|
|
||||||
return cached.getAuthenticationExecutions().get(flowId);
|
return cached.getAuthenticationExecutions().get(flowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,7 @@ public class CachedRealm implements Serializable {
|
||||||
defaultLocale = model.getDefaultLocale();
|
defaultLocale = model.getDefaultLocale();
|
||||||
for (AuthenticationFlowModel flow : model.getAuthenticationFlows()) {
|
for (AuthenticationFlowModel flow : model.getAuthenticationFlows()) {
|
||||||
authenticationFlows.put(flow.getId(), flow);
|
authenticationFlows.put(flow.getId(), flow);
|
||||||
|
authenticationExecutions.put(flow.getId(), new LinkedList<AuthenticationExecutionModel>());
|
||||||
for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) {
|
for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) {
|
||||||
authenticationExecutions.add(flow.getId(), execution);
|
authenticationExecutions.add(flow.getId(), execution);
|
||||||
executionsById.put(execution.getId(), execution);
|
executionsById.put(execution.getId(), execution);
|
||||||
|
|
|
@ -1628,7 +1628,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
model.setAuthenticator(entity.getAuthenticator());
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
model.setFlowId(entity.getFlowId());
|
model.setFlowId(entity.getFlowId());
|
||||||
model.setParentFlow(entity.getParentFlow().getId());
|
model.setParentFlow(entity.getParentFlow().getId());
|
||||||
model.setAutheticatorFlow(entity.isAutheticatorFlow());
|
model.setAuthenticatorFlow(entity.isAutheticatorFlow());
|
||||||
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -1655,7 +1655,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
flow.getExecutions().add(entity);
|
flow.getExecutions().add(entity);
|
||||||
entity.setRealm(realm);
|
entity.setRealm(realm);
|
||||||
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
entity.setAutheticatorFlow(model.isAuthenticatorFlow());
|
||||||
em.persist(entity);
|
em.persist(entity);
|
||||||
em.flush();
|
em.flush();
|
||||||
model.setId(entity.getId());
|
model.setId(entity.getId());
|
||||||
|
@ -1667,7 +1667,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
|
||||||
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
|
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
|
||||||
if (entity == null) return;
|
if (entity == null) return;
|
||||||
entity.setAutheticatorFlow(model.isAutheticatorFlow());
|
entity.setAutheticatorFlow(model.isAuthenticatorFlow());
|
||||||
entity.setAuthenticator(model.getAuthenticator());
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
entity.setPriority(model.getPriority());
|
entity.setPriority(model.getPriority());
|
||||||
entity.setRequirement(model.getRequirement());
|
entity.setRequirement(model.getRequirement());
|
||||||
|
|
|
@ -1390,7 +1390,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
model.setAuthenticator(entity.getAuthenticator());
|
model.setAuthenticator(entity.getAuthenticator());
|
||||||
model.setFlowId(entity.getFlowId());
|
model.setFlowId(entity.getFlowId());
|
||||||
model.setParentFlow(entity.getParentFlow());
|
model.setParentFlow(entity.getParentFlow());
|
||||||
model.setAutheticatorFlow(entity.isAuthenticatorFlow());
|
model.setAuthenticatorFlow(entity.isAuthenticatorFlow());
|
||||||
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -1422,7 +1422,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
entity.setPriority(model.getPriority());
|
entity.setPriority(model.getPriority());
|
||||||
entity.setRequirement(model.getRequirement());
|
entity.setRequirement(model.getRequirement());
|
||||||
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
entity.setUserSetupAllowed(model.isUserSetupAllowed());
|
||||||
entity.setAuthenticatorFlow(model.isAutheticatorFlow());
|
entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
|
||||||
entity.setFlowId(model.getFlowId());
|
entity.setFlowId(model.getFlowId());
|
||||||
entity.setParentFlow(model.getParentFlow());
|
entity.setParentFlow(model.getParentFlow());
|
||||||
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
|
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
|
||||||
|
@ -1444,7 +1444,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entity == null) return;
|
if (entity == null) return;
|
||||||
entity.setAuthenticatorFlow(model.isAutheticatorFlow());
|
entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
|
||||||
entity.setAuthenticator(model.getAuthenticator());
|
entity.setAuthenticator(model.getAuthenticator());
|
||||||
entity.setPriority(model.getPriority());
|
entity.setPriority(model.getPriority());
|
||||||
entity.setRequirement(model.getRequirement());
|
entity.setRequirement(model.getRequirement());
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.authentication;
|
package org.keycloak.authentication;
|
||||||
|
|
||||||
import org.keycloak.models.AuthenticationExecutionModel;
|
import org.keycloak.models.AuthenticationExecutionModel;
|
||||||
import org.keycloak.models.AuthenticatorConfigModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -21,9 +20,11 @@ public class AuthenticatorUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
|
public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
|
||||||
for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
|
List<AuthenticationExecutionModel> authenticationExecutions = realm.getAuthenticationExecutions(flowId);
|
||||||
|
if (authenticationExecutions == null) return;
|
||||||
|
for (AuthenticationExecutionModel model : authenticationExecutions) {
|
||||||
executions.add(model);
|
executions.add(model);
|
||||||
if (model.isAutheticatorFlow() && model.isEnabled()) {
|
if (model.isAuthenticatorFlow() && model.isEnabled()) {
|
||||||
recurseExecutions(realm, model.getFlowId(), executions);
|
recurseExecutions(realm, model.getFlowId(), executions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +32,7 @@ public class AuthenticatorUtil {
|
||||||
|
|
||||||
public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
|
public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
|
||||||
for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
|
for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
|
||||||
if (model.isAutheticatorFlow()) {
|
if (model.isAuthenticatorFlow()) {
|
||||||
AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
|
AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
|
||||||
if (recurse != null) return recurse;
|
if (recurse != null) return recurse;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
|
||||||
alternativeSuccessful = true;
|
alternativeSuccessful = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (model.isAutheticatorFlow()) {
|
if (model.isAuthenticatorFlow()) {
|
||||||
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
|
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
|
||||||
return authenticationFlow.processAction(actionExecution);
|
return authenticationFlow.processAction(actionExecution);
|
||||||
} else if (model.getId().equals(actionExecution)) {
|
} else if (model.getId().equals(actionExecution)) {
|
||||||
|
@ -79,7 +79,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
|
||||||
processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
|
processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (model.isAutheticatorFlow()) {
|
if (model.isAuthenticatorFlow()) {
|
||||||
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
|
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
|
||||||
Response flowChallenge = authenticationFlow.processFlow();
|
Response flowChallenge = authenticationFlow.processFlow();
|
||||||
if (flowChallenge == null) {
|
if (flowChallenge == null) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
|
||||||
property.setName(ROLE_CONFIG);
|
property.setName(ROLE_CONFIG);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role name you want changed. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role name you want changed. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.ROLE_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProviderConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(NEW_ROLE_NAME);
|
property.setName(NEW_ROLE_NAME);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.keycloak.services.resources.admin;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
|
import org.jboss.resteasy.spi.BadRequestException;
|
||||||
import org.jboss.resteasy.spi.NotFoundException;
|
import org.jboss.resteasy.spi.NotFoundException;
|
||||||
import org.keycloak.authentication.AuthenticationFlow;
|
import org.keycloak.authentication.AuthenticationFlow;
|
||||||
import org.keycloak.authentication.AuthenticatorUtil;
|
import org.keycloak.authentication.AuthenticatorUtil;
|
||||||
|
@ -28,6 +29,7 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -59,13 +61,15 @@ public class AuthenticationManagementResource {
|
||||||
|
|
||||||
public static class AuthenticationExecutionRepresentation {
|
public static class AuthenticationExecutionRepresentation {
|
||||||
protected String id;
|
protected String id;
|
||||||
protected String referenceType;
|
|
||||||
protected String requirement;
|
protected String requirement;
|
||||||
|
protected String displayName;
|
||||||
protected List<String> requirementChoices;
|
protected List<String> requirementChoices;
|
||||||
protected Boolean configurable;
|
protected Boolean configurable;
|
||||||
protected Boolean subFlow;
|
protected Boolean authenticationFlow;
|
||||||
protected String providerId;
|
protected String providerId;
|
||||||
protected String authenticationConfig;
|
protected String authenticationConfig;
|
||||||
|
protected int level;
|
||||||
|
protected int index;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -75,12 +79,12 @@ public class AuthenticationManagementResource {
|
||||||
this.id = execution;
|
this.id = execution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReferenceType() {
|
public String getDisplayName() {
|
||||||
return referenceType;
|
return displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReferenceType(String referenceType) {
|
public void setDisplayName(String displayName) {
|
||||||
this.referenceType = referenceType;
|
this.displayName = displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRequirement() {
|
public String getRequirement() {
|
||||||
|
@ -107,14 +111,6 @@ public class AuthenticationManagementResource {
|
||||||
this.configurable = configurable;
|
this.configurable = configurable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getSubFlow() {
|
|
||||||
return subFlow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubFlow(Boolean subFlow) {
|
|
||||||
this.subFlow = subFlow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getProviderId() {
|
public String getProviderId() {
|
||||||
return providerId;
|
return providerId;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +126,30 @@ public class AuthenticationManagementResource {
|
||||||
public void setAuthenticationConfig(String authenticationConfig) {
|
public void setAuthenticationConfig(String authenticationConfig) {
|
||||||
this.authenticationConfig = authenticationConfig;
|
this.authenticationConfig = authenticationConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getAuthenticationFlow() {
|
||||||
|
return authenticationFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationFlow(Boolean authenticationFlow) {
|
||||||
|
this.authenticationFlow = authenticationFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/flows")
|
@Path("/flows")
|
||||||
|
@ -147,6 +167,72 @@ public class AuthenticationManagementResource {
|
||||||
return flows;
|
return flows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("/flows")
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response createFlow(AuthenticationFlowModel model) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
|
||||||
|
if (realm.getFlowByAlias(model.getAlias()) != null) {
|
||||||
|
return Response.status(Response.Status.CONFLICT).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
realm.addAuthenticationFlow(model);
|
||||||
|
return Response.status(201).build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Path("/flows/{flowAlias}/copy")
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
|
||||||
|
String newName = data.get("newName");
|
||||||
|
if (realm.getFlowByAlias(newName) != null) {
|
||||||
|
return Response.status(Response.Status.CONFLICT).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
|
||||||
|
if (flow == null) {
|
||||||
|
logger.debug("flow not found: " + flowAlias);
|
||||||
|
return Response.status(NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
AuthenticationFlowModel copy = new AuthenticationFlowModel();
|
||||||
|
copy.setAlias(newName);
|
||||||
|
copy.setDescription(flow.getDescription());
|
||||||
|
copy.setProviderId(flow.getProviderId());
|
||||||
|
copy.setBuiltIn(false);
|
||||||
|
copy.setTopLevel(flow.isTopLevel());
|
||||||
|
copy = realm.addAuthenticationFlow(copy);
|
||||||
|
copy(newName, flow, copy);
|
||||||
|
|
||||||
|
return Response.status(201).build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void copy(String newName, AuthenticationFlowModel from, AuthenticationFlowModel to) {
|
||||||
|
for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(from.getId())) {
|
||||||
|
if (execution.isAuthenticatorFlow()) {
|
||||||
|
AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
|
||||||
|
AuthenticationFlowModel copy = new AuthenticationFlowModel();
|
||||||
|
copy.setAlias(newName + " " + subFlow.getAlias());
|
||||||
|
copy.setDescription(subFlow.getDescription());
|
||||||
|
copy.setProviderId(subFlow.getProviderId());
|
||||||
|
copy.setBuiltIn(false);
|
||||||
|
copy.setTopLevel(false);
|
||||||
|
copy = realm.addAuthenticationFlow(copy);
|
||||||
|
execution.setFlowId(copy.getId());
|
||||||
|
copy(newName, subFlow, copy);
|
||||||
|
}
|
||||||
|
execution.setId(null);
|
||||||
|
execution.setParentFlow(to.getId());
|
||||||
|
realm.addAuthenticatorExecution(execution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Path("/flows/{flowAlias}/executions")
|
@Path("/flows/{flowAlias}/executions")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
|
@ -160,12 +246,22 @@ public class AuthenticationManagementResource {
|
||||||
return Response.status(NOT_FOUND).build();
|
return Response.status(NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
List<AuthenticationExecutionRepresentation> result = new LinkedList<>();
|
List<AuthenticationExecutionRepresentation> result = new LinkedList<>();
|
||||||
List<AuthenticationExecutionModel> executions = AuthenticatorUtil.getEnabledExecutionsRecursively(realm, flow.getId());
|
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
|
recurseExecutions(flow, result, level);
|
||||||
|
return Response.ok(result).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recurseExecutions(AuthenticationFlowModel flow, List<AuthenticationExecutionRepresentation> result, int level) {
|
||||||
|
int index = 0;
|
||||||
|
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(flow.getId());
|
||||||
for (AuthenticationExecutionModel execution : executions) {
|
for (AuthenticationExecutionModel execution : executions) {
|
||||||
AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
|
AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
|
||||||
rep.setSubFlow(false);
|
rep.setLevel(level);
|
||||||
|
rep.setIndex(index++);
|
||||||
rep.setRequirementChoices(new LinkedList<String>());
|
rep.setRequirementChoices(new LinkedList<String>());
|
||||||
if (execution.isAutheticatorFlow()) {
|
if (execution.isAuthenticatorFlow()) {
|
||||||
AuthenticationFlowModel flowRef = realm.getAuthenticationFlowById(execution.getFlowId());
|
AuthenticationFlowModel flowRef = realm.getAuthenticationFlowById(execution.getFlowId());
|
||||||
if (AuthenticationFlow.BASIC_FLOW.equals(flowRef.getProviderId())) {
|
if (AuthenticationFlow.BASIC_FLOW.equals(flowRef.getProviderId())) {
|
||||||
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.ALTERNATIVE.name());
|
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.ALTERNATIVE.name());
|
||||||
|
@ -176,20 +272,19 @@ public class AuthenticationManagementResource {
|
||||||
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.DISABLED.name());
|
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.DISABLED.name());
|
||||||
rep.setProviderId(execution.getAuthenticator());
|
rep.setProviderId(execution.getAuthenticator());
|
||||||
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
|
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
|
||||||
|
|
||||||
}
|
}
|
||||||
rep.setReferenceType(flowRef.getAlias());
|
rep.setDisplayName(flowRef.getAlias());
|
||||||
rep.setConfigurable(false);
|
rep.setConfigurable(false);
|
||||||
rep.setId(execution.getId());
|
rep.setId(execution.getId());
|
||||||
|
rep.setAuthenticationFlow(execution.isAuthenticatorFlow());
|
||||||
rep.setRequirement(execution.getRequirement().name());
|
rep.setRequirement(execution.getRequirement().name());
|
||||||
result.add(rep);
|
result.add(rep);
|
||||||
|
AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
|
||||||
|
recurseExecutions(subFlow, result, level + 1);
|
||||||
} else {
|
} else {
|
||||||
if (!flow.getId().equals(execution.getParentFlow())) {
|
|
||||||
rep.setSubFlow(true);
|
|
||||||
}
|
|
||||||
String providerId = execution.getAuthenticator();
|
String providerId = execution.getAuthenticator();
|
||||||
ConfigurableAuthenticatorFactory factory = CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
|
ConfigurableAuthenticatorFactory factory = CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
|
||||||
rep.setReferenceType(factory.getDisplayType());
|
rep.setDisplayName(factory.getDisplayType());
|
||||||
rep.setConfigurable(factory.isConfigurable());
|
rep.setConfigurable(factory.isConfigurable());
|
||||||
for (AuthenticationExecutionModel.Requirement choice : factory.getRequirementChoices()) {
|
for (AuthenticationExecutionModel.Requirement choice : factory.getRequirementChoices()) {
|
||||||
rep.getRequirementChoices().add(choice.name());
|
rep.getRequirementChoices().add(choice.name());
|
||||||
|
@ -199,11 +294,8 @@ public class AuthenticationManagementResource {
|
||||||
rep.setProviderId(execution.getAuthenticator());
|
rep.setProviderId(execution.getAuthenticator());
|
||||||
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
|
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
|
||||||
result.add(rep);
|
result.add(rep);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return Response.ok(result).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/flows/{flowAlias}/executions")
|
@Path("/flows/{flowAlias}/executions")
|
||||||
|
@ -231,6 +323,134 @@ public class AuthenticationManagementResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("/executions")
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response addExecution(AuthenticationExecutionModel model) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
AuthenticationFlowModel parentFlow = getParentFlow(model);
|
||||||
|
if (parentFlow.isBuiltIn()) {
|
||||||
|
throw new BadRequestException("It is illegal to add execution to a built in flow");
|
||||||
|
}
|
||||||
|
int priority = 0;
|
||||||
|
List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
|
||||||
|
for (AuthenticationExecutionModel execution : executions) {
|
||||||
|
priority = execution.getPriority();
|
||||||
|
}
|
||||||
|
if (priority > 0) priority += 10;
|
||||||
|
model.setPriority(priority);
|
||||||
|
model = realm.addAuthenticatorExecution(model);
|
||||||
|
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationFlowModel getParentFlow(AuthenticationExecutionModel model) {
|
||||||
|
if (model.getParentFlow() == null) {
|
||||||
|
throw new BadRequestException("parent flow not set on new execution");
|
||||||
|
}
|
||||||
|
AuthenticationFlowModel parentFlow = realm.getAuthenticationFlowById(model.getParentFlow());
|
||||||
|
if (parentFlow == null) {
|
||||||
|
throw new BadRequestException("execution parent flow does not exist");
|
||||||
|
|
||||||
|
}
|
||||||
|
return parentFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Path("/executions/{executionId}/raise-priority")
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
public void raisePriority(@PathParam("executionId") String execution) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
|
||||||
|
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
|
||||||
|
if (model == null) {
|
||||||
|
session.getTransaction().setRollbackOnly();
|
||||||
|
throw new NotFoundException("Illegal execution");
|
||||||
|
|
||||||
|
}
|
||||||
|
AuthenticationFlowModel parentFlow = getParentFlow(model);
|
||||||
|
if (parentFlow.isBuiltIn()) {
|
||||||
|
throw new BadRequestException("It is illegal to modify execution in a built in flow");
|
||||||
|
}
|
||||||
|
List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
|
||||||
|
AuthenticationExecutionModel previous = null;
|
||||||
|
for (AuthenticationExecutionModel exe : executions) {
|
||||||
|
if (exe.getId().equals(model.getId())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previous = exe;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (previous == null) return;
|
||||||
|
int tmp = previous.getPriority();
|
||||||
|
previous.setPriority(model.getPriority());
|
||||||
|
realm.updateAuthenticatorExecution(previous);
|
||||||
|
model.setPriority(tmp);
|
||||||
|
realm.updateAuthenticatorExecution(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuthenticationExecutionModel> getSortedExecutions(AuthenticationFlowModel parentFlow) {
|
||||||
|
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(parentFlow.getId());
|
||||||
|
Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
|
||||||
|
return executions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Path("/executions/{executionId}/lower-priority")
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
public void lowerPriority(@PathParam("executionId") String execution) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
|
||||||
|
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
|
||||||
|
if (model == null) {
|
||||||
|
session.getTransaction().setRollbackOnly();
|
||||||
|
throw new NotFoundException("Illegal execution");
|
||||||
|
|
||||||
|
}
|
||||||
|
AuthenticationFlowModel parentFlow = getParentFlow(model);
|
||||||
|
if (parentFlow.isBuiltIn()) {
|
||||||
|
throw new BadRequestException("It is illegal to modify execution in a built in flow");
|
||||||
|
}
|
||||||
|
List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < executions.size(); i++) {
|
||||||
|
if (executions.get(i).getId().equals(model.getId())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i + 1 >= executions.size()) return;
|
||||||
|
AuthenticationExecutionModel next = executions.get(i + 1);
|
||||||
|
int tmp = model.getPriority();
|
||||||
|
model.setPriority(next.getPriority());
|
||||||
|
realm.updateAuthenticatorExecution(model);
|
||||||
|
next.setPriority(tmp);
|
||||||
|
realm.updateAuthenticatorExecution(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Path("/executions/{executionId}")
|
||||||
|
@DELETE
|
||||||
|
@NoCache
|
||||||
|
public void removeExecution(@PathParam("executionId") String execution) {
|
||||||
|
this.auth.requireManage();
|
||||||
|
|
||||||
|
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
|
||||||
|
if (model == null) {
|
||||||
|
session.getTransaction().setRollbackOnly();
|
||||||
|
throw new NotFoundException("Illegal execution");
|
||||||
|
|
||||||
|
}
|
||||||
|
AuthenticationFlowModel parentFlow = getParentFlow(model);
|
||||||
|
if (parentFlow.isBuiltIn()) {
|
||||||
|
throw new BadRequestException("It is illegal to remove execution from a built in flow");
|
||||||
|
}
|
||||||
|
realm.removeAuthenticatorExecution(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Path("/executions/{executionId}/config")
|
@Path("/executions/{executionId}/config")
|
||||||
@POST
|
@POST
|
||||||
@NoCache
|
@NoCache
|
||||||
|
|
Loading…
Reference in a new issue