Skip to content

Commit

Permalink
allow top-level/sibling executions, allow nested flows
Browse files Browse the repository at this point in the history
Signed-off-by: Craig McClendon <[email protected]>
  • Loading branch information
XcrigX committed Dec 7, 2022
1 parent 344a3b6 commit 9257599
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -609,9 +609,11 @@ void initializeAuthenticationFlow(AuthenticationManagementResource authMgmt, Str
System.err.println("Failed to create flow; status code '" + response.getStatus() + "'");
System.err.println(response.readEntity(String.class));
}
} else {
updateFlowWithExecutions(authMgmt, authenticationFlowPg, authenticationFlow);
}

updateFlowWithExecutions(authMgmt, authenticationFlowPg, authenticationFlow);


// Update identity provider redirector
for (PropertyEntry authExecutionPe: authenticationFlowPg.getProperties()) {
Expand All @@ -629,6 +631,9 @@ private void updateFlowWithExecutions(AuthenticationManagementResource authMgmt,
PropertyGroup authenticationExecutionsPg = authenticationFlowPg.getPropertyGroup("authenticationExecutions");
JsonObject jsonObject = authenticationFlowPg.getJsonValue("authenticationExecutions").asJsonObject();
for (String entry : jsonObject.keySet()) {

System.out.println("adding auth execution: " + entry);

PropertyGroup entryProps = authenticationExecutionsPg.getPropertyGroup(entry);

HashMap<String, String> executionParams = new HashMap<String, String>();
Expand All @@ -654,40 +659,75 @@ private void updateFlowWithExecutions(AuthenticationManagementResource authMgmt,
// TODO: see if we can get the display name from the authenticator provider_id somehow, instead of requiring it in our config
String displayName = childEntry.getName();
PropertyGroup childEntryPg = childExecutions.getPropertyGroup(displayName);
String authenticator = childEntryPg.getStringProperty("authenticator");

Boolean childIsFlow = childEntryPg.getBooleanProperty("authenticatorFlow", false);
if (childIsFlow) {
throw new UnsupportedOperationException("Nest subflows are not yet supported");
}
configExecution(childEntryPg, authMgmt, entry, displayName, authenticationFlow);
}
} else {
configExecution(entryProps, authMgmt, authenticationFlow.getAlias(), entry, authenticationFlow);
}
}
}

HashMap<String, String> childExecutionParams = new HashMap<String, String>();
childExecutionParams.put("provider", authenticator);
AuthenticationExecutionInfoRepresentation childExecution = getOrCreateExecution(authMgmt, entry, displayName, childIsFlow, childExecutionParams);
private void configExecution(PropertyGroup propGroup, AuthenticationManagementResource authMgmt, String entry,
String displayName, AuthenticationFlowRepresentation authenticationFlow) throws Exception {
String authenticator = propGroup.getStringProperty("authenticator");

String configAlias = childEntryPg.getStringProperty("configAlias");
JsonValue configJson = childEntryPg.getJsonValue("config");
if (configJson != null) {
Map<String, String> config = buildConfigMap(configJson, configAlias);
Boolean childIsFlow = propGroup.getBooleanProperty("authenticatorFlow", false);
if (childIsFlow) {
System.out.println("Adding nested flow: " + displayName);

AuthenticatorConfigRepresentation authenticatorConfig = getOrCreateAuthenticatorConfig(authMgmt, childExecution, configAlias, config);
authenticatorConfig.setConfig(config);
authMgmt.updateAuthenticatorConfig(authenticatorConfig.getId(), authenticatorConfig);
HashMap<String, String> executionParams = new HashMap<>();

childExecution.setAuthenticationConfig(configAlias);
}
// String alias = propGroup.getStringProperty("alias");
String parentFlowAlias = entry;
String flowAlias = displayName;
String type = propGroup.getStringProperty("providerId");
// String provider = propGroup.getStringProperty("provider");
String description = propGroup.getStringProperty("description");

childExecution.setRequirement(childEntryPg.getStringProperty("requirement"));
authMgmt.updateExecutions(authenticationFlow.getAlias(), childExecution);
}
} else {
executionParams.put("authenticator", entry);
getOrCreateExecution(authMgmt, authenticationFlow.getAlias(), entry, isFlow, executionParams);
executionParams.put("alias", flowAlias);
executionParams.put("type", type);
// executionParams.put("provider", "xx");
executionParams.put("description", description);

authMgmt.addExecutionFlow(parentFlowAlias, executionParams);

// there doesn't seem to be a way to query for this, but the last added item
// should be the correct one
AuthenticationExecutionInfoRepresentation lastAdded = null;
for (AuthenticationExecutionInfoRepresentation flow : authMgmt.getExecutions(parentFlowAlias)) {
lastAdded = flow;
}

// have to update the requirement separately, and also the flowAlias doesn't get
// set for some reason
lastAdded.setAlias(flowAlias);
lastAdded.setRequirement(propGroup.getStringProperty("requirement"));
authMgmt.updateExecutions(parentFlowAlias, lastAdded);

// TODO authenticatorConfig
executionParams.put("priority", Integer.toString(entryProps.getIntProperty("priority")));
// now fetch the nested flow so we can recursively add the executions to it
authenticationFlow = authMgmt.getFlow(lastAdded.getFlowId());
updateFlowWithExecutions(authMgmt, propGroup, authenticationFlow);
} else {
HashMap<String, String> childExecutionParams = new HashMap<>();
childExecutionParams.put("provider", authenticator);
AuthenticationExecutionInfoRepresentation childExecution = getOrCreateExecution(authMgmt, entry, displayName,
childIsFlow, childExecutionParams);

String configAlias = propGroup.getStringProperty("configAlias");
JsonValue configJson = propGroup.getJsonValue("config");
if (configJson != null) {
Map<String, String> config = buildConfigMap(configJson, configAlias);

AuthenticatorConfigRepresentation authenticatorConfig = getOrCreateAuthenticatorConfig(authMgmt,
childExecution, configAlias, config);
authenticatorConfig.setConfig(config);
authMgmt.updateAuthenticatorConfig(authenticatorConfig.getId(), authenticatorConfig);
childExecution.setAuthenticationConfig(configAlias);
}

childExecution.setRequirement(propGroup.getStringProperty("requirement"));
authMgmt.updateExecutions(authenticationFlow.getAlias(), childExecution);
}
}

Expand Down Expand Up @@ -735,13 +775,22 @@ private Map<String, String> buildConfigMap(JsonValue configJson, String configAl
private AuthenticationExecutionInfoRepresentation getOrCreateExecution(AuthenticationManagementResource authMgmt,
String flowAlias, String displayName, boolean isFlow, HashMap<String, String> executionParams) {
AuthenticationExecutionInfoRepresentation savedExecution = getExecutionByDisplayName(authMgmt, flowAlias, displayName);

// System.out.println("savedExecution1: " + savedExecution);

if (savedExecution == null) {
if (isFlow) {
authMgmt.addExecutionFlow(flowAlias, executionParams);
} else {
// System.out.println("calling addExecution for flowAlias: " + flowAlias);
// for (Map.Entry<String, String> entry : executionParams.entrySet()) {
// System.out.println("addExecution param: " + entry.getKey() + " : " +
// entry.getValue());
// }
authMgmt.addExecution(flowAlias, executionParams);
}
savedExecution = getExecutionByDisplayName(authMgmt, flowAlias, displayName);
// System.out.println("savedExecution2: " + savedExecution);
}
if (savedExecution == null) {
throw new RuntimeException("Unable to create execution '" + displayName + "'");
Expand Down
46 changes: 28 additions & 18 deletions keycloak-extensions/src/test/resources/keycloak-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"builtIn": false,
"authenticationExecutions": {
"SMART Login": {
"requirement": "ALTERNATIVE",
"requirement": "REQUIRED",
"userSetupAllowed": false,
"authenticatorFlow": true,
"description": "Username, password, otp and other auth forms.",
Expand All @@ -80,24 +80,34 @@
"audiences": "https://localhost:9443/fhir-server/api/v4##http://host.testcontainers.internal:9080/fhir-server/api/v4"
}
},
"Username Password Form": {
"authenticator": "auth-username-password-form",
"requirement": "REQUIRED",
"priority": 20,
"authenticatorFlow": false
},
"Patient Selection Authenticator": {
"authenticator": "auth-select-patient",
"requirement": "REQUIRED",
"priority": 30,
"authenticatorFlow": false,
"configAlias": "host.docker",
"config": {
"internalFhirUrl": "http://host.testcontainers.internal:${FHIR_PORT}/fhir-server/api/v4"
}
}
"Forms" : {
"description": "Forms",
"priority": 20,
"providerId": "basic-flow",
"builtIn": false,
"requirement": "REQUIRED",
"authenticatorFlow": true,
"authenticationExecutions": {
"Username Password Form": {
"authenticator": "auth-username-password-form",
"requirement": "REQUIRED",
"priority": 20,
"authenticatorFlow": false
}
}
}
}
}
},
"Patient Selection Authenticator": {
"authenticator": "auth-select-patient",
"requirement": "REQUIRED",
"priority": 30,
"authenticatorFlow": false,
"configAlias": "host.docker",
"config": {
"internalFhirUrl": "http://host.testcontainers.internal:${FHIR_PORT}/fhir-server/api/v4"
}
}
}
}
},
Expand Down

0 comments on commit 9257599

Please sign in to comment.