fix: accounting for the possibility of null flows from existing realms
closes: #23980 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
7695532011
commit
4091baf4c2
5 changed files with 64 additions and 35 deletions
|
@ -1288,38 +1288,35 @@ public class DefaultExportImportManager implements ExportImportManager {
|
||||||
}
|
}
|
||||||
public static Map<String, String> importAuthenticationFlows(KeycloakSession session, RealmModel newRealm, RealmRepresentation rep) {
|
public static Map<String, String> importAuthenticationFlows(KeycloakSession session, RealmModel newRealm, RealmRepresentation rep) {
|
||||||
Map<String, String> mappedFlows = new HashMap<>();
|
Map<String, String> mappedFlows = new HashMap<>();
|
||||||
if (rep.getAuthenticationFlows() == null) {
|
|
||||||
// assume this is an old version being imported
|
if (rep.getAuthenticatorConfig() != null) {
|
||||||
DefaultAuthenticationFlows.migrateFlows(newRealm);
|
for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) {
|
||||||
} else {
|
if (configRep.getAlias() == null) {
|
||||||
if (rep.getAuthenticatorConfig() != null) {
|
// this can happen only during import json files from keycloak 3.4.0 and older
|
||||||
for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) {
|
throw new IllegalStateException("Provided realm contains authenticator config with null alias. "
|
||||||
if (configRep.getAlias() == null) {
|
+ "It should be resolved by adding alias to the authenticator config before exporting the realm.");
|
||||||
// this can happen only during import json files from keycloak 3.4.0 and older
|
|
||||||
throw new IllegalStateException("Provided realm contains authenticator config with null alias. "
|
|
||||||
+ "It should be resolved by adding alias to the authenticator config before exporting the realm.");
|
|
||||||
}
|
|
||||||
AuthenticatorConfigModel model = RepresentationToModel.toModel(configRep);
|
|
||||||
newRealm.addAuthenticatorConfig(model);
|
|
||||||
}
|
}
|
||||||
|
AuthenticatorConfigModel model = RepresentationToModel.toModel(configRep);
|
||||||
|
newRealm.addAuthenticatorConfig(model);
|
||||||
}
|
}
|
||||||
if (rep.getAuthenticationFlows() != null) {
|
}
|
||||||
for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
|
if (rep.getAuthenticationFlows() != null) {
|
||||||
AuthenticationFlowModel model = RepresentationToModel.toModel(flowRep);
|
for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
|
||||||
String previousId = model.getId();
|
AuthenticationFlowModel model = RepresentationToModel.toModel(flowRep);
|
||||||
model = newRealm.addAuthenticationFlow(model);
|
String previousId = model.getId();
|
||||||
// store the mapped ids so that clients can reference the correct flow when importing the authenticationFlowBindingOverrides
|
model = newRealm.addAuthenticationFlow(model);
|
||||||
mappedFlows.put(previousId, model.getId());
|
// store the mapped ids so that clients can reference the correct flow when importing the authenticationFlowBindingOverrides
|
||||||
}
|
mappedFlows.put(previousId, model.getId());
|
||||||
for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
|
}
|
||||||
AuthenticationFlowModel model = newRealm.getFlowByAlias(flowRep.getAlias());
|
for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) {
|
||||||
for (AuthenticationExecutionExportRepresentation exeRep : flowRep.getAuthenticationExecutions()) {
|
AuthenticationFlowModel model = newRealm.getFlowByAlias(flowRep.getAlias());
|
||||||
AuthenticationExecutionModel execution = toModel(session, newRealm, model, exeRep);
|
for (AuthenticationExecutionExportRepresentation exeRep : flowRep.getAuthenticationExecutions()) {
|
||||||
newRealm.addAuthenticatorExecution(execution);
|
AuthenticationExecutionModel execution = toModel(session, newRealm, model, exeRep);
|
||||||
}
|
newRealm.addAuthenticatorExecution(execution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DefaultAuthenticationFlows.migrateFlows(newRealm);
|
||||||
if (rep.getBrowserFlow() == null) {
|
if (rep.getBrowserFlow() == null) {
|
||||||
AuthenticationFlowModel defaultFlow = newRealm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
AuthenticationFlowModel defaultFlow = newRealm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
||||||
if (defaultFlow != null) {
|
if (defaultFlow != null) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class AuthenticationMapper {
|
||||||
|
|
||||||
final List<String> useAsDefault = Stream.of(realm.getBrowserFlow(), realm.getRegistrationFlow(), realm.getDirectGrantFlow(),
|
final List<String> useAsDefault = Stream.of(realm.getBrowserFlow(), realm.getRegistrationFlow(), realm.getDirectGrantFlow(),
|
||||||
realm.getResetCredentialsFlow(), realm.getClientAuthenticationFlow(), realm.getDockerAuthenticationFlow(), realm.getFirstBrokerLoginFlow())
|
realm.getResetCredentialsFlow(), realm.getClientAuthenticationFlow(), realm.getDockerAuthenticationFlow(), realm.getFirstBrokerLoginFlow())
|
||||||
.filter(f -> flow.getAlias().equals(f.getAlias())).map(AuthenticationFlowModel::getAlias).collect(Collectors.toList());
|
.filter(f -> f != null && flow.getAlias().equals(f.getAlias())).map(AuthenticationFlowModel::getAlias).collect(Collectors.toList());
|
||||||
|
|
||||||
if (!useAsDefault.isEmpty()) {
|
if (!useAsDefault.isEmpty()) {
|
||||||
authentication.setUsedBy(new UsedBy(UsedBy.UsedByType.DEFAULT, useAsDefault));
|
authentication.setUsedBy(new UsedBy(UsedBy.UsedByType.DEFAULT, useAsDefault));
|
||||||
|
|
|
@ -605,13 +605,15 @@ public class DefaultAuthenticationFlows {
|
||||||
if (browserFlow == null) {
|
if (browserFlow == null) {
|
||||||
browserFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
browserFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW);
|
||||||
}
|
}
|
||||||
List<AuthenticationExecutionModel> browserExecutions = new LinkedList<>();
|
if (browserFlow != null) {
|
||||||
KeycloakModelUtils.deepFindAuthenticationExecutions(realm, browserFlow, browserExecutions);
|
List<AuthenticationExecutionModel> browserExecutions = new LinkedList<>();
|
||||||
for (AuthenticationExecutionModel browserExecution : browserExecutions) {
|
KeycloakModelUtils.deepFindAuthenticationExecutions(realm, browserFlow, browserExecutions);
|
||||||
if (browserExecution.isAuthenticatorFlow()){
|
for (AuthenticationExecutionModel browserExecution : browserExecutions) {
|
||||||
if (realm.getAuthenticationExecutionsStream(browserExecution.getFlowId())
|
if (browserExecution.isAuthenticatorFlow()){
|
||||||
.anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){
|
if (realm.getAuthenticationExecutionsStream(browserExecution.getFlowId())
|
||||||
execution.setRequirement(browserExecution.getRequirement());
|
.anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){
|
||||||
|
execution.setRequirement(browserExecution.getRequirement());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,6 +257,13 @@ public class ExportImportTest extends AbstractKeycloakTest {
|
||||||
addTestRealmToTestRealmReps("import-without-clients");
|
addTestRealmToTestRealmReps("import-without-clients");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImportFromRealmWithPartialAuthenticationFlows() {
|
||||||
|
// import a realm with no built-in authentication flows
|
||||||
|
importRealmFromFile("/import/partial-authentication-flows-import.json");
|
||||||
|
Assert.assertTrue("Imported realm hasn't been found!", isRealmPresent("partial-authentication-flows-import"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImportWithNullAuthenticatorConfigAndNoDefaultBrowserFlow() {
|
public void testImportWithNullAuthenticatorConfigAndNoDefaultBrowserFlow() {
|
||||||
importRealmFromFile("/import/testrealm-authenticator-config-null.json");
|
importRealmFromFile("/import/testrealm-authenticator-config-null.json");
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"realm": "partial-authentication-flows-import",
|
||||||
|
"authenticationFlows": [
|
||||||
|
{
|
||||||
|
"alias": "X.509 browser",
|
||||||
|
"description": "Browser-based authentication",
|
||||||
|
"providerId": "basic-flow",
|
||||||
|
"topLevel": true,
|
||||||
|
"builtIn": false,
|
||||||
|
"authenticationExecutions": [
|
||||||
|
{
|
||||||
|
"requirement": "ALTERNATIVE",
|
||||||
|
"priority": 10,
|
||||||
|
"authenticator": "auth-cookie",
|
||||||
|
"authenticatorFlow": false,
|
||||||
|
"autheticatorFlow": false,
|
||||||
|
"userSetupAllowed": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue