2023-02-03 10:45:11 +00:00
|
|
|
// tslint:disable:no-unused-expression
|
|
|
|
import { faker } from "@faker-js/faker";
|
|
|
|
import { fail } from "assert";
|
|
|
|
import * as chai from "chai";
|
|
|
|
import { KeycloakAdminClient } from "../src/client.js";
|
|
|
|
import { RequiredActionAlias } from "../src/defs/requiredActionProviderRepresentation.js";
|
|
|
|
import { credentials } from "./constants.js";
|
|
|
|
|
|
|
|
const expect = chai.expect;
|
|
|
|
|
|
|
|
describe("Authentication management", () => {
|
|
|
|
let kcAdminClient: KeycloakAdminClient;
|
|
|
|
let currentRealm: string;
|
|
|
|
let requiredActionProvider: Record<string, any>;
|
|
|
|
|
|
|
|
before(async () => {
|
|
|
|
kcAdminClient = new KeycloakAdminClient();
|
|
|
|
await kcAdminClient.auth(credentials);
|
|
|
|
const realmName = faker.internet.userName().toLowerCase();
|
|
|
|
await kcAdminClient.realms.create({
|
|
|
|
id: realmName,
|
|
|
|
realm: realmName,
|
|
|
|
enabled: true,
|
|
|
|
});
|
|
|
|
currentRealm = realmName;
|
|
|
|
kcAdminClient.setConfig({
|
|
|
|
realmName,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
after(async () => {
|
|
|
|
// delete test realm
|
|
|
|
await kcAdminClient.realms.del({ realm: currentRealm });
|
|
|
|
const realm = await kcAdminClient.realms.findOne({
|
|
|
|
realm: currentRealm,
|
|
|
|
});
|
|
|
|
expect(realm).to.be.null;
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Required Actions
|
|
|
|
*/
|
|
|
|
describe("Required Actions", () => {
|
|
|
|
it("should delete required action by alias", async () => {
|
|
|
|
await kcAdminClient.authenticationManagement.deleteRequiredAction({
|
|
|
|
alias: RequiredActionAlias.UPDATE_PROFILE,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should get unregistered required actions", async () => {
|
|
|
|
const unregisteredReqActions =
|
|
|
|
await kcAdminClient.authenticationManagement.getUnregisteredRequiredActions();
|
|
|
|
expect(unregisteredReqActions).to.be.an("array");
|
|
|
|
expect(unregisteredReqActions.length).to.be.least(1);
|
|
|
|
requiredActionProvider = unregisteredReqActions[0];
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should register new required action", async () => {
|
|
|
|
const requiredAction =
|
|
|
|
await kcAdminClient.authenticationManagement.registerRequiredAction({
|
|
|
|
providerId: requiredActionProvider.providerId,
|
|
|
|
name: requiredActionProvider.name,
|
|
|
|
});
|
|
|
|
expect(requiredAction).to.be.empty;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should get required actions", async () => {
|
|
|
|
const requiredActions =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActions();
|
|
|
|
expect(requiredActions).to.be.an("array");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should get required action by alias", async () => {
|
|
|
|
const requiredAction =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
expect(requiredAction).to.be.ok;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should update required action by alias", async () => {
|
|
|
|
const requiredAction =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
const response =
|
|
|
|
await kcAdminClient.authenticationManagement.updateRequiredAction(
|
|
|
|
{ alias: requiredActionProvider.providerId },
|
|
|
|
{
|
|
|
|
...requiredAction,
|
|
|
|
enabled: true,
|
|
|
|
priority: 10,
|
2023-07-11 14:03:21 +00:00
|
|
|
},
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
expect(response).to.be.empty;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should lower required action priority", async () => {
|
|
|
|
const requiredAction =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
const response =
|
|
|
|
await kcAdminClient.authenticationManagement.lowerRequiredActionPriority(
|
2023-07-11 14:03:21 +00:00
|
|
|
{ alias: requiredActionProvider.providerId },
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
expect(response).to.be.empty;
|
|
|
|
const requiredActionUpdated =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
expect(requiredActionUpdated.priority).to.be.greaterThan(
|
2023-07-11 14:03:21 +00:00
|
|
|
requiredAction.priority,
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should raise required action priority", async () => {
|
|
|
|
const requiredAction =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
const response =
|
|
|
|
await kcAdminClient.authenticationManagement.raiseRequiredActionPriority(
|
2023-07-11 14:03:21 +00:00
|
|
|
{ alias: requiredActionProvider.providerId },
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
expect(response).to.be.empty;
|
|
|
|
const requiredActionUpdated =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionForAlias({
|
|
|
|
alias: requiredActionProvider.providerId,
|
|
|
|
});
|
|
|
|
expect(requiredActionUpdated.priority).to.be.lessThan(
|
2023-07-11 14:03:21 +00:00
|
|
|
requiredAction.priority,
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2024-04-02 22:42:32 +00:00
|
|
|
it("should fetch config description for required action", async () => {
|
|
|
|
const configDescription =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionConfigDescription(
|
|
|
|
{
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(configDescription).is.ok;
|
|
|
|
expect(configDescription.properties).is.ok;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should fetch required action config for update password", async () => {
|
|
|
|
const actionConfig =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionConfig({
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(actionConfig).is.ok;
|
|
|
|
expect(actionConfig.config).is.ok;
|
|
|
|
expect(actionConfig.config!["max_auth_age"]).to.be.eq(300); // default max_auth_age for update password
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should update required action config for update password", async () => {
|
|
|
|
await kcAdminClient.authenticationManagement.updateRequiredActionConfig(
|
|
|
|
{
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
config: {
|
|
|
|
max_auth_age: "301",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
const actionConfig =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionConfig({
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(actionConfig).is.ok;
|
|
|
|
expect(actionConfig.config).is.ok;
|
|
|
|
expect(actionConfig.config!["max_auth_age"]).to.be.eq(301); // updated value max_auth_age for update password
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should reset required action config for update password", async () => {
|
|
|
|
await kcAdminClient.authenticationManagement.removeRequiredActionConfig({
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
});
|
|
|
|
|
|
|
|
const actionConfig =
|
|
|
|
await kcAdminClient.authenticationManagement.getRequiredActionConfig({
|
|
|
|
alias: "UPDATE_PASSWORD",
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(actionConfig).is.ok;
|
|
|
|
expect(actionConfig.config).is.ok;
|
|
|
|
expect(actionConfig.config!["max_auth_age"]).to.be.eq(300); // default max_auth_age for update password
|
|
|
|
});
|
|
|
|
|
2023-02-03 10:45:11 +00:00
|
|
|
it("should get client authenticator providers", async () => {
|
|
|
|
const authenticationProviders =
|
|
|
|
await kcAdminClient.authenticationManagement.getClientAuthenticatorProviders();
|
|
|
|
|
|
|
|
expect(authenticationProviders).is.ok;
|
|
|
|
expect(authenticationProviders.length).to.be.equal(4);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should fetch form providers", async () => {
|
|
|
|
const formProviders =
|
|
|
|
await kcAdminClient.authenticationManagement.getFormActionProviders();
|
|
|
|
expect(formProviders).is.ok;
|
|
|
|
expect(formProviders.length).to.be.eq(4);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should fetch authenticator providers", async () => {
|
|
|
|
const providers =
|
|
|
|
await kcAdminClient.authenticationManagement.getAuthenticatorProviders();
|
|
|
|
expect(providers).is.ok;
|
|
|
|
expect(providers.length).to.be.greaterThan(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Flows", () => {
|
|
|
|
it("should get the registered form providers", async () => {
|
|
|
|
const formProviders =
|
|
|
|
await kcAdminClient.authenticationManagement.getFormProviders();
|
|
|
|
|
|
|
|
expect(formProviders).to.be.ok;
|
|
|
|
expect(formProviders.length).to.be.eq(1);
|
|
|
|
expect(formProviders[0].displayName).to.be.eq("Registration Page");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should get authentication flows", async () => {
|
|
|
|
const flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
|
|
|
|
expect(flows.map((flow) => flow.alias)).to.be.deep.eq([
|
|
|
|
"browser",
|
|
|
|
"direct grant",
|
|
|
|
"registration",
|
|
|
|
"reset credentials",
|
|
|
|
"clients",
|
|
|
|
"first broker login",
|
|
|
|
"docker auth",
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should get authentication flow", async () => {
|
|
|
|
const flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
const flow = await kcAdminClient.authenticationManagement.getFlow({
|
|
|
|
flowId: flows[0].id!,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(flow.alias).to.be.eq("browser");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should create new authentication flow", async () => {
|
|
|
|
const flow = "test";
|
|
|
|
await kcAdminClient.authenticationManagement.createFlow({
|
|
|
|
alias: flow,
|
|
|
|
providerId: "basic-flow",
|
|
|
|
description: "",
|
|
|
|
topLevel: true,
|
|
|
|
builtIn: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
const flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
expect(flows.find((f) => f.alias === flow)).to.be.ok;
|
|
|
|
});
|
|
|
|
|
|
|
|
const flowName = "copy of browser";
|
|
|
|
it("should copy existing authentication flow", async () => {
|
|
|
|
await kcAdminClient.authenticationManagement.copyFlow({
|
|
|
|
flow: "browser",
|
|
|
|
newName: flowName,
|
|
|
|
});
|
|
|
|
|
|
|
|
const flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
const flow = flows.find((f) => f.alias === flowName);
|
|
|
|
expect(flow).to.be.ok;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should update authentication flow", async () => {
|
|
|
|
const flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
const flow = flows.find((f) => f.alias === flowName)!;
|
|
|
|
const description = "Updated description";
|
|
|
|
flow.description = description;
|
|
|
|
const updatedFlow =
|
|
|
|
await kcAdminClient.authenticationManagement.updateFlow(
|
|
|
|
{ flowId: flow.id! },
|
2023-07-11 14:03:21 +00:00
|
|
|
flow,
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
expect(updatedFlow.description).to.be.eq(description);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should delete authentication flow", async () => {
|
|
|
|
let flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
const flow = flows.find((f) => f.alias === flowName)!;
|
|
|
|
await kcAdminClient.authenticationManagement.deleteFlow({
|
|
|
|
flowId: flow.id!,
|
|
|
|
});
|
|
|
|
|
|
|
|
flows = await kcAdminClient.authenticationManagement.getFlows();
|
|
|
|
expect(flows.find((f) => f.alias === flowName)).to.be.undefined;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe("Flow executions", () => {
|
|
|
|
it("should fetch all executions for a flow", async () => {
|
|
|
|
const executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: "browser",
|
|
|
|
});
|
|
|
|
expect(executions.length).to.be.gt(5);
|
|
|
|
});
|
|
|
|
|
|
|
|
const flowName = "executionTest";
|
|
|
|
it("should add execution to a flow", async () => {
|
|
|
|
await kcAdminClient.authenticationManagement.copyFlow({
|
|
|
|
flow: "browser",
|
|
|
|
newName: flowName,
|
|
|
|
});
|
|
|
|
const execution =
|
|
|
|
await kcAdminClient.authenticationManagement.addExecutionToFlow({
|
|
|
|
flow: flowName,
|
|
|
|
provider: "auth-otp-form",
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(execution.id).to.be.ok;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should add flow to a flow", async () => {
|
|
|
|
const flow = await kcAdminClient.authenticationManagement.addFlowToFlow({
|
|
|
|
flow: flowName,
|
|
|
|
alias: "subFlow",
|
|
|
|
description: "",
|
|
|
|
provider: "registration-page-form",
|
|
|
|
type: "basic-flow",
|
|
|
|
});
|
|
|
|
const executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
expect(flow.id).to.be.ok;
|
|
|
|
|
|
|
|
expect(executions.map((execution) => execution.displayName)).includes(
|
2023-07-11 14:03:21 +00:00
|
|
|
"subFlow",
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should update execution to a flow", async () => {
|
|
|
|
let executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
let execution = executions[executions.length - 1];
|
|
|
|
const choice = execution.requirementChoices![1];
|
|
|
|
execution.requirement = choice;
|
|
|
|
await kcAdminClient.authenticationManagement.updateExecution(
|
|
|
|
{ flow: flowName },
|
2023-07-11 14:03:21 +00:00
|
|
|
execution,
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
executions = await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
execution = executions[executions.length - 1];
|
|
|
|
|
|
|
|
expect(execution.requirement).to.be.eq(choice);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should delete execution", async () => {
|
|
|
|
let executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
const id = executions[0].id!;
|
|
|
|
await kcAdminClient.authenticationManagement.delExecution({ id });
|
|
|
|
executions = await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
expect(executions.find((ex) => ex.id === id)).to.be.undefined;
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should raise priority of execution", async () => {
|
|
|
|
let executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
let execution = executions[executions.length - 1];
|
|
|
|
const priority = execution.index!;
|
|
|
|
await kcAdminClient.authenticationManagement.raisePriorityExecution({
|
|
|
|
id: execution.id!,
|
|
|
|
});
|
|
|
|
|
|
|
|
executions = await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
execution = executions.find((ex) => ex.id === execution.id)!;
|
|
|
|
|
|
|
|
expect(execution.index).to.be.eq(priority - 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should lower priority of execution", async () => {
|
|
|
|
let executions =
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
let execution = executions[0];
|
|
|
|
const priority = execution.index!;
|
|
|
|
await kcAdminClient.authenticationManagement.lowerPriorityExecution({
|
|
|
|
id: execution.id!,
|
|
|
|
});
|
|
|
|
|
|
|
|
executions = await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
});
|
|
|
|
execution = executions.find((ex) => ex.id === execution.id)!;
|
|
|
|
|
|
|
|
expect(execution.index).to.be.eq(priority + 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should create, update and delete config for execution", async () => {
|
|
|
|
const execution = (
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
})
|
|
|
|
)[0];
|
|
|
|
const alias = "test";
|
|
|
|
let config = await kcAdminClient.authenticationManagement.createConfig({
|
|
|
|
id: execution.id,
|
|
|
|
alias,
|
|
|
|
});
|
|
|
|
config = await kcAdminClient.authenticationManagement.getConfig({
|
|
|
|
id: config.id!,
|
|
|
|
});
|
|
|
|
expect(config.alias).to.be.eq(alias);
|
|
|
|
|
|
|
|
const extraConfig = { defaultProvider: "sdf" };
|
|
|
|
await kcAdminClient.authenticationManagement.updateConfig({
|
|
|
|
...config,
|
|
|
|
config: extraConfig,
|
|
|
|
});
|
|
|
|
config = await kcAdminClient.authenticationManagement.getConfig({
|
|
|
|
id: config.id!,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(config.config!.defaultProvider).to.be.eq(
|
2023-07-11 14:03:21 +00:00
|
|
|
extraConfig.defaultProvider,
|
2023-02-03 10:45:11 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
await kcAdminClient.authenticationManagement.delConfig({
|
|
|
|
id: config.id!,
|
|
|
|
});
|
|
|
|
try {
|
|
|
|
await kcAdminClient.authenticationManagement.getConfig({
|
|
|
|
id: config.id!,
|
|
|
|
});
|
|
|
|
fail("should not find deleted config");
|
|
|
|
} catch (error) {
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should fetch config description for execution", async () => {
|
|
|
|
const execution = (
|
|
|
|
await kcAdminClient.authenticationManagement.getExecutions({
|
|
|
|
flow: flowName,
|
|
|
|
})
|
|
|
|
)[0];
|
|
|
|
|
|
|
|
const configDescription =
|
|
|
|
await kcAdminClient.authenticationManagement.getConfigDescription({
|
|
|
|
providerId: execution.providerId!,
|
|
|
|
});
|
|
|
|
expect(configDescription).is.ok;
|
|
|
|
expect(configDescription.providerId).to.be.eq(execution.providerId);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|