Compare commits
52 Commits
v11.3.26
...
keycloak_c
Author | SHA1 | Date | |
---|---|---|---|
10cfa1cf41 | |||
3938584aeb | |||
163b060dc5 | |||
67f8ae41fc | |||
b6e9fe2585 | |||
5b83bd8fa9 | |||
d0f43b6318 | |||
df338ed6a0 | |||
295994d02a | |||
f9e15f93c4 | |||
2659cf391c | |||
76416ddd5b | |||
8e8a0ccf54 | |||
db0ec954df | |||
dc942aa5de | |||
029cfcb591 | |||
b1b6919395 | |||
9185740d35 | |||
8d59fe7b67 | |||
92b505dd56 | |||
c0e6661d3d | |||
0cae2c68d8 | |||
1e43343529 | |||
0a74dca7c2 | |||
a66a373256 | |||
606cf7ad02 | |||
5225749c7b | |||
819e3833ad | |||
b0ba37fcc4 | |||
f4829b557f | |||
60a9b5a693 | |||
c323b94a8c | |||
4bbc0241ec | |||
5a7dacfcdd | |||
7e05e1bf0c | |||
1530ca32c8 | |||
ed054f131a | |||
ec74ceef4d | |||
fd3261cdf1 | |||
b4b53d2552 | |||
0371d9ea7a | |||
73031e74ec | |||
f71ab4635f | |||
983db6780a | |||
ea22107b9b | |||
8e4a7fed9e | |||
30efd8fcf4 | |||
f4c4e92ca1 | |||
cfda99f5b0 | |||
5063b1c7ab | |||
955b6cac45 | |||
1fa3d6133c |
@ -12,4 +12,5 @@ node_modules/
|
|||||||
/sample_react_project/
|
/sample_react_project/
|
||||||
/sample_custom_react_project/
|
/sample_custom_react_project/
|
||||||
/keycloakify_starter_test/
|
/keycloakify_starter_test/
|
||||||
/.storybook/static/keycloak-resources/
|
/.storybook/static/keycloak-resources/
|
||||||
|
/src/bin/start-keycloak/*.json
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "keycloakify",
|
"name": "keycloakify",
|
||||||
"version": "11.3.26",
|
"version": "11.4.5",
|
||||||
"description": "Framework to create custom Keycloak UIs",
|
"description": "Framework to create custom Keycloak UIs",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
39
scripts/build/downloadKeycloakifyLogging.ts
Normal file
39
scripts/build/downloadKeycloakifyLogging.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { downloadAndExtractArchive } from "../../src/bin/tools/downloadAndExtractArchive";
|
||||||
|
import { cacheDirPath } from "../shared/cacheDirPath";
|
||||||
|
import { getProxyFetchOptions } from "../../src/bin/tools/fetchProxyOptions";
|
||||||
|
import { getThisCodebaseRootDirPath } from "../../src/bin/tools/getThisCodebaseRootDirPath";
|
||||||
|
import { existsAsync } from "../../src/bin/tools/fs.existsAsync";
|
||||||
|
import * as fs from "fs/promises";
|
||||||
|
import {
|
||||||
|
KEYCLOAKIFY_LOGGING_VERSION,
|
||||||
|
KEYCLOAKIFY_LOGIN_JAR_BASENAME
|
||||||
|
} from "../../src/bin/shared/constants";
|
||||||
|
import { join as pathJoin } from "path";
|
||||||
|
|
||||||
|
export async function downloadKeycloakifyLogging(params: { distDirPath: string }) {
|
||||||
|
const { distDirPath } = params;
|
||||||
|
|
||||||
|
const jarFilePath = pathJoin(
|
||||||
|
distDirPath,
|
||||||
|
"src",
|
||||||
|
"bin",
|
||||||
|
"start-keycloak",
|
||||||
|
KEYCLOAKIFY_LOGIN_JAR_BASENAME
|
||||||
|
);
|
||||||
|
|
||||||
|
if (await existsAsync(jarFilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { archiveFilePath } = await downloadAndExtractArchive({
|
||||||
|
cacheDirPath,
|
||||||
|
fetchOptions: getProxyFetchOptions({
|
||||||
|
npmConfigGetCwd: getThisCodebaseRootDirPath()
|
||||||
|
}),
|
||||||
|
url: `https://github.com/keycloakify/keycloakify-logging/releases/download/${KEYCLOAKIFY_LOGGING_VERSION}/keycloakify-logging-${KEYCLOAKIFY_LOGGING_VERSION}.jar`,
|
||||||
|
uniqueIdOfOnArchiveFile: "no extraction",
|
||||||
|
onArchiveFile: async () => {}
|
||||||
|
});
|
||||||
|
|
||||||
|
await fs.cp(archiveFilePath, jarFilePath);
|
||||||
|
}
|
@ -7,6 +7,7 @@ import { createAccountV1Dir } from "./createAccountV1Dir";
|
|||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { run } from "../shared/run";
|
import { run } from "../shared/run";
|
||||||
import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
||||||
|
import { downloadKeycloakifyLogging } from "./downloadKeycloakifyLogging";
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log(chalk.cyan("Building Keycloakify..."));
|
console.log(chalk.cyan("Building Keycloakify..."));
|
||||||
@ -148,9 +149,6 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
|||||||
fs.cpSync(dirBasename, destDirPath, { recursive: true });
|
fs.cpSync(dirBasename, destDirPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await createPublicKeycloakifyDevResourcesDir();
|
|
||||||
await createAccountV1Dir();
|
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
srcDirPath: join("stories"),
|
srcDirPath: join("stories"),
|
||||||
destDirPath: join("dist", "stories"),
|
destDirPath: join("dist", "stories"),
|
||||||
@ -163,6 +161,12 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await createPublicKeycloakifyDevResourcesDir();
|
||||||
|
await createAccountV1Dir();
|
||||||
|
await downloadKeycloakifyLogging({
|
||||||
|
distDirPath: join(process.cwd(), "dist")
|
||||||
|
});
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
|
chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
|
||||||
);
|
);
|
||||||
|
@ -1,65 +1,15 @@
|
|||||||
import { CONTAINER_NAME } from "../src/bin/shared/constants";
|
import { CONTAINER_NAME } from "../src/bin/shared/constants";
|
||||||
import child_process from "child_process";
|
import child_process from "child_process";
|
||||||
import { SemVer } from "../src/bin/tools/SemVer";
|
import { SemVer } from "../src/bin/tools/SemVer";
|
||||||
import { join as pathJoin, relative as pathRelative } from "path";
|
import { dumpContainerConfig } from "../src/bin/start-keycloak/realmConfig/dumpContainerConfig";
|
||||||
|
import { cacheDirPath } from "./shared/cacheDirPath";
|
||||||
|
import { runPrettier } from "../src/bin/tools/runPrettier";
|
||||||
|
import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath";
|
||||||
|
import { join as pathJoin } from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { Deferred } from "evt/tools/Deferred";
|
|
||||||
import { assert, is } from "tsafe/assert";
|
|
||||||
import { run } from "./shared/run";
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
{
|
|
||||||
const dCompleted = new Deferred<void>();
|
|
||||||
|
|
||||||
const child = child_process.spawn(
|
|
||||||
"docker",
|
|
||||||
[
|
|
||||||
...["exec", CONTAINER_NAME],
|
|
||||||
...["/opt/keycloak/bin/kc.sh", "export"],
|
|
||||||
...["--dir", "/tmp"],
|
|
||||||
...["--realm", "myrealm"],
|
|
||||||
...["--users", "realm_file"]
|
|
||||||
],
|
|
||||||
{ shell: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
let output = "";
|
|
||||||
|
|
||||||
const onExit = (code: number | null) => {
|
|
||||||
dCompleted.reject(new Error(`Exited with code ${code}`));
|
|
||||||
};
|
|
||||||
|
|
||||||
child.on("exit", onExit);
|
|
||||||
|
|
||||||
child.stdout.on("data", data => {
|
|
||||||
const outputStr = data.toString("utf8");
|
|
||||||
|
|
||||||
if (outputStr.includes("Export finished successfully")) {
|
|
||||||
child.removeListener("exit", onExit);
|
|
||||||
|
|
||||||
child.kill();
|
|
||||||
|
|
||||||
dCompleted.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
output += outputStr;
|
|
||||||
});
|
|
||||||
|
|
||||||
child.stderr.on("data", data => (output += chalk.red(data.toString("utf8"))));
|
|
||||||
|
|
||||||
try {
|
|
||||||
await dCompleted.pr;
|
|
||||||
} catch (error) {
|
|
||||||
assert(is<Error>(error));
|
|
||||||
|
|
||||||
console.log(chalk.red(error.message));
|
|
||||||
|
|
||||||
console.log(output);
|
|
||||||
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const keycloakMajorVersionNumber = SemVer.parse(
|
const keycloakMajorVersionNumber = SemVer.parse(
|
||||||
child_process
|
child_process
|
||||||
.execSync(`docker inspect --format '{{.Config.Image}}' ${CONTAINER_NAME}`)
|
.execSync(`docker inspect --format '{{.Config.Image}}' ${CONTAINER_NAME}`)
|
||||||
@ -68,19 +18,32 @@ import { run } from "./shared/run";
|
|||||||
.split(":")[1]
|
.split(":")[1]
|
||||||
).major;
|
).major;
|
||||||
|
|
||||||
const targetFilePath = pathRelative(
|
const parsedRealmJson = await dumpContainerConfig({
|
||||||
process.cwd(),
|
buildContext: {
|
||||||
pathJoin(
|
cacheDirPath
|
||||||
__dirname,
|
},
|
||||||
"..",
|
keycloakMajorVersionNumber,
|
||||||
"src",
|
realmName: "myrealm"
|
||||||
"bin",
|
});
|
||||||
"start-keycloak",
|
|
||||||
`myrealm-realm-${keycloakMajorVersionNumber}.json`
|
let sourceCode = JSON.stringify(parsedRealmJson, null, 2);
|
||||||
)
|
|
||||||
|
const filePath = pathJoin(
|
||||||
|
getThisCodebaseRootDirPath(),
|
||||||
|
"src",
|
||||||
|
"bin",
|
||||||
|
"start-keycloak",
|
||||||
|
"realmConfig",
|
||||||
|
"defaultConfig",
|
||||||
|
`realm-kc-${keycloakMajorVersionNumber}.json`
|
||||||
);
|
);
|
||||||
|
|
||||||
run(`docker cp ${CONTAINER_NAME}:/tmp/myrealm-realm.json ${targetFilePath}`);
|
sourceCode = await runPrettier({
|
||||||
|
sourceCode,
|
||||||
|
filePath
|
||||||
|
});
|
||||||
|
|
||||||
console.log(`${chalk.green(`✓ Exported realm to`)} ${chalk.bold(targetFilePath)}`);
|
fs.writeFileSync(filePath, Buffer.from(sourceCode, "utf8"));
|
||||||
|
|
||||||
|
console.log(chalk.green(`Realm config dumped to ${filePath}`));
|
||||||
})();
|
})();
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { type TemplateProps, type ClassKey } from "keycloakify/account/TemplateProps";
|
import { type TemplateProps, type ClassKey } from "keycloakify/account/TemplateProps";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { i18nBuilder } from "keycloakify/account";
|
import { i18nBuilder } from "keycloakify/account";
|
||||||
import type { ThemeName } from "../kc.gen";
|
import type { ThemeName } from "../kc.gen";
|
||||||
|
|
||||||
const { useI18n, ofTypeI18n } = i18nBuilder
|
/** @see: https://docs.keycloakify.dev/i18n */
|
||||||
.withThemeName<ThemeName>()
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
.withExtraLanguages({})
|
const { useI18n, ofTypeI18n } = i18nBuilder.withThemeName<ThemeName>().build();
|
||||||
.withCustomTranslations({})
|
|
||||||
.build();
|
|
||||||
|
|
||||||
type I18n = typeof ofTypeI18n;
|
type I18n = typeof ofTypeI18n;
|
||||||
|
|
||||||
|
@ -11,7 +11,11 @@ import * as fs from "fs";
|
|||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { type ThemeType, WELL_KNOWN_DIRECTORY_BASE_NAME } from "../../shared/constants";
|
import {
|
||||||
|
type ThemeType,
|
||||||
|
WELL_KNOWN_DIRECTORY_BASE_NAME,
|
||||||
|
KEYCLOAKIFY_SPA_DEV_SERVER_PORT
|
||||||
|
} from "../../shared/constants";
|
||||||
import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
|
import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
|
||||||
|
|
||||||
export type BuildContextLike = BuildContextLike_replaceImportsInJsCode &
|
export type BuildContextLike = BuildContextLike_replaceImportsInJsCode &
|
||||||
@ -116,6 +120,7 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
.replace("{{themeVersion}}", buildContext.themeVersion)
|
.replace("{{themeVersion}}", buildContext.themeVersion)
|
||||||
.replace("{{fieldNames}}", fieldNames.map(name => `"${name}"`).join(", "))
|
.replace("{{fieldNames}}", fieldNames.map(name => `"${name}"`).join(", "))
|
||||||
.replace("{{RESOURCES_COMMON}}", WELL_KNOWN_DIRECTORY_BASE_NAME.RESOURCES_COMMON)
|
.replace("{{RESOURCES_COMMON}}", WELL_KNOWN_DIRECTORY_BASE_NAME.RESOURCES_COMMON)
|
||||||
|
.replace("{{KEYCLOAKIFY_SPA_DEV_SERVER_PORT}}", KEYCLOAKIFY_SPA_DEV_SERVER_PORT)
|
||||||
.replace(
|
.replace(
|
||||||
"{{userDefinedExclusions}}",
|
"{{userDefinedExclusions}}",
|
||||||
buildContext.kcContextExclusionsFtlCode ?? ""
|
buildContext.kcContextExclusionsFtlCode ?? ""
|
||||||
|
@ -84,8 +84,47 @@ attributes_to_attributesByName: {
|
|||||||
kcContext.profile.attributesByName[attribute.name] = attribute;
|
kcContext.profile.attributesByName[attribute.name] = attribute;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redirect_to_dev_server: {
|
||||||
|
|
||||||
|
switch(kcContext.themeType){
|
||||||
|
case "login":
|
||||||
|
break redirect_to_dev_server;
|
||||||
|
case "account":
|
||||||
|
if( kcContext.pageId !== "index.ftl" ){
|
||||||
|
break redirect_to_dev_server;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "admin":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break redirect_to_dev_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
const devSeverPort = kcContext.properties.{{KEYCLOAKIFY_SPA_DEV_SERVER_PORT}};
|
||||||
|
|
||||||
|
if( !devSeverPort ){
|
||||||
|
break redirect_to_dev_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
const redirectUrl = new URL(window.location.href);
|
||||||
|
|
||||||
|
redirectUrl.port = devSeverPort;
|
||||||
|
|
||||||
|
delete kcContext.msgJSON;
|
||||||
|
|
||||||
|
console.log(kcContext);
|
||||||
|
|
||||||
|
redirectUrl.searchParams.set("kcContext", encodeURIComponent(JSON.stringify(kcContext)));
|
||||||
|
|
||||||
|
window.location.href = redirectUrl.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
window.kcContext = kcContext;
|
window.kcContext = kcContext;
|
||||||
|
|
||||||
|
|
||||||
<#if xKeycloakify.themeType == "login" >
|
<#if xKeycloakify.themeType == "login" >
|
||||||
{
|
{
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
|
@ -20,7 +20,8 @@ import {
|
|||||||
LOGIN_THEME_PAGE_IDS,
|
LOGIN_THEME_PAGE_IDS,
|
||||||
ACCOUNT_THEME_PAGE_IDS,
|
ACCOUNT_THEME_PAGE_IDS,
|
||||||
WELL_KNOWN_DIRECTORY_BASE_NAME,
|
WELL_KNOWN_DIRECTORY_BASE_NAME,
|
||||||
THEME_TYPES
|
THEME_TYPES,
|
||||||
|
KEYCLOAKIFY_SPA_DEV_SERVER_PORT
|
||||||
} from "../../shared/constants";
|
} from "../../shared/constants";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
import { readFieldNameUsage } from "./readFieldNameUsage";
|
import { readFieldNameUsage } from "./readFieldNameUsage";
|
||||||
@ -379,7 +380,10 @@ export async function generateResources(params: {
|
|||||||
? ["deprecatedMode=false"]
|
? ["deprecatedMode=false"]
|
||||||
: []),
|
: []),
|
||||||
...(buildContext.extraThemeProperties ?? []),
|
...(buildContext.extraThemeProperties ?? []),
|
||||||
...buildContext.environmentVariables.map(
|
...[
|
||||||
|
...buildContext.environmentVariables,
|
||||||
|
{ name: KEYCLOAKIFY_SPA_DEV_SERVER_PORT, default: "" }
|
||||||
|
].map(
|
||||||
({ name, default: defaultValue }) =>
|
({ name, default: defaultValue }) =>
|
||||||
`${name}=\${env.${name}:${escapeStringForPropertiesFile(defaultValue)}}`
|
`${name}=\${env.${name}:${escapeStringForPropertiesFile(defaultValue)}}`
|
||||||
),
|
),
|
||||||
|
@ -5,6 +5,9 @@ import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
|
|||||||
import * as child_process from "child_process";
|
import * as child_process from "child_process";
|
||||||
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
|
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
|
||||||
import { getBuildContext } from "./shared/buildContext";
|
import { getBuildContext } from "./shared/buildContext";
|
||||||
|
import { SemVer } from "./tools/SemVer";
|
||||||
|
import { assert, is } from "tsafe/assert";
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
type CliCommandOptions = {
|
type CliCommandOptions = {
|
||||||
projectDirPath: string | undefined;
|
projectDirPath: string | undefined;
|
||||||
@ -80,7 +83,7 @@ program
|
|||||||
program
|
program
|
||||||
.command<{
|
.command<{
|
||||||
port: number | undefined;
|
port: number | undefined;
|
||||||
keycloakVersion: string | undefined;
|
keycloakVersion: string | number | undefined;
|
||||||
realmJsonFilePath: string | undefined;
|
realmJsonFilePath: string | undefined;
|
||||||
}>({
|
}>({
|
||||||
name: "start-keycloak",
|
name: "start-keycloak",
|
||||||
@ -134,9 +137,50 @@ program
|
|||||||
handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
|
handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
|
||||||
const { command } = await import("./start-keycloak");
|
const { command } = await import("./start-keycloak");
|
||||||
|
|
||||||
|
validate_keycloak_version: {
|
||||||
|
if (keycloakVersion === undefined) {
|
||||||
|
break validate_keycloak_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidVersion = (() => {
|
||||||
|
if (typeof keycloakVersion === "number") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
SemVer.parse(keycloakVersion);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (isValidVersion) {
|
||||||
|
break validate_keycloak_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.red(
|
||||||
|
[
|
||||||
|
`Invalid Keycloak version: ${keycloakVersion}`,
|
||||||
|
"It should be a valid semver version example: 26.0.4"
|
||||||
|
].join(" ")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(is<string | undefined>(keycloakVersion));
|
||||||
|
|
||||||
await command({
|
await command({
|
||||||
buildContext: getBuildContext({ projectDirPath }),
|
buildContext: getBuildContext({ projectDirPath }),
|
||||||
cliCommandOptions: { keycloakVersion, port, realmJsonFilePath }
|
cliCommandOptions: {
|
||||||
|
keycloakVersion,
|
||||||
|
port,
|
||||||
|
realmJsonFilePath
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -201,7 +245,7 @@ program
|
|||||||
.command({
|
.command({
|
||||||
name: "copy-keycloak-resources-to-public",
|
name: "copy-keycloak-resources-to-public",
|
||||||
description:
|
description:
|
||||||
"(Webpack/Create-React-App only) Copy Keycloak default theme resources to the public directory."
|
"(Internal) Copy Keycloak default theme resources to the public directory."
|
||||||
})
|
})
|
||||||
.task({
|
.task({
|
||||||
skip,
|
skip,
|
||||||
|
@ -10,7 +10,8 @@ export type ThemeType = (typeof THEME_TYPES)[number];
|
|||||||
|
|
||||||
export const VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES = {
|
export const VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES = {
|
||||||
RUN_POST_BUILD_SCRIPT: "KEYCLOAKIFY_RUN_POST_BUILD_SCRIPT",
|
RUN_POST_BUILD_SCRIPT: "KEYCLOAKIFY_RUN_POST_BUILD_SCRIPT",
|
||||||
RESOLVE_VITE_CONFIG: "KEYCLOAKIFY_RESOLVE_VITE_CONFIG"
|
RESOLVE_VITE_CONFIG: "KEYCLOAKIFY_RESOLVE_VITE_CONFIG",
|
||||||
|
READ_KC_CONTEXT_FROM_URL: "KEYCLOAKIFY_READ_KC_CONTEXT_FROM_URL"
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const BUILD_FOR_KEYCLOAK_MAJOR_VERSION_ENV_NAME =
|
export const BUILD_FOR_KEYCLOAK_MAJOR_VERSION_ENV_NAME =
|
||||||
@ -78,3 +79,11 @@ export const CUSTOM_HANDLER_ENV_NAMES = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const KEYCLOAK_THEME = "keycloak-theme";
|
export const KEYCLOAK_THEME = "keycloak-theme";
|
||||||
|
|
||||||
|
export const KEYCLOAKIFY_SPA_DEV_SERVER_PORT = "KEYCLOAKIFY_SPA_DEV_SERVER_PORT";
|
||||||
|
|
||||||
|
export const KEYCLOAKIFY_LOGGING_VERSION = "1.0.3";
|
||||||
|
|
||||||
|
export const KEYCLOAKIFY_LOGIN_JAR_BASENAME = `keycloakify-logging-${KEYCLOAKIFY_LOGGING_VERSION}.jar`;
|
||||||
|
|
||||||
|
export const TEST_APP_URL = "https://my-theme.keycloakify.dev";
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
import * as child_process from "child_process";
|
import * as child_process from "child_process";
|
||||||
import { Deferred } from "evt/tools/Deferred";
|
import { Deferred } from "evt/tools/Deferred";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert, is, type Equals } from "tsafe/assert";
|
||||||
|
import { id } from "tsafe/id";
|
||||||
import type { BuildContext } from "../shared/buildContext";
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { sep as pathSep, join as pathJoin } from "path";
|
import { sep as pathSep, join as pathJoin } from "path";
|
||||||
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
|
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { dirname as pathDirname, relative as pathRelative } from "path";
|
import { dirname as pathDirname, relative as pathRelative } from "path";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
projectDirPath: string;
|
projectDirPath: string;
|
||||||
keycloakifyBuildDirPath: string;
|
|
||||||
bundler: BuildContext["bundler"];
|
|
||||||
projectBuildDirPath: string;
|
|
||||||
packageJsonFilePath: string;
|
packageJsonFilePath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,58 +22,36 @@ export async function appBuild(params: {
|
|||||||
}): Promise<{ isAppBuildSuccess: boolean }> {
|
}): Promise<{ isAppBuildSuccess: boolean }> {
|
||||||
const { buildContext } = params;
|
const { buildContext } = params;
|
||||||
|
|
||||||
switch (buildContext.bundler) {
|
const { parsedPackageJson } = (() => {
|
||||||
case "vite":
|
type ParsedPackageJson = {
|
||||||
return appBuild_vite({ buildContext });
|
scripts?: Record<string, string>;
|
||||||
case "webpack":
|
};
|
||||||
return appBuild_webpack({ buildContext });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function appBuild_vite(params: {
|
const zParsedPackageJson = (() => {
|
||||||
buildContext: BuildContextLike;
|
type TargetType = ParsedPackageJson;
|
||||||
}): Promise<{ isAppBuildSuccess: boolean }> {
|
|
||||||
const { buildContext } = params;
|
|
||||||
|
|
||||||
assert(buildContext.bundler === "vite");
|
const zTargetType = z.object({
|
||||||
|
scripts: z.record(z.string()).optional()
|
||||||
|
});
|
||||||
|
|
||||||
const dIsSuccess = new Deferred<boolean>();
|
assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
|
||||||
|
|
||||||
console.log(chalk.blue("$ npx vite build"));
|
return id<z.ZodType<TargetType>>(zTargetType);
|
||||||
|
})();
|
||||||
|
const parsedPackageJson = JSON.parse(
|
||||||
|
fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
|
||||||
|
);
|
||||||
|
|
||||||
const child = child_process.spawn("npx", ["vite", "build"], {
|
zParsedPackageJson.parse(parsedPackageJson);
|
||||||
cwd: buildContext.projectDirPath,
|
|
||||||
shell: true
|
|
||||||
});
|
|
||||||
|
|
||||||
child.stdout.on("data", data => {
|
assert(is<ParsedPackageJson>(parsedPackageJson));
|
||||||
if (data.toString("utf8").includes("gzip:")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
process.stdout.write(data);
|
return { parsedPackageJson };
|
||||||
});
|
})();
|
||||||
|
|
||||||
child.stderr.on("data", data => process.stderr.write(data));
|
const entries = Object.entries(parsedPackageJson.scripts ?? {}).filter(
|
||||||
|
([, scriptCommand]) => scriptCommand.includes("keycloakify build")
|
||||||
child.on("exit", code => dIsSuccess.resolve(code === 0));
|
);
|
||||||
|
|
||||||
const isSuccess = await dIsSuccess.pr;
|
|
||||||
|
|
||||||
return { isAppBuildSuccess: isSuccess };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function appBuild_webpack(params: {
|
|
||||||
buildContext: BuildContextLike;
|
|
||||||
}): Promise<{ isAppBuildSuccess: boolean }> {
|
|
||||||
const { buildContext } = params;
|
|
||||||
|
|
||||||
assert(buildContext.bundler === "webpack");
|
|
||||||
|
|
||||||
const entries = Object.entries(
|
|
||||||
(JSON.parse(fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8"))
|
|
||||||
.scripts ?? {}) as Record<string, string>
|
|
||||||
).filter(([, scriptCommand]) => scriptCommand.includes("keycloakify build"));
|
|
||||||
|
|
||||||
if (entries.length === 0) {
|
if (entries.length === 0) {
|
||||||
console.log(
|
console.log(
|
||||||
@ -127,6 +104,76 @@ async function appBuild_webpack(params: {
|
|||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_case: {
|
||||||
|
if (appBuildSubCommands.length !== 1) {
|
||||||
|
break common_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [appBuildSubCommand] = appBuildSubCommands;
|
||||||
|
|
||||||
|
const isNpmRunBuild = (() => {
|
||||||
|
for (const packageManager of ["npm", "yarn", "pnpm", "bun", "deno"]) {
|
||||||
|
for (const doUseRun of [true, false]) {
|
||||||
|
if (
|
||||||
|
`${packageManager}${doUseRun ? " run " : " "}build` ===
|
||||||
|
appBuildSubCommand
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (!isNpmRunBuild) {
|
||||||
|
break common_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { scripts } = parsedPackageJson;
|
||||||
|
|
||||||
|
assert(scripts !== undefined);
|
||||||
|
|
||||||
|
const buildCmd = scripts.build;
|
||||||
|
|
||||||
|
if (buildCmd !== "tsc && vite build") {
|
||||||
|
break common_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scripts.prebuild !== undefined) {
|
||||||
|
break common_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scripts.postbuild !== undefined) {
|
||||||
|
break common_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dIsSuccess = new Deferred<boolean>();
|
||||||
|
|
||||||
|
console.log(chalk.blue("$ npx vite build"));
|
||||||
|
|
||||||
|
const child = child_process.spawn("npx", ["vite", "build"], {
|
||||||
|
cwd: buildContext.projectDirPath,
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stdout.on("data", data => {
|
||||||
|
if (data.toString("utf8").includes("gzip:")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process.stdout.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on("data", data => process.stderr.write(data));
|
||||||
|
|
||||||
|
child.on("exit", code => dIsSuccess.resolve(code === 0));
|
||||||
|
|
||||||
|
const isSuccess = await dIsSuccess.pr;
|
||||||
|
|
||||||
|
return { isAppBuildSuccess: isSuccess };
|
||||||
|
}
|
||||||
|
|
||||||
let commandCwd = pathDirname(buildContext.packageJsonFilePath);
|
let commandCwd = pathDirname(buildContext.packageJsonFilePath);
|
||||||
|
|
||||||
for (const subCommand of appBuildSubCommands) {
|
for (const subCommand of appBuildSubCommands) {
|
||||||
|
230
src/bin/start-keycloak/getSupportedDockerImageTags.ts
Normal file
230
src/bin/start-keycloak/getSupportedDockerImageTags.ts
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
import fetch from "make-fetch-happen";
|
||||||
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
import { id } from "tsafe/id";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { SemVer } from "../tools/SemVer";
|
||||||
|
import { exclude } from "tsafe/exclude";
|
||||||
|
import { getSupportedKeycloakMajorVersions } from "./realmConfig/defaultConfig";
|
||||||
|
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||||
|
import * as fs from "fs/promises";
|
||||||
|
import { existsAsync } from "../tools/fs.existsAsync";
|
||||||
|
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
|
||||||
|
|
||||||
|
export type BuildContextLike = {
|
||||||
|
fetchOptions: BuildContext["fetchOptions"];
|
||||||
|
cacheDirPath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>;
|
||||||
|
|
||||||
|
export async function getSupportedDockerImageTags(params: {
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}) {
|
||||||
|
const { buildContext } = params;
|
||||||
|
|
||||||
|
{
|
||||||
|
const result = await getCachedValue({ cacheDirPath: buildContext.cacheDirPath });
|
||||||
|
|
||||||
|
if (result !== undefined) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags: string[] = [];
|
||||||
|
|
||||||
|
await (async function callee(url: string) {
|
||||||
|
const r = await fetch(url, buildContext.fetchOptions);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
(async () => {
|
||||||
|
tags.push(
|
||||||
|
...z
|
||||||
|
.object({
|
||||||
|
tags: z.array(z.string())
|
||||||
|
})
|
||||||
|
.parse(await r.json()).tags
|
||||||
|
);
|
||||||
|
})(),
|
||||||
|
(async () => {
|
||||||
|
const link = r.headers.get("link");
|
||||||
|
|
||||||
|
if (link === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const split = link.split(";").map(s => s.trim());
|
||||||
|
|
||||||
|
assert(split.length === 2);
|
||||||
|
|
||||||
|
assert(split[1] === 'rel="next"');
|
||||||
|
|
||||||
|
const match = split[0].match(/^<(.+)>$/);
|
||||||
|
|
||||||
|
assert(match !== null);
|
||||||
|
|
||||||
|
const nextUrl = new URL(url).origin + match[1];
|
||||||
|
|
||||||
|
await callee(nextUrl);
|
||||||
|
})()
|
||||||
|
]);
|
||||||
|
})("https://quay.io/v2/keycloak/keycloak/tags/list");
|
||||||
|
|
||||||
|
const arr = tags
|
||||||
|
.map(tag => ({
|
||||||
|
tag,
|
||||||
|
version: (() => {
|
||||||
|
if (tag.includes("-")) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let version: SemVer;
|
||||||
|
|
||||||
|
try {
|
||||||
|
version = SemVer.parse(tag);
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return version;
|
||||||
|
})()
|
||||||
|
}))
|
||||||
|
.map(({ tag, version }) => (version === undefined ? undefined : { tag, version }))
|
||||||
|
.filter(exclude(undefined));
|
||||||
|
|
||||||
|
const versionByMajor: Record<number, SemVer | undefined> = {};
|
||||||
|
|
||||||
|
for (const { version } of arr) {
|
||||||
|
const version_current = versionByMajor[version.major];
|
||||||
|
|
||||||
|
if (
|
||||||
|
version_current === undefined ||
|
||||||
|
SemVer.compare(version_current, version) === -1
|
||||||
|
) {
|
||||||
|
versionByMajor[version.major] = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const supportedKeycloakMajorVersions = getSupportedKeycloakMajorVersions();
|
||||||
|
|
||||||
|
const result = Object.entries(versionByMajor)
|
||||||
|
.sort(([a], [b]) => parseInt(b) - parseInt(a))
|
||||||
|
.map(([, version]) => version)
|
||||||
|
.map(version => {
|
||||||
|
assert(version !== undefined);
|
||||||
|
|
||||||
|
if (!supportedKeycloakMajorVersions.includes(version.major)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SemVer.stringify(version);
|
||||||
|
})
|
||||||
|
.filter(exclude(undefined));
|
||||||
|
|
||||||
|
await setCachedValue({ cacheDirPath: buildContext.cacheDirPath, result });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { getCachedValue, setCachedValue } = (() => {
|
||||||
|
type Cache = {
|
||||||
|
keycloakifyVersion: string;
|
||||||
|
time: number;
|
||||||
|
result: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const zCache = (() => {
|
||||||
|
type TargetType = Cache;
|
||||||
|
|
||||||
|
const zTargetType = z.object({
|
||||||
|
keycloakifyVersion: z.string(),
|
||||||
|
time: z.number(),
|
||||||
|
result: z.array(z.string())
|
||||||
|
});
|
||||||
|
|
||||||
|
type InferredType = z.infer<typeof zTargetType>;
|
||||||
|
|
||||||
|
assert<Equals<TargetType, InferredType>>;
|
||||||
|
|
||||||
|
return id<z.ZodType<TargetType>>(zTargetType);
|
||||||
|
})();
|
||||||
|
|
||||||
|
let inMemoryCachedResult: Cache["result"] | undefined = undefined;
|
||||||
|
|
||||||
|
function getCacheFilePath(params: { cacheDirPath: string }) {
|
||||||
|
const { cacheDirPath } = params;
|
||||||
|
|
||||||
|
return pathJoin(cacheDirPath, "supportedDockerImageTags.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCachedValue(params: { cacheDirPath: string }) {
|
||||||
|
const { cacheDirPath } = params;
|
||||||
|
|
||||||
|
if (inMemoryCachedResult !== undefined) {
|
||||||
|
return inMemoryCachedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheFilePath = getCacheFilePath({ cacheDirPath });
|
||||||
|
|
||||||
|
if (!(await existsAsync(cacheFilePath))) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache: Cache | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cache = zCache.parse(JSON.parse(await fs.readFile(cacheFilePath, "utf8")));
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache.keycloakifyVersion !== readThisNpmPackageVersion()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Date.now() - cache.time > 3_600 * 24) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
inMemoryCachedResult = cache.result;
|
||||||
|
|
||||||
|
return cache.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setCachedValue(params: {
|
||||||
|
cacheDirPath: string;
|
||||||
|
result: Cache["result"];
|
||||||
|
}) {
|
||||||
|
const { cacheDirPath, result } = params;
|
||||||
|
|
||||||
|
inMemoryCachedResult = result;
|
||||||
|
|
||||||
|
const cacheFilePath = getCacheFilePath({ cacheDirPath });
|
||||||
|
|
||||||
|
{
|
||||||
|
const dirPath = pathDirname(cacheFilePath);
|
||||||
|
|
||||||
|
if (!(await existsAsync(dirPath))) {
|
||||||
|
await fs.mkdir(dirPath, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
cacheFilePath,
|
||||||
|
JSON.stringify(
|
||||||
|
zCache.parse({
|
||||||
|
keycloakifyVersion: readThisNpmPackageVersion(),
|
||||||
|
time: Date.now(),
|
||||||
|
result
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getCachedValue,
|
||||||
|
setCachedValue
|
||||||
|
};
|
||||||
|
})();
|
118
src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts
Normal file
118
src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
import { is } from "tsafe/is";
|
||||||
|
import { id } from "tsafe/id";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
export type ParsedRealmJson = {
|
||||||
|
realm: string;
|
||||||
|
loginTheme?: string;
|
||||||
|
accountTheme?: string;
|
||||||
|
adminTheme?: string;
|
||||||
|
emailTheme?: string;
|
||||||
|
eventsListeners: string[];
|
||||||
|
users: {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
credentials: {
|
||||||
|
type: string /* "password" or something else */;
|
||||||
|
}[];
|
||||||
|
clientRoles?: Record<string, string[]>;
|
||||||
|
}[];
|
||||||
|
roles: {
|
||||||
|
client: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
containerId: string; // client id
|
||||||
|
}[]
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
clients: {
|
||||||
|
id: string;
|
||||||
|
clientId: string; // example: realm-management
|
||||||
|
baseUrl?: string;
|
||||||
|
redirectUris?: string[];
|
||||||
|
webOrigins?: string[];
|
||||||
|
attributes?: {
|
||||||
|
"post.logout.redirect.uris"?: string;
|
||||||
|
};
|
||||||
|
protocol?: string;
|
||||||
|
protocolMappers?: unknown[];
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const zParsedRealmJson = (() => {
|
||||||
|
type TargetType = ParsedRealmJson;
|
||||||
|
|
||||||
|
const zTargetType = z.object({
|
||||||
|
realm: z.string(),
|
||||||
|
loginTheme: z.string().optional(),
|
||||||
|
accountTheme: z.string().optional(),
|
||||||
|
adminTheme: z.string().optional(),
|
||||||
|
emailTheme: z.string().optional(),
|
||||||
|
eventsListeners: z.array(z.string()),
|
||||||
|
users: z.array(
|
||||||
|
z.object({
|
||||||
|
id: z.string(),
|
||||||
|
email: z.string(),
|
||||||
|
username: z.string(),
|
||||||
|
credentials: z.array(
|
||||||
|
z.object({
|
||||||
|
type: z.string()
|
||||||
|
})
|
||||||
|
),
|
||||||
|
clientRoles: z.record(z.array(z.string())).optional()
|
||||||
|
})
|
||||||
|
),
|
||||||
|
roles: z.object({
|
||||||
|
client: z.record(
|
||||||
|
z.array(
|
||||||
|
z.object({
|
||||||
|
name: z.string(),
|
||||||
|
containerId: z.string()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
clients: z.array(
|
||||||
|
z.object({
|
||||||
|
id: z.string(),
|
||||||
|
clientId: z.string(),
|
||||||
|
baseUrl: z.string().optional(),
|
||||||
|
redirectUris: z.array(z.string()).optional(),
|
||||||
|
webOrigins: z.array(z.string()).optional(),
|
||||||
|
attributes: z
|
||||||
|
.object({
|
||||||
|
"post.logout.redirect.uris": z.string().optional()
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
protocol: z.string().optional(),
|
||||||
|
protocolMappers: z.array(z.unknown()).optional()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
type InferredType = z.infer<typeof zTargetType>;
|
||||||
|
|
||||||
|
assert<Equals<TargetType, InferredType>>;
|
||||||
|
|
||||||
|
return id<z.ZodType<TargetType>>(zTargetType);
|
||||||
|
})();
|
||||||
|
|
||||||
|
export function readRealmJsonFile(params: {
|
||||||
|
realmJsonFilePath: string;
|
||||||
|
}): ParsedRealmJson {
|
||||||
|
const { realmJsonFilePath } = params;
|
||||||
|
|
||||||
|
const parsedRealmJson = JSON.parse(
|
||||||
|
fs.readFileSync(realmJsonFilePath).toString("utf8")
|
||||||
|
) as unknown;
|
||||||
|
|
||||||
|
zParsedRealmJson.parse(parsedRealmJson);
|
||||||
|
|
||||||
|
assert(is<ParsedRealmJson>(parsedRealmJson));
|
||||||
|
|
||||||
|
return parsedRealmJson;
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||||
|
import { getThisCodebaseRootDirPath } from "../../../tools/getThisCodebaseRootDirPath";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { exclude } from "tsafe/exclude";
|
||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import { type ParsedRealmJson, readRealmJsonFile } from "../ParsedRealmJson";
|
||||||
|
|
||||||
|
export function getDefaultRealmJsonFilePath(params: {
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
}) {
|
||||||
|
const { keycloakMajorVersionNumber } = params;
|
||||||
|
|
||||||
|
return pathJoin(
|
||||||
|
getThisCodebaseRootDirPath(),
|
||||||
|
"src",
|
||||||
|
"bin",
|
||||||
|
"start-keycloak",
|
||||||
|
"realmConfig",
|
||||||
|
"defaultConfig",
|
||||||
|
`realm-kc-${keycloakMajorVersionNumber}.json`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const { getSupportedKeycloakMajorVersions } = (() => {
|
||||||
|
let cache: number[] | undefined = undefined;
|
||||||
|
|
||||||
|
function getSupportedKeycloakMajorVersions(): number[] {
|
||||||
|
if (cache !== undefined) {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = fs
|
||||||
|
.readdirSync(
|
||||||
|
pathDirname(
|
||||||
|
getDefaultRealmJsonFilePath({ keycloakMajorVersionNumber: 0 })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map(fileBasename => {
|
||||||
|
const match = fileBasename.match(/^realm-kc-(\d+)\.json$/);
|
||||||
|
|
||||||
|
if (match === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const n = parseInt(match[1]);
|
||||||
|
|
||||||
|
assert(!isNaN(n));
|
||||||
|
|
||||||
|
return n;
|
||||||
|
})
|
||||||
|
.filter(exclude(undefined))
|
||||||
|
.sort((a, b) => b - a);
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getSupportedKeycloakMajorVersions };
|
||||||
|
})();
|
||||||
|
|
||||||
|
export function getDefaultConfig(params: {
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
}): ParsedRealmJson {
|
||||||
|
const { keycloakMajorVersionNumber } = params;
|
||||||
|
|
||||||
|
assert(
|
||||||
|
getSupportedKeycloakMajorVersions().includes(keycloakMajorVersionNumber),
|
||||||
|
`We do not have a default config for Keycloak ${keycloakMajorVersionNumber}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return readRealmJsonFile({
|
||||||
|
realmJsonFilePath: getDefaultRealmJsonFilePath({
|
||||||
|
keycloakMajorVersionNumber
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from "./defaultConfig";
|
@ -73,7 +73,7 @@
|
|||||||
"composites": {
|
"composites": {
|
||||||
"realm": ["offline_access", "uma_authorization"],
|
"realm": ["offline_access", "uma_authorization"],
|
||||||
"client": {
|
"client": {
|
||||||
"account": ["delete-account", "view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account", "delete-account"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clientRole": false,
|
"clientRole": false,
|
||||||
@ -398,6 +398,26 @@
|
|||||||
"otpPolicyLookAheadWindow": 1,
|
"otpPolicyLookAheadWindow": 1,
|
||||||
"otpPolicyPeriod": 30,
|
"otpPolicyPeriod": 30,
|
||||||
"otpSupportedApplications": ["FreeOTP", "Google Authenticator"],
|
"otpSupportedApplications": ["FreeOTP", "Google Authenticator"],
|
||||||
|
"webAuthnPolicyRpEntityName": "keycloak",
|
||||||
|
"webAuthnPolicySignatureAlgorithms": ["ES256"],
|
||||||
|
"webAuthnPolicyRpId": "",
|
||||||
|
"webAuthnPolicyAttestationConveyancePreference": "not specified",
|
||||||
|
"webAuthnPolicyAuthenticatorAttachment": "not specified",
|
||||||
|
"webAuthnPolicyRequireResidentKey": "not specified",
|
||||||
|
"webAuthnPolicyUserVerificationRequirement": "not specified",
|
||||||
|
"webAuthnPolicyCreateTimeout": 0,
|
||||||
|
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
|
||||||
|
"webAuthnPolicyAcceptableAaguids": [],
|
||||||
|
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
|
||||||
|
"webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
|
||||||
|
"webAuthnPolicyPasswordlessRpId": "",
|
||||||
|
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
|
||||||
|
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
|
||||||
|
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
|
||||||
|
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
|
||||||
|
"webAuthnPolicyPasswordlessCreateTimeout": 0,
|
||||||
|
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
|
||||||
|
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
|
||||||
"users": [
|
"users": [
|
||||||
{
|
{
|
||||||
"id": "00a62e75-bcc1-419a-a292-63ee5d161ed3",
|
"id": "00a62e75-bcc1-419a-a292-63ee5d161ed3",
|
||||||
@ -422,30 +442,43 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"create-client",
|
||||||
|
"view-identity-providers",
|
||||||
|
"manage-realm",
|
||||||
|
"query-groups",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"realm-admin",
|
||||||
|
"view-authorization",
|
||||||
|
"view-events",
|
||||||
|
"view-clients",
|
||||||
|
"view-realm",
|
||||||
|
"manage-events",
|
||||||
|
"query-realms",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"manage-users",
|
||||||
|
"view-users",
|
||||||
|
"impersonation",
|
||||||
|
"manage-authorization"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-applications",
|
||||||
|
"manage-consent",
|
||||||
|
"delete-account",
|
||||||
|
"manage-account",
|
||||||
|
"view-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"webAuthnPolicyRpEntityName": "keycloak",
|
|
||||||
"webAuthnPolicySignatureAlgorithms": ["ES256"],
|
|
||||||
"webAuthnPolicyRpId": "",
|
|
||||||
"webAuthnPolicyAttestationConveyancePreference": "not specified",
|
|
||||||
"webAuthnPolicyAuthenticatorAttachment": "not specified",
|
|
||||||
"webAuthnPolicyRequireResidentKey": "not specified",
|
|
||||||
"webAuthnPolicyUserVerificationRequirement": "not specified",
|
|
||||||
"webAuthnPolicyCreateTimeout": 0,
|
|
||||||
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
|
|
||||||
"webAuthnPolicyAcceptableAaguids": [],
|
|
||||||
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
|
|
||||||
"webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
|
|
||||||
"webAuthnPolicyPasswordlessRpId": "",
|
|
||||||
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
|
|
||||||
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
|
|
||||||
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
|
|
||||||
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
|
|
||||||
"webAuthnPolicyPasswordlessCreateTimeout": 0,
|
|
||||||
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
|
|
||||||
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
|
|
||||||
"scopeMappings": [
|
"scopeMappings": [
|
||||||
{
|
{
|
||||||
"clientScope": "offline_access",
|
"clientScope": "offline_access",
|
||||||
@ -505,8 +538,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -518,6 +555,7 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"post.logout.redirect.uris": "+",
|
||||||
"pkce.code.challenge.method": "S256"
|
"pkce.code.challenge.method": "S256"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
@ -636,7 +674,7 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
"post.logout.redirect.uris": "+",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"backchannel.logout.revoke.offline.tokens": "false"
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
@ -694,8 +732,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -707,6 +749,7 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"post.logout.redirect.uris": "+",
|
||||||
"pkce.code.challenge.method": "S256"
|
"pkce.code.challenge.method": "S256"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
@ -757,7 +800,8 @@
|
|||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
"config": {
|
"config": {
|
||||||
"id.token.claim": "true",
|
"id.token.claim": "true",
|
||||||
"access.token.claim": "true"
|
"access.token.claim": "true",
|
||||||
|
"userinfo.token.claim": "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1205,6 +1249,7 @@
|
|||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
"config": {
|
"config": {
|
||||||
"multivalued": "true",
|
"multivalued": "true",
|
||||||
|
"userinfo.token.claim": "true",
|
||||||
"user.attribute": "foo",
|
"user.attribute": "foo",
|
||||||
"id.token.claim": "true",
|
"id.token.claim": "true",
|
||||||
"access.token.claim": "true",
|
"access.token.claim": "true",
|
||||||
@ -1271,11 +1316,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1291,14 +1336,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
|
"saml-user-attribute-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"saml-role-list-mapper",
|
"saml-role-list-mapper"
|
||||||
"oidc-usermodel-property-mapper"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1347,14 +1392,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-usermodel-property-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-role-list-mapper"
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
|
"saml-user-attribute-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1394,6 +1439,12 @@
|
|||||||
"providerId": "rsa-generated",
|
"providerId": "rsa-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
|
"privateKey": [
|
||||||
|
"MIIEpAIBAAKCAQEA+VQAcuaRivrzLVI8H/tt8PKbtRznTQKmmxOdLRR37leY/ph7sFnEmZt6K02Rvut7R0dxUFtTdiEHUKxhyM8CADMznGUjDYj/EXQzLfZ3LEwbwmR39zp+fZL/H24UDO03zt23Ov9C8Aly0ufXZ1Ic1c33KW6UtUEK/3M52pU8Y0daWdjx7nBj1eRlzWfVG+BYotTTWEnFJuEoZPFQMiXqeA5ob1zZdXjL5JDuGEiBsYjtiiaKbKL5545+FmEBnoCmWXqGu0qWxI2TzvV2dohxfl5KjNzRoKt40ydraiVk5rtBpoNDpeEApuphbokH5dJVwJ5cvWu1CSTnYPW2jXeG4wIDAQABAoIBAQDHV6AcPbhz8/xlafBkabQXBwHzJi7QZaQrLN1n44uX5jWOqP+LmdoULjjZUmWKzd98t+QjKUFrmzCsEYcE9G1XF5jWHA6Qjc3ReKRKxVm28wrmu0knQ39KizKrQGmLhEYwgRg0dU5heExzz6VrGD2xu8E3QRBocp6GauwAlXz4qcnTPHOl8OBPeDHAc0RUdaL5+jRLgKQzf9nnnKB19imBKP++zwrwFrkOZti2ZPs1I7j/ym27mHUbi8TDI2VepDX4QwjjC5a+v3vTsVAGE+1tUAZtqpxpIP9hiUkLH3ajyvp3typhnmZHklqsSZdwtRcK94WiMzL3TkiY70y8abMhAoGBAP8I4EQRXxcKfBn23eaRw8Cd4PFrOouz4zFbYLrBODsvXfku/jnQOMFD0If4IzT6y0FGgBd+t/yqnFJi98oZOKm3P8w+NZBXTbFLH8rgmsElXyS0+9LVMjVa7+UlqZB1eRZbUeLREp03Fsz1y2rflnoWgUnpDIlyhmJqGhCsJdebAoGBAPpFmJ9P42mUTeDWpCyCxgg0zpp6rlpAP8StqZkcvr7kYjhbWrJfJuxrTXtzTTA1zZ59L9EvEAxuug/gl9BkuZ11Uzg8ZLOr4gSuAJZlAORaxJlcoylmNMYIL1fP/K0dxhdO0eHZOpPVpBmGctgev2HBtWp9ZwzQ3DddKimZfNZZAoGAfNOOWSKbhT6HgXnYIHtl8YgUynUuYaR5ZfYQwTfDWwyTFVzP5+IndUjI71Qff1XlWBy2o0lNqmijPJveJlfz6PWdT01/kBd7GnTnqbgHZtPw3pmKzCW3fm/1DRZDCUbGLpAh4z9rufF1wnnnx3aKQ1VykId1sGySo+bEvTZVC1MCgYAlv6uWk/ksKpdYi2d14z+1aymieVClAj3cD4meM4y9xDrgXz8d2mZHkKO+NBT3aZYbCqzUs3GLPoRH8stTPm4UxuaHe+yAgTN1Gz2xcYih6OLwct2VV/oryH5Dk3Z8Mhp314amtxozxCydQP8/g9vABfS0HDgX4cTlgOLkJWeD+QKBgQDuRtsstQ4Q3yK44himPi1JQMMvbYAqyGgRxWH8G1Kr41DV2sQ4wt9CbYxeh6RwMsE+YYNMkTAw1kksUTugWdcDnYpcSVG7xHLJk8WMti0WTqI/7KlkoRehXXv18WJNEXaCr5mJTtJL9wuQcd8nhkEDrrCZubZiJzX9IDnEqZc4Mg=="
|
||||||
|
],
|
||||||
|
"certificate": [
|
||||||
|
"MIICnTCCAYUCBgGTy58etTANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE4Mzg0M1oXDTM0MTIxNTE4NDAyM1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPlUAHLmkYr68y1SPB/7bfDym7Uc500CppsTnS0Ud+5XmP6Ye7BZxJmbeitNkb7re0dHcVBbU3YhB1CsYcjPAgAzM5xlIw2I/xF0My32dyxMG8Jkd/c6fn2S/x9uFAztN87dtzr/QvAJctLn12dSHNXN9ylulLVBCv9zOdqVPGNHWlnY8e5wY9XkZc1n1RvgWKLU01hJxSbhKGTxUDIl6ngOaG9c2XV4y+SQ7hhIgbGI7Yomimyi+eeOfhZhAZ6Apll6hrtKlsSNk871dnaIcX5eSozc0aCreNMna2olZOa7QaaDQ6XhAKbqYW6JB+XSVcCeXL1rtQkk52D1to13huMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAH/nsEi88hFiNPCWYvTB3lERZpeUCbpDzAXQT/4TONmOw8zi7Cd2OlX8BGBFqjh/fESHv+adlzsY1mUdMvpVaYgHr3gYi8sBSrq5TMUfSYaWp4WCD7utiXXGprG08GCdbye1lpyyNnniWp12Bgjao+rtGamL/M1d6+WZTC+XL+H30u4VHURAiFBsAEoX6tlGV8ynhYOr/b8B43jy0/R0JfrzLjwSKEcA6RfKM7ozbZ0QZuQDALULymPIesrV4mvZ2Qwg4YgpAKaki9Sse45yiIhsIY0p5RnuNZRZnCbukyeBzIyDJobEBGhpui/KT2dqXBlRgRuOhCUf7OGCcPVHKNQ=="
|
||||||
|
],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1403,6 +1454,12 @@
|
|||||||
"providerId": "rsa-enc-generated",
|
"providerId": "rsa-enc-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
|
"privateKey": [
|
||||||
|
"MIIEogIBAAKCAQEAn82AU+InXwYlE8u9lMwhQghZB7oQ71Hg3PdFqS9ICGzw1u1JcENooCsZse55V6nqptdYF1oZA8QrxnhHzCVCGIqFHtXSoPGHVtozO3Fe1cVIVFm1D9TNS3JHe1C8SBQQT4hGItO5cjDyfGdK3x09RkoAcelrzH5uQ78zd0FKHkzbsTMsP2V8V94c35+ViIUjyGhH2T2BpIyGRLignL+6d0wHbw463L1Ewj/J9z8BtNLCH9PaVLWiGQARjlWyL9vtWBig9XXL0Z9tZUuoLihjh4StkXt2lQ++DKxUklsAjyenRAG5d72T2rY8MO5a1Z2ZSt8+s86D5esrAEIFZc9mqwIDAQABAoIBAAmmCcqGzCPDpjd0xMSYMqXfBSkfReh9RBtzXqRhc3L2yO/hMd7yYv3QvGNu56qwWreqJup6CSqeDJqWJpef5EbBDlqXRHltO+O1lwROyxATMlPNes4y5hZZFxHOBSBA/d8fdkSiDf9kDzANuIqSJGH7E93M3zJgq92xTLU1nvkHR/VYJQv+j+Pjye7MWvjIePfhwFeBqEWlWPTlw/080Mpfp8Hhbl6JeKjx2inkSphp43v4wR1Wmp+E2JIHF4P4sVXPPuPf3JDwg5uGOrROw1ziloD3jTI+LnQ+kRm6R2EbqRqqVsehXT7mZy2puQNqVc4vVqWQdxIErMBazYEpZOECgYEA+8PEcDiIPr2PTYZk+/jErRVYwsxyLgDJexPak7onLxLBJRNRnp1Uk6b1LXM6af5qp+Y510kyAe1k+9xkQLx1gW8rMka9rvVsM+1A2ACvF99V23sRw29CVxeFV/zNn83MinYPX5biUl6MkOX2PvWUhdwRGhKByjiYcAeBOsXkz3ECgYEAon2yYXGzph8Vb8Fetv0wFFbjQOixuL02OjVp/nU1XVE8Aw9BJ7uzA6GQ7akPG0HsaUq7AEHP1uUOsJWQTNQ8WYD9LDuDOl/JFqkG+zrmdUdm0mAIYyH1/GBqgaTLvMq78qqosua8BBJojEyoXDz69UBHpu7cwtUgmzRNQSYqgdsCgYASvD3JEBvrd1XLsh2ftqKEMtt5G5e/nqVfuFmCts6lrSKcbLSdNh4OItWJ/VIygxFSz0osoDDNfeoO6Ba5zox8BlbTlfoVpAPaVWSG7n4ZK7CK9bybq5LnQkPVCWYP51O6VhDMz0CmWozhV4ucoc/cqkTHiOsJrm6Bn71ZL1LYsQKBgFNb8qgk4YnGhoPHiuSLbR/yFzGUbqAciXZBMrg0vwS5iPT03XMZytOBDk2uHi7YmgTGLrsKCCrxZaDXiaiwdKliD/+iJEdNHmc+nXNDGzltQOWKGKNqp7wqZllOBqs6wkLSpCrrTec03mejZ/ex3Pj2WgvcnGpjVg/pO/zBLKtjAoGACzGQNEF93fabHQJTsHmb/g+jO2iumjF6ZIWzdFh2KzQABONcoBvy1MJNASFQj3iVy/8kEo4SfmexvMWLBW9igi2z1pHeHY32EuImzuc4xnVDm6dkmDdsO43Ex6CFBx8lM40H4l27mXu+EZRzGClUY8TnmV/FBGmX+LPtOiiwT7s="
|
||||||
|
],
|
||||||
|
"certificate": [
|
||||||
|
"MIICnTCCAYUCBgGTy58fHjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE4Mzg0M1oXDTM0MTIxNTE4NDAyM1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ/NgFPiJ18GJRPLvZTMIUIIWQe6EO9R4Nz3RakvSAhs8NbtSXBDaKArGbHueVep6qbXWBdaGQPEK8Z4R8wlQhiKhR7V0qDxh1baMztxXtXFSFRZtQ/UzUtyR3tQvEgUEE+IRiLTuXIw8nxnSt8dPUZKAHHpa8x+bkO/M3dBSh5M27EzLD9lfFfeHN+flYiFI8hoR9k9gaSMhkS4oJy/undMB28OOty9RMI/yfc/AbTSwh/T2lS1ohkAEY5Vsi/b7VgYoPV1y9GfbWVLqC4oY4eErZF7dpUPvgysVJJbAI8np0QBuXe9k9q2PDDuWtWdmUrfPrPOg+XrKwBCBWXPZqsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATwmKBzLiZiUjyB9BWUR4BCXh46DxsiM0BCublewlUFY6FBTn7ea6q3G+X3QP2WM6xa0oAmQz9dq1KChbIoC2WPbceAbwd5XZZfziWsRCv6+xPswtpHPIrsenz8TR4K4P73aeCC+vTVs/y+2tGPEVbnSkcNnOP71hRQGlt0LvjKlEetJSRyYz5depSdJOjl4F3ehpxQtTK/48xUVAytu9ZotJj6AUA7jWFlP5GHgoB+mPk6QTHNWddnc7BQx2FMvg151vxu722ywLh5Dh7WzgFhJNwkX4xpwzhfo0Q1gSygGTdZaJCGj5jfF+KwdiKpN04UxJ8OrRgJqklQgrSVnsgQ=="
|
||||||
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["RSA-OAEP"]
|
"algorithm": ["RSA-OAEP"]
|
||||||
}
|
}
|
||||||
@ -1413,6 +1470,8 @@
|
|||||||
"providerId": "aes-generated",
|
"providerId": "aes-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
|
"kid": ["132fb843-59e9-4f36-ad55-5ce2d3a13fb3"],
|
||||||
|
"secret": ["ETyyqapnrkUsNXLQ-tBVKw"],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1422,6 +1481,10 @@
|
|||||||
"providerId": "hmac-generated",
|
"providerId": "hmac-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
|
"kid": ["5110d380-c930-49d9-b91b-87f338f6170b"],
|
||||||
|
"secret": [
|
||||||
|
"uCpQrJvP5OBuTxXfDb4JRL0bCKpXUgfGn5vb8UvL-Sfs_sZ9rtvBmd6vuFWARqyezjJQtpoNlMv7sXgxkN-yxQ"
|
||||||
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["HS256"]
|
"algorithm": ["HS256"]
|
||||||
}
|
}
|
||||||
@ -1454,7 +1517,7 @@
|
|||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"authenticationFlows": [
|
"authenticationFlows": [
|
||||||
{
|
{
|
||||||
"id": "f7f2b89b-43cb-491d-8e7c-f1814024a6da",
|
"id": "223ce532-2038-4f24-a606-2a5c73f7bd65",
|
||||||
"alias": "Account verification options",
|
"alias": "Account verification options",
|
||||||
"description": "Method with which to verity the existing account",
|
"description": "Method with which to verity the existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1480,7 +1543,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "17cdac6f-d2a3-4907-8d44-a42827610b63",
|
"id": "57e47732-79cc-4d60-bee7-4f0b8fd44540",
|
||||||
"alias": "Authentication Options",
|
"alias": "Authentication Options",
|
||||||
"description": "Authentication options.",
|
"description": "Authentication options.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1514,7 +1577,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "53a3e43f-9468-401f-8051-40f982d12f85",
|
"id": "c2735d89-60c0-45a4-9b3c-ae5df17df395",
|
||||||
"alias": "Browser - Conditional OTP",
|
"alias": "Browser - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1540,7 +1603,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "26286808-3b7b-43df-b32e-af55a37af2e9",
|
"id": "11a5a507-2b9a-443f-961b-dffd66f4318d",
|
||||||
"alias": "Direct Grant - Conditional OTP",
|
"alias": "Direct Grant - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1566,7 +1629,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "8a6a752a-9a9a-4d38-b1f8-edf0a9433490",
|
"id": "963bd753-6ea7-4d93-ab56-30f9ab59d597",
|
||||||
"alias": "First broker login - Conditional OTP",
|
"alias": "First broker login - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1592,7 +1655,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a6f6804c-4160-4a84-8a1f-c2747a2d3f27",
|
"id": "1db6a489-a3b4-44c4-b480-1d1e8c123d20",
|
||||||
"alias": "Handle Existing Account",
|
"alias": "Handle Existing Account",
|
||||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1618,7 +1681,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "740baa9e-8328-4035-9e1a-8fc1616d1f0f",
|
"id": "7a38f32d-4f34-450f-8f03-64802d7cb8f1",
|
||||||
"alias": "Reset - Conditional OTP",
|
"alias": "Reset - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1644,7 +1707,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e60187a8-3e16-4a0c-9daa-f3a4a1fcfdba",
|
"id": "0df88739-3739-4d70-8893-47c546f19003",
|
||||||
"alias": "User creation or linking",
|
"alias": "User creation or linking",
|
||||||
"description": "Flow for the existing/non-existing user alternatives",
|
"description": "Flow for the existing/non-existing user alternatives",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1671,7 +1734,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d959d0c2-4004-4633-b280-f80d6423f574",
|
"id": "35025424-e291-4c54-8a29-70aadba549ce",
|
||||||
"alias": "Verify Existing Account by Re-authentication",
|
"alias": "Verify Existing Account by Re-authentication",
|
||||||
"description": "Reauthentication of existing account",
|
"description": "Reauthentication of existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1697,7 +1760,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ba02689d-b9e8-4a4b-8fdd-0d1386b198fc",
|
"id": "1813b7f2-c3c2-4b92-8ffc-9ff2d12186c6",
|
||||||
"alias": "browser",
|
"alias": "browser",
|
||||||
"description": "browser based authentication",
|
"description": "browser based authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1739,7 +1802,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f09ac92a-e091-4e84-9cd1-cb905ca57b89",
|
"id": "954283ac-f1c2-40b6-a39f-bf23ff9f3ce8",
|
||||||
"alias": "clients",
|
"alias": "clients",
|
||||||
"description": "Base authentication for clients",
|
"description": "Base authentication for clients",
|
||||||
"providerId": "client-flow",
|
"providerId": "client-flow",
|
||||||
@ -1781,7 +1844,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "aaf72b22-cec4-4714-93d6-f54d5a986ab8",
|
"id": "52a789ce-2cad-4f0f-93b2-295b7fd519f0",
|
||||||
"alias": "direct grant",
|
"alias": "direct grant",
|
||||||
"description": "OpenID Connect Resource Owner Grant",
|
"description": "OpenID Connect Resource Owner Grant",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1815,7 +1878,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c4a54bb3-f009-4231-a82b-376c2515e07e",
|
"id": "5a6a71e1-9105-45b6-b5f0-52538461357b",
|
||||||
"alias": "docker auth",
|
"alias": "docker auth",
|
||||||
"description": "Used by Docker clients to authenticate against the IDP",
|
"description": "Used by Docker clients to authenticate against the IDP",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1833,7 +1896,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f55ded54-683a-4f5a-a101-9cfbd7b96781",
|
"id": "8392b6e7-bdbf-4d7f-97b6-885761c200db",
|
||||||
"alias": "first broker login",
|
"alias": "first broker login",
|
||||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1860,7 +1923,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "931d5a82-378f-4533-8c69-2239a4acd047",
|
"id": "52136d70-8d08-42ea-b04b-cf40ea2807aa",
|
||||||
"alias": "forms",
|
"alias": "forms",
|
||||||
"description": "Username, password, otp and other auth forms.",
|
"description": "Username, password, otp and other auth forms.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1886,7 +1949,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "22b05374-f480-4ca8-aca8-9db8b6dd1729",
|
"id": "26bbc7e6-ef01-4cdb-9dba-520e2f3f8993",
|
||||||
"alias": "http challenge",
|
"alias": "http challenge",
|
||||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1912,7 +1975,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c0371832-e4b7-485e-bf23-6babe4c6ac83",
|
"id": "f0887979-04eb-4033-8f19-0ffd8c8b7f6a",
|
||||||
"alias": "registration",
|
"alias": "registration",
|
||||||
"description": "registration flow",
|
"description": "registration flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1931,7 +1994,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "4d0445da-073e-465e-b25b-af522915c73f",
|
"id": "a3b7b94b-bfbf-4760-a8c9-7d9cd98d262e",
|
||||||
"alias": "registration form",
|
"alias": "registration form",
|
||||||
"description": "registration form",
|
"description": "registration form",
|
||||||
"providerId": "form-flow",
|
"providerId": "form-flow",
|
||||||
@ -1973,7 +2036,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "740d467f-4203-425b-8203-9bfd3eed25ae",
|
"id": "dc68a665-2e51-4a22-aaad-bd693ddc77cc",
|
||||||
"alias": "reset credentials",
|
"alias": "reset credentials",
|
||||||
"description": "Reset credentials for a user if they forgot their password or something",
|
"description": "Reset credentials for a user if they forgot their password or something",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2015,7 +2078,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cf1a9af9-dadd-4cb9-a26e-fbbba216f8e1",
|
"id": "ae6b73aa-1318-4ae8-a3d9-d01b5e7d957e",
|
||||||
"alias": "saml ecp",
|
"alias": "saml ecp",
|
||||||
"description": "SAML ECP Profile Authentication Flow",
|
"description": "SAML ECP Profile Authentication Flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2035,14 +2098,14 @@
|
|||||||
],
|
],
|
||||||
"authenticatorConfig": [
|
"authenticatorConfig": [
|
||||||
{
|
{
|
||||||
"id": "4e65eb4b-9f0a-4ab8-98b2-6daf50cd1bf8",
|
"id": "0c18de7f-0714-41f4-9a3f-ed4edd53ae9c",
|
||||||
"alias": "create unique user config",
|
"alias": "create unique user config",
|
||||||
"config": {
|
"config": {
|
||||||
"require.password.update.after.registration": "false"
|
"require.password.update.after.registration": "false"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5e8dc1c5-1489-4d39-bb75-9c499583b91b",
|
"id": "65b3c8bb-34a4-4d19-b578-245dc8ff53ea",
|
||||||
"alias": "review profile config",
|
"alias": "review profile config",
|
||||||
"config": {
|
"config": {
|
||||||
"update.profile.on.first.login": "missing"
|
"update.profile.on.first.login": "missing"
|
||||||
@ -2132,8 +2195,8 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"cibaBackchannelTokenDeliveryMode": "poll",
|
"cibaBackchannelTokenDeliveryMode": "poll",
|
||||||
"cibaAuthRequestedUserHint": "login_hint",
|
"cibaAuthRequestedUserHint": "login_hint",
|
||||||
"oauth2DevicePollingInterval": "5",
|
|
||||||
"clientOfflineSessionMaxLifespan": "0",
|
"clientOfflineSessionMaxLifespan": "0",
|
||||||
|
"oauth2DevicePollingInterval": "5",
|
||||||
"clientSessionIdleTimeout": "0",
|
"clientSessionIdleTimeout": "0",
|
||||||
"userProfileEnabled": "true",
|
"userProfileEnabled": "true",
|
||||||
"clientOfflineSessionIdleTimeout": "0",
|
"clientOfflineSessionIdleTimeout": "0",
|
@ -73,7 +73,7 @@
|
|||||||
"composites": {
|
"composites": {
|
||||||
"realm": ["offline_access", "uma_authorization"],
|
"realm": ["offline_access", "uma_authorization"],
|
||||||
"client": {
|
"client": {
|
||||||
"account": ["delete-account", "view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account", "delete-account"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clientRole": false,
|
"clientRole": false,
|
||||||
@ -435,13 +435,46 @@
|
|||||||
"type": "password",
|
"type": "password",
|
||||||
"userLabel": "My password",
|
"userLabel": "My password",
|
||||||
"createdDate": 1716214710762,
|
"createdDate": 1716214710762,
|
||||||
"secretData": "{\"value\":\"OaI4sKqQn+NZtS6N/bcqoZ8Q+ucpBby1n4XmzVmioKw=\",\"salt\":\"temixVCSbpA7Genml2KTAw==\",\"additionalParameters\":{}}",
|
"secretData": "{\"value\":\"QzJjOdXU0L9Pdxdx1V5xUs7BY9beGlmN8NpR2qiWxbkjrQ434Q1GwSiJKekZQ/zrLDtNZ7sAbVu+SS+XIe9Zaw==\",\"salt\":\"x8cABpa0Hk/nJ2BPKdFXTg==\",\"additionalParameters\":{}}",
|
||||||
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
|
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"create-client",
|
||||||
|
"view-identity-providers",
|
||||||
|
"manage-realm",
|
||||||
|
"query-groups",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"realm-admin",
|
||||||
|
"view-authorization",
|
||||||
|
"view-events",
|
||||||
|
"view-clients",
|
||||||
|
"view-realm",
|
||||||
|
"manage-events",
|
||||||
|
"query-realms",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"manage-users",
|
||||||
|
"view-users",
|
||||||
|
"impersonation",
|
||||||
|
"manage-authorization"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-applications",
|
||||||
|
"manage-consent",
|
||||||
|
"delete-account",
|
||||||
|
"manage-account",
|
||||||
|
"view-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -507,8 +540,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -643,7 +680,6 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
@ -704,8 +740,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1284,11 +1324,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1304,14 +1344,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-usermodel-property-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
"saml-role-list-mapper"
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
|
"oidc-usermodel-attribute-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1360,14 +1400,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"saml-user-property-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"oidc-address-mapper",
|
"oidc-usermodel-property-mapper",
|
||||||
"saml-role-list-mapper",
|
"saml-role-list-mapper",
|
||||||
"oidc-usermodel-property-mapper"
|
"oidc-full-name-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
|
"saml-user-attribute-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1485,7 +1525,7 @@
|
|||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"authenticationFlows": [
|
"authenticationFlows": [
|
||||||
{
|
{
|
||||||
"id": "e134634e-f219-4df4-867c-8110688d8e56",
|
"id": "1f4d4e13-1591-4751-8985-17886a8c98a9",
|
||||||
"alias": "Account verification options",
|
"alias": "Account verification options",
|
||||||
"description": "Method with which to verity the existing account",
|
"description": "Method with which to verity the existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1511,7 +1551,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a611a8eb-9626-4aa4-8b54-ee565ea6e5dc",
|
"id": "126f07c3-1bcb-4a02-bf16-bb44674bf55d",
|
||||||
"alias": "Authentication Options",
|
"alias": "Authentication Options",
|
||||||
"description": "Authentication options.",
|
"description": "Authentication options.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1545,7 +1585,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "d87cbb31-5c69-45c8-888d-f9649ebbbf97",
|
"id": "eb3a08c8-5f99-49b6-b02b-16b62571f273",
|
||||||
"alias": "Browser - Conditional OTP",
|
"alias": "Browser - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1571,7 +1611,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "752ba282-a369-4592-92e8-b4287192dbbf",
|
"id": "3dc19838-5025-4bbb-b569-b574bd5a8d90",
|
||||||
"alias": "Direct Grant - Conditional OTP",
|
"alias": "Direct Grant - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1597,7 +1637,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2349282e-40ff-431a-984d-53911511e3d3",
|
"id": "70d6fd40-d740-4dae-b0e6-350f8e9d4a1c",
|
||||||
"alias": "First broker login - Conditional OTP",
|
"alias": "First broker login - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1623,7 +1663,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "4ff5463d-26d9-4219-ba85-41464401098f",
|
"id": "6e24dcb3-5818-483c-8e44-883858171901",
|
||||||
"alias": "Handle Existing Account",
|
"alias": "Handle Existing Account",
|
||||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1649,7 +1689,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "87bb6c6d-cca8-4832-b5ab-67ecb9454a42",
|
"id": "ac6254cd-403b-457b-b308-22a2a0e4f99d",
|
||||||
"alias": "Reset - Conditional OTP",
|
"alias": "Reset - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1675,7 +1715,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "1fc3d028-0e0a-43a4-aaf9-ba7f7d60b409",
|
"id": "485e74e6-9b3e-4b2c-a9b9-927802dc4f06",
|
||||||
"alias": "User creation or linking",
|
"alias": "User creation or linking",
|
||||||
"description": "Flow for the existing/non-existing user alternatives",
|
"description": "Flow for the existing/non-existing user alternatives",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1702,7 +1742,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "036aae59-641f-4799-9124-c7e5034af6c1",
|
"id": "ff9bb879-1d6a-4d1c-9836-1e4fab6f8997",
|
||||||
"alias": "Verify Existing Account by Re-authentication",
|
"alias": "Verify Existing Account by Re-authentication",
|
||||||
"description": "Reauthentication of existing account",
|
"description": "Reauthentication of existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1728,7 +1768,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2e8b9f28-93b8-4368-84b0-1a8326daafe0",
|
"id": "af8b2470-d581-401c-9984-762b966ebcc2",
|
||||||
"alias": "browser",
|
"alias": "browser",
|
||||||
"description": "browser based authentication",
|
"description": "browser based authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1770,7 +1810,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0b826105-8493-45ce-87b3-7d917d190b39",
|
"id": "414dbda4-eb3f-4baa-b23a-d3423af1eae6",
|
||||||
"alias": "clients",
|
"alias": "clients",
|
||||||
"description": "Base authentication for clients",
|
"description": "Base authentication for clients",
|
||||||
"providerId": "client-flow",
|
"providerId": "client-flow",
|
||||||
@ -1812,7 +1852,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "bf6d9edd-48d8-4392-bbc8-4b17a6866074",
|
"id": "1cae0c4b-8dfb-4f5d-a781-e74d0a13c940",
|
||||||
"alias": "direct grant",
|
"alias": "direct grant",
|
||||||
"description": "OpenID Connect Resource Owner Grant",
|
"description": "OpenID Connect Resource Owner Grant",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1846,7 +1886,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "97e31722-dd11-42be-aa99-88788fa2dde6",
|
"id": "e798b655-7d85-4b6b-aee7-1448a3e1e0ea",
|
||||||
"alias": "docker auth",
|
"alias": "docker auth",
|
||||||
"description": "Used by Docker clients to authenticate against the IDP",
|
"description": "Used by Docker clients to authenticate against the IDP",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1864,7 +1904,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "3f45cf34-231f-4ea1-8e58-d636c451a76b",
|
"id": "eb94b723-1041-426a-87bf-f7b4bd2f485d",
|
||||||
"alias": "first broker login",
|
"alias": "first broker login",
|
||||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1891,7 +1931,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "9bef2f7c-f989-4871-aaa7-18e2cfa73f22",
|
"id": "452d1d5f-7632-44d7-bc89-77ff2b209b3e",
|
||||||
"alias": "forms",
|
"alias": "forms",
|
||||||
"description": "Username, password, otp and other auth forms.",
|
"description": "Username, password, otp and other auth forms.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1917,7 +1957,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0bfaa325-acde-4443-8bd8-1dc2ae759c5f",
|
"id": "7c1b9e8f-6b57-49d1-a9a7-494862f93c0f",
|
||||||
"alias": "http challenge",
|
"alias": "http challenge",
|
||||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1943,7 +1983,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "37ddbe8c-abf3-4654-bd6d-ffabbeefbb98",
|
"id": "2b38f34a-1739-499e-bb24-1dff96f32009",
|
||||||
"alias": "registration",
|
"alias": "registration",
|
||||||
"description": "registration flow",
|
"description": "registration flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1962,7 +2002,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5d7b4bc9-e93b-40da-aeb6-ba0c38392f1a",
|
"id": "d26ae72b-a933-44dc-9927-1c82757004b2",
|
||||||
"alias": "registration form",
|
"alias": "registration form",
|
||||||
"description": "registration form",
|
"description": "registration form",
|
||||||
"providerId": "form-flow",
|
"providerId": "form-flow",
|
||||||
@ -2004,7 +2044,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ee7a56e4-c827-4f24-8b8b-8476050b0b64",
|
"id": "222ee8d6-1892-4768-9ada-720274b6bf9a",
|
||||||
"alias": "reset credentials",
|
"alias": "reset credentials",
|
||||||
"description": "Reset credentials for a user if they forgot their password or something",
|
"description": "Reset credentials for a user if they forgot their password or something",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2046,7 +2086,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "360f0031-4c3b-4272-84ca-2172d430b4bc",
|
"id": "e8b4d92c-27c1-4a9b-9b16-7ceb810fa230",
|
||||||
"alias": "saml ecp",
|
"alias": "saml ecp",
|
||||||
"description": "SAML ECP Profile Authentication Flow",
|
"description": "SAML ECP Profile Authentication Flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2066,14 +2106,14 @@
|
|||||||
],
|
],
|
||||||
"authenticatorConfig": [
|
"authenticatorConfig": [
|
||||||
{
|
{
|
||||||
"id": "53630acd-a33a-40e3-8786-cf85464c6f9e",
|
"id": "e5847a0b-855d-4d93-85fd-94714be3ed92",
|
||||||
"alias": "create unique user config",
|
"alias": "create unique user config",
|
||||||
"config": {
|
"config": {
|
||||||
"require.password.update.after.registration": "false"
|
"require.password.update.after.registration": "false"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "c0d2b6a0-caad-4e90-b040-17cacdaf70bb",
|
"id": "a2a18aa4-bd4c-4c2a-9286-e9d6c64f4812",
|
||||||
"alias": "review profile config",
|
"alias": "review profile config",
|
||||||
"config": {
|
"config": {
|
||||||
"update.profile.on.first.login": "missing"
|
"update.profile.on.first.login": "missing"
|
@ -73,7 +73,7 @@
|
|||||||
"composites": {
|
"composites": {
|
||||||
"realm": ["offline_access", "uma_authorization"],
|
"realm": ["offline_access", "uma_authorization"],
|
||||||
"client": {
|
"client": {
|
||||||
"account": ["delete-account", "view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account", "delete-account"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clientRole": false,
|
"clientRole": false,
|
||||||
@ -407,7 +407,7 @@
|
|||||||
"otpPolicyLookAheadWindow": 1,
|
"otpPolicyLookAheadWindow": 1,
|
||||||
"otpPolicyPeriod": 30,
|
"otpPolicyPeriod": 30,
|
||||||
"otpPolicyCodeReusable": false,
|
"otpPolicyCodeReusable": false,
|
||||||
"otpSupportedApplications": ["totpAppGoogleName", "totpAppFreeOTPName"],
|
"otpSupportedApplications": ["totpAppFreeOTPName", "totpAppGoogleName"],
|
||||||
"webAuthnPolicyRpEntityName": "keycloak",
|
"webAuthnPolicyRpEntityName": "keycloak",
|
||||||
"webAuthnPolicySignatureAlgorithms": ["ES256"],
|
"webAuthnPolicySignatureAlgorithms": ["ES256"],
|
||||||
"webAuthnPolicyRpId": "",
|
"webAuthnPolicyRpId": "",
|
||||||
@ -452,6 +452,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"create-client",
|
||||||
|
"view-identity-providers",
|
||||||
|
"manage-realm",
|
||||||
|
"query-groups",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"realm-admin",
|
||||||
|
"view-authorization",
|
||||||
|
"view-events",
|
||||||
|
"view-clients",
|
||||||
|
"view-realm",
|
||||||
|
"manage-events",
|
||||||
|
"query-realms",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"manage-users",
|
||||||
|
"view-users",
|
||||||
|
"impersonation",
|
||||||
|
"manage-authorization"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-applications",
|
||||||
|
"manage-consent",
|
||||||
|
"delete-account",
|
||||||
|
"manage-account",
|
||||||
|
"view-groups",
|
||||||
|
"view-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -517,8 +551,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -653,7 +691,6 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
@ -714,8 +751,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1294,11 +1335,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1314,14 +1355,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"saml-user-property-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-usermodel-attribute-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"saml-role-list-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
"oidc-usermodel-property-mapper"
|
"saml-role-list-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
|
"oidc-usermodel-attribute-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
|
"saml-user-attribute-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1370,14 +1411,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"saml-role-list-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"saml-role-list-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"oidc-usermodel-property-mapper"
|
"oidc-usermodel-attribute-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1495,7 +1536,7 @@
|
|||||||
"defaultLocale": "en",
|
"defaultLocale": "en",
|
||||||
"authenticationFlows": [
|
"authenticationFlows": [
|
||||||
{
|
{
|
||||||
"id": "19317acb-fe8e-4c79-82bc-90e159273075",
|
"id": "c40791b4-4d59-4df2-bebd-2b71e793704f",
|
||||||
"alias": "Account verification options",
|
"alias": "Account verification options",
|
||||||
"description": "Method with which to verity the existing account",
|
"description": "Method with which to verity the existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1521,7 +1562,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "122857d2-33da-4086-8acb-cb0e303aaf1b",
|
"id": "8813b6d1-8b88-4672-b29b-8420ce3f3975",
|
||||||
"alias": "Authentication Options",
|
"alias": "Authentication Options",
|
||||||
"description": "Authentication options.",
|
"description": "Authentication options.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1555,7 +1596,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "abf5dd35-4791-4268-a10c-5f4b6a06b84a",
|
"id": "a9937c40-a1ee-4c57-adf7-ede0a9983953",
|
||||||
"alias": "Browser - Conditional OTP",
|
"alias": "Browser - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1581,7 +1622,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a18daeec-a33c-4a43-b014-10c84ec69b81",
|
"id": "2d494b5a-eb73-40d0-94d3-a8d8024a7db4",
|
||||||
"alias": "Direct Grant - Conditional OTP",
|
"alias": "Direct Grant - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1607,7 +1648,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e9f032a7-32f7-457c-becf-011a1a35cc6a",
|
"id": "2e977f5a-8110-412b-b704-3e15164dbb1b",
|
||||||
"alias": "First broker login - Conditional OTP",
|
"alias": "First broker login - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP is required for the authentication",
|
"description": "Flow to determine if the OTP is required for the authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1633,7 +1674,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "9db65b7c-98ca-4003-beea-611038831ffe",
|
"id": "6f171b4b-8723-4e6d-bb1e-6b4293a7bb3f",
|
||||||
"alias": "Handle Existing Account",
|
"alias": "Handle Existing Account",
|
||||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1659,7 +1700,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "7bd0854c-d7ae-43d7-a1ae-7b759a34cb1d",
|
"id": "2dbb7f27-757d-4178-8217-4a24fdb0163c",
|
||||||
"alias": "Reset - Conditional OTP",
|
"alias": "Reset - Conditional OTP",
|
||||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1685,7 +1726,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2de1a450-fe98-443a-9c6c-d24d8a7ebcb3",
|
"id": "7295aaf7-acf4-4b78-8186-d2415ea4ede0",
|
||||||
"alias": "User creation or linking",
|
"alias": "User creation or linking",
|
||||||
"description": "Flow for the existing/non-existing user alternatives",
|
"description": "Flow for the existing/non-existing user alternatives",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1712,7 +1753,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "7b3efad5-4b7d-4385-a41c-fecc73afdcc4",
|
"id": "e0d34d7c-7bbb-4847-8864-fbd97a1f3e89",
|
||||||
"alias": "Verify Existing Account by Re-authentication",
|
"alias": "Verify Existing Account by Re-authentication",
|
||||||
"description": "Reauthentication of existing account",
|
"description": "Reauthentication of existing account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1738,7 +1779,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "de93418e-8f28-4099-b15e-ad36ec194796",
|
"id": "5f3d0fb0-d95e-4841-89d3-a27d0cdbbcb4",
|
||||||
"alias": "browser",
|
"alias": "browser",
|
||||||
"description": "browser based authentication",
|
"description": "browser based authentication",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1780,7 +1821,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0dd3345c-6e82-4c3a-a39a-d49ae1f5c409",
|
"id": "c246380d-af25-4151-ab19-1f1e5b553008",
|
||||||
"alias": "clients",
|
"alias": "clients",
|
||||||
"description": "Base authentication for clients",
|
"description": "Base authentication for clients",
|
||||||
"providerId": "client-flow",
|
"providerId": "client-flow",
|
||||||
@ -1822,7 +1863,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "87fb4dd0-5326-47a1-b670-982f4872ff89",
|
"id": "abacf398-0f1f-4f28-a310-8d306d588048",
|
||||||
"alias": "direct grant",
|
"alias": "direct grant",
|
||||||
"description": "OpenID Connect Resource Owner Grant",
|
"description": "OpenID Connect Resource Owner Grant",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1856,7 +1897,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "344723b3-4ab1-4999-abdd-32398e82327b",
|
"id": "a0f87683-619a-44d4-8b4f-4b053bba2346",
|
||||||
"alias": "docker auth",
|
"alias": "docker auth",
|
||||||
"description": "Used by Docker clients to authenticate against the IDP",
|
"description": "Used by Docker clients to authenticate against the IDP",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1874,7 +1915,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "f3341938-caf9-4c8a-9cd5-eb34609809ab",
|
"id": "e8820c7c-22a7-4618-beb7-3e09be72c00c",
|
||||||
"alias": "first broker login",
|
"alias": "first broker login",
|
||||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1901,7 +1942,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ba7b7357-e324-4b71-9bda-f8512a760e02",
|
"id": "cac00c38-ee44-44c9-b95e-cc755bab36ef",
|
||||||
"alias": "forms",
|
"alias": "forms",
|
||||||
"description": "Username, password, otp and other auth forms.",
|
"description": "Username, password, otp and other auth forms.",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1927,7 +1968,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "134971e6-bf63-432c-806e-74ca4fb09963",
|
"id": "688cde36-507e-4a68-afdf-18ec4ad626a7",
|
||||||
"alias": "http challenge",
|
"alias": "http challenge",
|
||||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1953,7 +1994,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "6ea9e2cf-5684-4c65-8c07-930d1cbb0b46",
|
"id": "e058697c-f450-4f14-ae64-04e9299fa24f",
|
||||||
"alias": "registration",
|
"alias": "registration",
|
||||||
"description": "registration flow",
|
"description": "registration flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -1972,7 +2013,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "67e3c8c7-1b5e-4119-84a2-e90876293150",
|
"id": "ad768088-32c9-4979-90dd-61bf111fd72e",
|
||||||
"alias": "registration form",
|
"alias": "registration form",
|
||||||
"description": "registration form",
|
"description": "registration form",
|
||||||
"providerId": "form-flow",
|
"providerId": "form-flow",
|
||||||
@ -2014,7 +2055,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "fc6d48ec-a1f1-41b1-9310-54f58861d5aa",
|
"id": "47d4b090-f965-4588-b5bc-029ccb59876f",
|
||||||
"alias": "reset credentials",
|
"alias": "reset credentials",
|
||||||
"description": "Reset credentials for a user if they forgot their password or something",
|
"description": "Reset credentials for a user if they forgot their password or something",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2056,7 +2097,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "80b1d464-c2ec-4eb1-82e8-32cbede779a8",
|
"id": "1f68feec-7f99-4c49-afe6-45d46684ca21",
|
||||||
"alias": "saml ecp",
|
"alias": "saml ecp",
|
||||||
"description": "SAML ECP Profile Authentication Flow",
|
"description": "SAML ECP Profile Authentication Flow",
|
||||||
"providerId": "basic-flow",
|
"providerId": "basic-flow",
|
||||||
@ -2076,14 +2117,14 @@
|
|||||||
],
|
],
|
||||||
"authenticatorConfig": [
|
"authenticatorConfig": [
|
||||||
{
|
{
|
||||||
"id": "86b1d5fa-450c-40d8-899c-725861ac39fc",
|
"id": "bd7365c7-842b-4bc6-a4ca-498cf025c210",
|
||||||
"alias": "create unique user config",
|
"alias": "create unique user config",
|
||||||
"config": {
|
"config": {
|
||||||
"require.password.update.after.registration": "false"
|
"require.password.update.after.registration": "false"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ea724f02-029a-493d-b4d3-08972be21cfb",
|
"id": "b929192d-f650-4a09-9701-3d3216547552",
|
||||||
"alias": "review profile config",
|
"alias": "review profile config",
|
||||||
"config": {
|
"config": {
|
||||||
"update.profile.on.first.login": "missing"
|
"update.profile.on.first.login": "missing"
|
@ -73,7 +73,7 @@
|
|||||||
"composites": {
|
"composites": {
|
||||||
"realm": ["offline_access", "uma_authorization"],
|
"realm": ["offline_access", "uma_authorization"],
|
||||||
"client": {
|
"client": {
|
||||||
"account": ["delete-account", "view-profile", "manage-account"]
|
"account": ["view-profile", "manage-account", "delete-account"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clientRole": false,
|
"clientRole": false,
|
||||||
@ -456,6 +456,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"create-client",
|
||||||
|
"view-identity-providers",
|
||||||
|
"manage-realm",
|
||||||
|
"query-groups",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"realm-admin",
|
||||||
|
"view-authorization",
|
||||||
|
"view-events",
|
||||||
|
"view-clients",
|
||||||
|
"view-realm",
|
||||||
|
"manage-events",
|
||||||
|
"query-realms",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"manage-users",
|
||||||
|
"view-users",
|
||||||
|
"impersonation",
|
||||||
|
"manage-authorization"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-applications",
|
||||||
|
"manage-consent",
|
||||||
|
"delete-account",
|
||||||
|
"manage-account",
|
||||||
|
"view-groups",
|
||||||
|
"view-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -521,8 +555,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -657,7 +695,6 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
@ -718,8 +755,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1298,11 +1339,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1318,13 +1359,13 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-usermodel-property-mapper",
|
"saml-user-attribute-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
"saml-user-property-mapper",
|
"oidc-usermodel-property-mapper",
|
||||||
"saml-role-list-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-address-mapper"
|
"oidc-address-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1374,14 +1415,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"oidc-usermodel-property-mapper",
|
"oidc-usermodel-property-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-user-attribute-mapper",
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
"saml-role-list-mapper",
|
"saml-role-list-mapper",
|
||||||
"saml-user-property-mapper"
|
"saml-user-attribute-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
@ -55,7 +55,7 @@
|
|||||||
"composites": {
|
"composites": {
|
||||||
"realm": ["offline_access", "uma_authorization"],
|
"realm": ["offline_access", "uma_authorization"],
|
||||||
"client": {
|
"client": {
|
||||||
"account": ["delete-account", "view-profile", "manage-account"]
|
"account": ["view-profile", "delete-account", "manage-account"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clientRole": false,
|
"clientRole": false,
|
||||||
@ -459,6 +459,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"create-client",
|
||||||
|
"view-users",
|
||||||
|
"query-groups",
|
||||||
|
"view-realm",
|
||||||
|
"manage-authorization",
|
||||||
|
"view-authorization",
|
||||||
|
"query-users",
|
||||||
|
"impersonation",
|
||||||
|
"realm-admin",
|
||||||
|
"manage-users",
|
||||||
|
"view-identity-providers",
|
||||||
|
"manage-realm",
|
||||||
|
"manage-clients",
|
||||||
|
"query-realms",
|
||||||
|
"view-events",
|
||||||
|
"manage-events",
|
||||||
|
"view-clients"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"manage-account",
|
||||||
|
"view-consent",
|
||||||
|
"view-groups",
|
||||||
|
"delete-account",
|
||||||
|
"view-applications",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-profile",
|
||||||
|
"manage-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -505,7 +539,6 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
@ -532,8 +565,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -649,7 +686,11 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["https://my-theme.keycloakify.dev/*", "http://localhost*"],
|
"redirectUris": [
|
||||||
|
"https://my-theme.keycloakify.dev/*",
|
||||||
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*"
|
||||||
|
],
|
||||||
"webOrigins": ["*"],
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
@ -664,8 +705,7 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
"post.logout.redirect.uris": "+",
|
||||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*",
|
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"backchannel.logout.revoke.offline.tokens": "false"
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
@ -725,8 +765,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1336,12 +1380,12 @@
|
|||||||
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1357,13 +1401,13 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"saml-user-property-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"saml-role-list-mapper",
|
"saml-role-list-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
"oidc-usermodel-property-mapper"
|
"oidc-usermodel-property-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1433,13 +1477,13 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"saml-role-list-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
"saml-role-list-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-property-mapper"
|
"oidc-usermodel-property-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -468,6 +468,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"manage-clients",
|
||||||
|
"manage-users",
|
||||||
|
"view-identity-providers",
|
||||||
|
"view-users",
|
||||||
|
"impersonation",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"query-users",
|
||||||
|
"query-realms",
|
||||||
|
"realm-admin",
|
||||||
|
"view-events",
|
||||||
|
"view-realm",
|
||||||
|
"manage-events",
|
||||||
|
"manage-authorization",
|
||||||
|
"manage-realm",
|
||||||
|
"query-clients",
|
||||||
|
"query-groups",
|
||||||
|
"view-clients",
|
||||||
|
"create-client",
|
||||||
|
"view-authorization"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"manage-consent",
|
||||||
|
"manage-account-links",
|
||||||
|
"view-applications",
|
||||||
|
"view-consent",
|
||||||
|
"manage-account",
|
||||||
|
"view-profile",
|
||||||
|
"view-groups",
|
||||||
|
"delete-account"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -514,7 +548,6 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
@ -541,8 +574,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -658,7 +695,11 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["https://my-theme.keycloakify.dev/*", "http://localhost*"],
|
"redirectUris": [
|
||||||
|
"https://my-theme.keycloakify.dev/*",
|
||||||
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*"
|
||||||
|
],
|
||||||
"webOrigins": ["*"],
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
@ -673,8 +714,7 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
"post.logout.redirect.uris": "+",
|
||||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*",
|
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"backchannel.logout.revoke.offline.tokens": "false"
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
@ -840,8 +880,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1451,12 +1495,12 @@
|
|||||||
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloak",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1504,11 +1548,11 @@
|
|||||||
"saml-role-list-mapper",
|
"saml-role-list-mapper",
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"oidc-usermodel-property-mapper",
|
"oidc-usermodel-property-mapper",
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper"
|
||||||
"saml-user-property-mapper"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1540,14 +1584,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-usermodel-property-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
|
"saml-user-attribute-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper"
|
||||||
"saml-role-list-mapper",
|
|
||||||
"saml-user-attribute-mapper"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
@ -538,10 +538,10 @@
|
|||||||
"emailVerified": true,
|
"emailVerified": true,
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"],
|
"additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"],
|
||||||
"gender": ["prefer_not_to_say"],
|
|
||||||
"favorite_pet": ["cats"],
|
"favorite_pet": ["cats"],
|
||||||
"favourite_pet": ["cat"],
|
"gender": ["prefer_not_to_say"],
|
||||||
"bio": ["Hello I'm Test User and I do not exist."],
|
"bio": ["Hello I'm Test User and I do not exist."],
|
||||||
|
"favourite_pet": ["cat"],
|
||||||
"phone_number": ["1111111111"],
|
"phone_number": ["1111111111"],
|
||||||
"locale": ["en"],
|
"locale": ["en"],
|
||||||
"favorite_media": ["movies", "series"]
|
"favorite_media": ["movies", "series"]
|
||||||
@ -562,6 +562,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"manage-users",
|
||||||
|
"create-client",
|
||||||
|
"view-users",
|
||||||
|
"view-realm",
|
||||||
|
"query-realms",
|
||||||
|
"impersonation",
|
||||||
|
"view-events",
|
||||||
|
"realm-admin",
|
||||||
|
"manage-authorization",
|
||||||
|
"manage-events",
|
||||||
|
"view-authorization",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"query-groups",
|
||||||
|
"manage-realm",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"view-clients",
|
||||||
|
"view-identity-providers"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"delete-account",
|
||||||
|
"view-applications",
|
||||||
|
"manage-account",
|
||||||
|
"view-consent",
|
||||||
|
"view-groups",
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"manage-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -628,14 +662,16 @@
|
|||||||
"id": "d8f14dc4-5f0f-4a1d-8c0b-cfe78ee55cb3",
|
"id": "d8f14dc4-5f0f-4a1d-8c0b-cfe78ee55cb3",
|
||||||
"clientId": "account-console",
|
"clientId": "account-console",
|
||||||
"name": "${client_account-console}",
|
"name": "${client_account-console}",
|
||||||
|
"description": "",
|
||||||
"rootUrl": "${authBaseUrl}",
|
"rootUrl": "${authBaseUrl}",
|
||||||
|
"adminUrl": "",
|
||||||
"baseUrl": "/realms/myrealm/account/",
|
"baseUrl": "/realms/myrealm/account/",
|
||||||
"surrogateAuthRequired": false,
|
"surrogateAuthRequired": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": ["http://localhost*", "http://127.0.0.1*", "*"],
|
||||||
"webOrigins": [],
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -647,8 +683,13 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"oidc.ciba.grant.enabled": "false",
|
||||||
|
"backchannel.logout.session.required": "true",
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"pkce.code.challenge.method": "S256"
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
|
"display.on.consent.screen": "false",
|
||||||
|
"pkce.code.challenge.method": "S256",
|
||||||
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
"fullScopeAllowed": false,
|
"fullScopeAllowed": false,
|
||||||
@ -791,8 +832,7 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
"post.logout.redirect.uris": "+",
|
||||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
|
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"backchannel.logout.revoke.offline.tokens": "false"
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
@ -885,8 +925,12 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -1544,11 +1588,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1574,14 +1618,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
|
"saml-role-list-mapper",
|
||||||
"oidc-full-name-mapper",
|
"oidc-full-name-mapper",
|
||||||
|
"saml-user-property-mapper",
|
||||||
|
"saml-user-attribute-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
"oidc-usermodel-attribute-mapper",
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"saml-user-attribute-mapper",
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-property-mapper",
|
"oidc-usermodel-property-mapper"
|
||||||
"saml-user-property-mapper",
|
|
||||||
"saml-role-list-mapper",
|
|
||||||
"oidc-sha256-pairwise-sub-mapper"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1611,14 +1655,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
|
||||||
"oidc-usermodel-property-mapper",
|
|
||||||
"oidc-address-mapper",
|
"oidc-address-mapper",
|
||||||
"oidc-usermodel-attribute-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
|
"oidc-full-name-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"oidc-usermodel-attribute-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"saml-role-list-mapper"
|
"oidc-usermodel-property-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1672,11 +1716,10 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"privateKey": [
|
"privateKey": [
|
||||||
"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"
|
||||||
],
|
],
|
||||||
"keyUse": ["SIG"],
|
|
||||||
"certificate": [
|
"certificate": [
|
||||||
"MIICnTCCAYUCBgGQBsyplzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGFFs1X2THessKQZiyWHhdVPTIHf898Vr5dWKu+qETz36XKkIrTfnJLVqrtIT3qwlUpdpbcFwzK1MBc7MBvTIjPYW/gSxJXe5GImJHBTbd5QrZpnkUBGnuycFops3jVfekJc9LR2PH/WYdH3zw7C0zdRxgHkSSYSO5jUJuqgiTTAn1QPzuUlrprCJ9ly50jIkNOQAAlRzi1KuqwGdswgmmJl05iZLkjm/Htuld9Nz+petw0nuR0jVw3SNNLY3xRX9+6vO9M4b37KLa448dETIo8vSo4/DmRfqRR6Q0WhhIvLaUMWQ5wk6H04ngf1ad0D/mk5bwMg90NWZycRkAi8oMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVS+gJshIFX6cmBGI8UaOOI/9+XFb4Gi+DHaHVWVVHTd14MoqNK1bmmyTHbGIZbvK8UqgJ9+FhJX1ejx17d4KBzkZI3tYvPnVacHvaw1CIUMZ1Ini6u+UGUTnIlnQzCG0pcTKjOZXf3ih1B2CKdwyC7XeXyEJHicAIG7XfzYfYd9DYHvA+h6hrXaQcNJMW7WFNbtb3fJhtlv5P1Iw+ZEGdj15ukMI0bg2OEQA0F3jIw6QZpigSAGuai3HOY6OgoPO82d7TyTYlNhuwyutWr9izl6QMc2R7BmRfW9XQj4ICR2VWJiL9nqz+SOyqnjQiOObuw8Vywb8c36R1Ym1aaGjOw=="
|
"MIICnTCCAYUCBgGTy2TGBjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE3MzQ1OVoXDTM0MTIxNTE3MzYzOVowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKPPaqby4X/QyHAm9iQG8SLUS0iLz/zQmYTHQBMUx8q4TOQdu2UOjGe3SUG5zLu0Ce8ogpbA9V5wze1pY9O7GNgLN5WN7/ZIzgwXgA2JT7jdZu/31xR196n0U/j8FUmgITMpJqr1qfOlE4O7e6zY1QZ1zz1yLZkSyBfo2VDFkHbsDc56+iYeeGXSMBMuIb19W6TcNJz5eCl4jotnpb4Pq5OwYRcsBsEPx1AhpK3KtF0v2jTstQoZqg27avNe5mKVXrXgg3vMT9zD62f7Ni4hLeCKdXDaNHWPmuCcDs8C+NodxmkfvNIit6WTaPjK9CgTmPRl73VfzL3Dxy0O1bo1BkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAggzxmYvHqUaCPLxxSidLQMgpu1pTozg3rTq8dcxhcHINI//A/z7qQyDA/QQN5cuSpYvdt2MRWoNop+uRNKqSr3C8aRErbY0j4acl7yG/ghNfQUZ9KxDBxKrd0HLFUibdZobg10+Ih/qXo3Mi2VtkqyZQRl/iy0O3ITgqb7YJUEx5tuEWyGbn+SerFvqZNcmsLziOJefm1n4uqroHgIfmgY6Deh+wZK0DwO3WZ6ThjhMp5GFi1oNeZ9xoExNEXrYp07b2xTQFF57oypc7prf733lqGjPRLfoVJP6qcsjvAlOA7f8TG9sKwGuRsPfadYY9PxmdHxl2k7PHDJeDhA7VdQ=="
|
||||||
],
|
],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
@ -1688,11 +1731,10 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"privateKey": [
|
"privateKey": [
|
||||||
"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"
|
||||||
],
|
],
|
||||||
"keyUse": ["ENC"],
|
|
||||||
"certificate": [
|
"certificate": [
|
||||||
"MIICnTCCAYUCBgGQBsyq0jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJELXnx8vNnvHeXVVjdNC5xiOWJgTkyodLYKmslUY6ix+rtzX4CVVSHtLRZ8Wu1pGv8kh659SkrFudnM2eLj1y1KOLFwZEMcshV3mYljfB/vVolEPtIXn2ReHrOWT4WNlaXjCvVwJ6YQt+tixS1cnF7pZKSXEPuA4yPfU6OCy8iZo0L7FWie2pqFSecXetnlL/g+39vo8Lmk8IxhN/jFmQA141cbFGNaibhixipy5DTcSTTA4b5ymMPmmt2eFfdH0FcozdVaJYMNw3QOfaOMK1hMvtsR3Oo9hEovPnDOtH1s2VPbKdl5MiaAp1e55sJO6WZA8t87wJHjls669zlnkd8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAD9wQ+CJ0FRgls3JrUzxwHLgrJ3Yo4+mDFpSe1rh2XYK5FEIWDWSqxaXI3p0cOZq75RZmI2xV8oaiJMUz9WMZkbNe/KtGRzHY1N9AZooicGIsnFu1t++b8taFxxpvKWZgnbOum2PZlfcNiXL0QeMv0wwhfn9zKA9W1DRcqYGbIamoyVlumvbNyIjqXJKwGYIOW6GNt7v3wJl5AJw8qAU/O/DQwWwmzcnFGNRxRxAwI7we8EiQ5JlG0Wi+nyAQn74o3RhNr3zsY0ndmFx9bFV4BBo2AiYGozCDOCCG5HvrmoDbrm//wmGRv0tCwueBzWHL2mhtbZ6sGWmMWfiTJ2HPpg=="
|
"MIICnTCCAYUCBgGTy2TG/jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE3MzQ1OVoXDTM0MTIxNTE3MzYzOVowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMaBL57/mBwqlFgDRrpLuUGLHAGclBNFh0pXAM2dG0LoD6MOt6YkLLsT89HKTyLi2m+mnbLF1KihBYXk9R9AarZk/S/+4jigejEbiJzeGkc80x/atNkyj5HKUgMwB0xnLCQTDGsJW5yHTLufpnrzD8anlVcb65yhtu0vB91uY6iJEMPG6OuOh695eQ8av42O7JXEl113uGXXn3gr50qnmvn8uXPq/6+eOp1+BUxopJbuii0Gg3PUnxnHK2Q5pY2Ow19ZB65ryHS0oXLrpEx3NIYtqm4DHFLXv+/7L0iS1FjmTmysXrXeMtTgOPb9+sazKhocBg3cK1n9FbjATfHhzgkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdUIlJ91E0UkFS45AByjFufRnQbAi1smnHkC3WSN39bhcFT7Hgip97qtABODR58zVHSTS0XcMiL4mMObH3Vyz9J3gmwWZnbokAuo9tYeyrhPh/gqXv3LGtGhTpWlUJ7JEJxH7RVI4UZZyG6Y6FR+3zwiZ0j1p3QsZclfcNmacoi/Ano+4TfloOnY4k8yP7G6LWUTJHpcRNWVVozM3RwekYgpJRAtXDoYfm9p2hRQ090e7NvbblSuVQ/FXhUn4g0wz91WdCWlwXZfvNaRjbynPCHejJpszqiyjPkx3aRKTWqer0ZocKNmY8+RO27XIsXmwOYcjdpX2TCFDv6O+VLfNdw=="
|
||||||
],
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["RSA-OAEP"]
|
"algorithm": ["RSA-OAEP"]
|
||||||
@ -1704,8 +1746,8 @@
|
|||||||
"providerId": "aes-generated",
|
"providerId": "aes-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"kid": ["1c1d0c8a-6f0b-48a9-a66f-488489137d85"],
|
"kid": ["95db7eb8-b57b-475e-90cd-58841a9388d3"],
|
||||||
"secret": ["N4wzheVYYBWxFn9VGWTPQQ"],
|
"secret": ["dp6bv53YrC2PZuJCxa3aNA"],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1715,9 +1757,9 @@
|
|||||||
"providerId": "hmac-generated",
|
"providerId": "hmac-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"kid": ["ce43821c-6cfd-4ea9-a29a-a724a37e6955"],
|
"kid": ["d0254883-059e-4fdd-bf03-704c76650aab"],
|
||||||
"secret": [
|
"secret": [
|
||||||
"j_8WeQHYt5R6coay0IOUeu9hGvCoJsgnENSoYm0gDlDx6IHOg-f6p17QIaesNmgrzXtJDRpYMhSjpTMHOnHCHLxwUM4eVg9TcszffndB850Yj3PHPeCc5aoHcpYzWN9NDZZ02nBYA04nfbkdlLXiGlpS3I3e502e4DX3rFtbFZ0"
|
"bcW7E4rcbgSKZIQysWOSuhezRGYs5Kzmp3ZESthdTUMyFivK8RbBAdBE4PhFPk5B9TuByDO2RWvd8F7F5YhGJitf6cfYB1BfDuAk-2iBAtdZA98g7a2h4jpwzh-GIgtoRbGbH9qnquUn52f5qteo34g5WifKE2bWjOELza9FrTo"
|
||||||
],
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["HS512"]
|
"algorithm": ["HS512"]
|
||||||
@ -2388,7 +2430,7 @@
|
|||||||
"clientSessionMaxLifespan": "0",
|
"clientSessionMaxLifespan": "0",
|
||||||
"organizationsEnabled": "false"
|
"organizationsEnabled": "false"
|
||||||
},
|
},
|
||||||
"keycloakVersion": "25.0.0",
|
"keycloakVersion": "25.0.6",
|
||||||
"userManagedAccessAllowed": false,
|
"userManagedAccessAllowed": false,
|
||||||
"organizationsEnabled": false,
|
"organizationsEnabled": false,
|
||||||
"clientProfiles": {
|
"clientProfiles": {
|
@ -38,6 +38,7 @@
|
|||||||
"bruteForceProtected": false,
|
"bruteForceProtected": false,
|
||||||
"permanentLockout": false,
|
"permanentLockout": false,
|
||||||
"maxTemporaryLockouts": 0,
|
"maxTemporaryLockouts": 0,
|
||||||
|
"bruteForceStrategy": "MULTIPLE",
|
||||||
"maxFailureWaitSeconds": 900,
|
"maxFailureWaitSeconds": 900,
|
||||||
"minimumQuickLoginWaitSeconds": 60,
|
"minimumQuickLoginWaitSeconds": 60,
|
||||||
"waitIncrementSeconds": 60,
|
"waitIncrementSeconds": 60,
|
||||||
@ -562,6 +563,40 @@
|
|||||||
"disableableCredentialTypes": [],
|
"disableableCredentialTypes": [],
|
||||||
"requiredActions": [],
|
"requiredActions": [],
|
||||||
"realmRoles": ["default-roles-myrealm"],
|
"realmRoles": ["default-roles-myrealm"],
|
||||||
|
"clientRoles": {
|
||||||
|
"realm-management": [
|
||||||
|
"manage-users",
|
||||||
|
"create-client",
|
||||||
|
"view-users",
|
||||||
|
"view-realm",
|
||||||
|
"query-realms",
|
||||||
|
"impersonation",
|
||||||
|
"view-events",
|
||||||
|
"realm-admin",
|
||||||
|
"manage-authorization",
|
||||||
|
"view-authorization",
|
||||||
|
"manage-events",
|
||||||
|
"manage-clients",
|
||||||
|
"query-users",
|
||||||
|
"query-groups",
|
||||||
|
"manage-realm",
|
||||||
|
"query-clients",
|
||||||
|
"manage-identity-providers",
|
||||||
|
"view-identity-providers",
|
||||||
|
"view-clients"
|
||||||
|
],
|
||||||
|
"broker": ["read-token"],
|
||||||
|
"account": [
|
||||||
|
"delete-account",
|
||||||
|
"view-applications",
|
||||||
|
"manage-account",
|
||||||
|
"view-consent",
|
||||||
|
"view-groups",
|
||||||
|
"view-profile",
|
||||||
|
"manage-account-links",
|
||||||
|
"manage-consent"
|
||||||
|
]
|
||||||
|
},
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"groups": []
|
"groups": []
|
||||||
}
|
}
|
||||||
@ -604,6 +639,7 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "false",
|
||||||
"post.logout.redirect.uris": "+"
|
"post.logout.redirect.uris": "+"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
@ -628,14 +664,20 @@
|
|||||||
"id": "d8f14dc4-5f0f-4a1d-8c0b-cfe78ee55cb3",
|
"id": "d8f14dc4-5f0f-4a1d-8c0b-cfe78ee55cb3",
|
||||||
"clientId": "account-console",
|
"clientId": "account-console",
|
||||||
"name": "${client_account-console}",
|
"name": "${client_account-console}",
|
||||||
|
"description": "",
|
||||||
"rootUrl": "${authBaseUrl}",
|
"rootUrl": "${authBaseUrl}",
|
||||||
|
"adminUrl": "",
|
||||||
"baseUrl": "/realms/myrealm/account/",
|
"baseUrl": "/realms/myrealm/account/",
|
||||||
"surrogateAuthRequired": false,
|
"surrogateAuthRequired": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/realms/myrealm/account/*"],
|
"redirectUris": [
|
||||||
"webOrigins": [],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/realms/myrealm/account/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -647,8 +689,14 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "false",
|
||||||
|
"oidc.ciba.grant.enabled": "false",
|
||||||
|
"backchannel.logout.session.required": "true",
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"pkce.code.challenge.method": "S256"
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
|
"display.on.consent.screen": "false",
|
||||||
|
"pkce.code.challenge.method": "S256",
|
||||||
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
"fullScopeAllowed": false,
|
"fullScopeAllowed": false,
|
||||||
@ -699,10 +747,12 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "false",
|
||||||
|
"client.use.lightweight.access.token.enabled": "true",
|
||||||
"post.logout.redirect.uris": "+"
|
"post.logout.redirect.uris": "+"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
"fullScopeAllowed": false,
|
"fullScopeAllowed": true,
|
||||||
"nodeReRegistrationTimeout": 0,
|
"nodeReRegistrationTimeout": 0,
|
||||||
"defaultClientScopes": [
|
"defaultClientScopes": [
|
||||||
"web-origins",
|
"web-origins",
|
||||||
@ -740,6 +790,7 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "true",
|
||||||
"post.logout.redirect.uris": "+"
|
"post.logout.redirect.uris": "+"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
@ -789,10 +840,10 @@
|
|||||||
"frontchannelLogout": true,
|
"frontchannelLogout": true,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "false",
|
||||||
"oidc.ciba.grant.enabled": "false",
|
"oidc.ciba.grant.enabled": "false",
|
||||||
"backchannel.logout.session.required": "true",
|
"backchannel.logout.session.required": "true",
|
||||||
"login_theme": "keycloakify-starter",
|
"post.logout.redirect.uris": "+",
|
||||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
|
|
||||||
"oauth2.device.authorization.grant.enabled": "false",
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
"display.on.consent.screen": "false",
|
"display.on.consent.screen": "false",
|
||||||
"backchannel.logout.revoke.offline.tokens": "false"
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
@ -855,6 +906,7 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "true",
|
||||||
"post.logout.redirect.uris": "+"
|
"post.logout.redirect.uris": "+"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
@ -879,14 +931,20 @@
|
|||||||
"id": "fce8a109-6f32-4814-9a20-2ff2435d2da6",
|
"id": "fce8a109-6f32-4814-9a20-2ff2435d2da6",
|
||||||
"clientId": "security-admin-console",
|
"clientId": "security-admin-console",
|
||||||
"name": "${client_security-admin-console}",
|
"name": "${client_security-admin-console}",
|
||||||
|
"description": "",
|
||||||
"rootUrl": "${authAdminUrl}",
|
"rootUrl": "${authAdminUrl}",
|
||||||
|
"adminUrl": "",
|
||||||
"baseUrl": "/admin/myrealm/console/",
|
"baseUrl": "/admin/myrealm/console/",
|
||||||
"surrogateAuthRequired": false,
|
"surrogateAuthRequired": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"alwaysDisplayInConsole": false,
|
"alwaysDisplayInConsole": false,
|
||||||
"clientAuthenticatorType": "client-secret",
|
"clientAuthenticatorType": "client-secret",
|
||||||
"redirectUris": ["/admin/myrealm/console/*"],
|
"redirectUris": [
|
||||||
"webOrigins": ["+"],
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*",
|
||||||
|
"/admin/myrealm/console/*"
|
||||||
|
],
|
||||||
|
"webOrigins": ["*"],
|
||||||
"notBefore": 0,
|
"notBefore": 0,
|
||||||
"bearerOnly": false,
|
"bearerOnly": false,
|
||||||
"consentRequired": false,
|
"consentRequired": false,
|
||||||
@ -898,11 +956,18 @@
|
|||||||
"frontchannelLogout": false,
|
"frontchannelLogout": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"realm_client": "false",
|
||||||
|
"oidc.ciba.grant.enabled": "false",
|
||||||
|
"client.use.lightweight.access.token.enabled": "true",
|
||||||
|
"backchannel.logout.session.required": "true",
|
||||||
"post.logout.redirect.uris": "+",
|
"post.logout.redirect.uris": "+",
|
||||||
"pkce.code.challenge.method": "S256"
|
"oauth2.device.authorization.grant.enabled": "false",
|
||||||
|
"display.on.consent.screen": "false",
|
||||||
|
"pkce.code.challenge.method": "S256",
|
||||||
|
"backchannel.logout.revoke.offline.tokens": "false"
|
||||||
},
|
},
|
||||||
"authenticationFlowBindingOverrides": {},
|
"authenticationFlowBindingOverrides": {},
|
||||||
"fullScopeAllowed": false,
|
"fullScopeAllowed": true,
|
||||||
"nodeReRegistrationTimeout": 0,
|
"nodeReRegistrationTimeout": 0,
|
||||||
"protocolMappers": [
|
"protocolMappers": [
|
||||||
{
|
{
|
||||||
@ -1544,11 +1609,11 @@
|
|||||||
},
|
},
|
||||||
"smtpServer": {},
|
"smtpServer": {},
|
||||||
"loginTheme": "keycloakify-starter",
|
"loginTheme": "keycloakify-starter",
|
||||||
"accountTheme": "keycloakify-starter",
|
"accountTheme": "",
|
||||||
"adminTheme": "",
|
"adminTheme": "",
|
||||||
"emailTheme": "",
|
"emailTheme": "",
|
||||||
"eventsEnabled": false,
|
"eventsEnabled": false,
|
||||||
"eventsListeners": ["jboss-logging"],
|
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||||
"enabledEventTypes": [],
|
"enabledEventTypes": [],
|
||||||
"adminEventsEnabled": false,
|
"adminEventsEnabled": false,
|
||||||
"adminEventsDetailsEnabled": false,
|
"adminEventsDetailsEnabled": false,
|
||||||
@ -1574,14 +1639,14 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"oidc-usermodel-attribute-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
|
||||||
"oidc-usermodel-property-mapper",
|
"oidc-usermodel-property-mapper",
|
||||||
|
"saml-user-attribute-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"saml-role-list-mapper",
|
"oidc-full-name-mapper",
|
||||||
"oidc-sha256-pairwise-sub-mapper"
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
|
"oidc-address-mapper",
|
||||||
|
"oidc-usermodel-attribute-mapper",
|
||||||
|
"saml-role-list-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1612,13 +1677,13 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"allowed-protocol-mapper-types": [
|
"allowed-protocol-mapper-types": [
|
||||||
"oidc-sha256-pairwise-sub-mapper",
|
"oidc-sha256-pairwise-sub-mapper",
|
||||||
"oidc-usermodel-property-mapper",
|
|
||||||
"oidc-address-mapper",
|
|
||||||
"oidc-usermodel-attribute-mapper",
|
|
||||||
"oidc-full-name-mapper",
|
|
||||||
"saml-user-attribute-mapper",
|
"saml-user-attribute-mapper",
|
||||||
|
"oidc-usermodel-property-mapper",
|
||||||
|
"oidc-full-name-mapper",
|
||||||
|
"saml-role-list-mapper",
|
||||||
"saml-user-property-mapper",
|
"saml-user-property-mapper",
|
||||||
"saml-role-list-mapper"
|
"oidc-usermodel-attribute-mapper",
|
||||||
|
"oidc-address-mapper"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1672,11 +1737,10 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"privateKey": [
|
"privateKey": [
|
||||||
"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"
|
||||||
],
|
],
|
||||||
"keyUse": ["SIG"],
|
|
||||||
"certificate": [
|
"certificate": [
|
||||||
"MIICnTCCAYUCBgGQBsyplzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGFFs1X2THessKQZiyWHhdVPTIHf898Vr5dWKu+qETz36XKkIrTfnJLVqrtIT3qwlUpdpbcFwzK1MBc7MBvTIjPYW/gSxJXe5GImJHBTbd5QrZpnkUBGnuycFops3jVfekJc9LR2PH/WYdH3zw7C0zdRxgHkSSYSO5jUJuqgiTTAn1QPzuUlrprCJ9ly50jIkNOQAAlRzi1KuqwGdswgmmJl05iZLkjm/Htuld9Nz+petw0nuR0jVw3SNNLY3xRX9+6vO9M4b37KLa448dETIo8vSo4/DmRfqRR6Q0WhhIvLaUMWQ5wk6H04ngf1ad0D/mk5bwMg90NWZycRkAi8oMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVS+gJshIFX6cmBGI8UaOOI/9+XFb4Gi+DHaHVWVVHTd14MoqNK1bmmyTHbGIZbvK8UqgJ9+FhJX1ejx17d4KBzkZI3tYvPnVacHvaw1CIUMZ1Ini6u+UGUTnIlnQzCG0pcTKjOZXf3ih1B2CKdwyC7XeXyEJHicAIG7XfzYfYd9DYHvA+h6hrXaQcNJMW7WFNbtb3fJhtlv5P1Iw+ZEGdj15ukMI0bg2OEQA0F3jIw6QZpigSAGuai3HOY6OgoPO82d7TyTYlNhuwyutWr9izl6QMc2R7BmRfW9XQj4ICR2VWJiL9nqz+SOyqnjQiOObuw8Vywb8c36R1Ym1aaGjOw=="
|
"MIICnTCCAYUCBgGTulJBzTANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxMjEwMDExM1oXDTM0MTIxMjEwMDI1M1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMUxTL0YjYkI2Pc2o7y7GoelcuKZ/FO7JrJwXB0vUpCydY/TvPvdAfdLSGZOCKhBOIHSQP5m23lJ6Ltb1rnNJOvXYkDBXpc3SGg6iWhRXjkvidQ6AKY04YxiM+xSIJhouqqDfMZ6z1Q/+qDGALsU70GiR+5hDYiBtNffHb2rn1dZhT4PpK07Ie1qJqNgiXmZjbgF7+0Q0GMcD2AwhWS26aXs+PA+/tg/tVekrZOl8M/CA0Gb5Y8Qxeltj/a4T1ldQubXCaQv/UT8hg6PpHvFDd3zOl+2DoKWzM7Va4PCdGk6j12e3bekBVKlTrn6PucGC9owmn6WDVfHJmhpWPkN3eUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATZXyOluloTj6Q/Mv0JjstfdvPQbzGFzWtULB1ttOJqQVL+IJoF8V79HIvfP9U5OYaOdYk9dDurQcd2hXvEtX+zQlLYGniRfJlFI7d+m6MDXa7/g1r+OmcvaiXX7O3ol7eJdymPKS79+PSWFsHk0JjfgRJ11jajOscYPoQ+IvxXgwuy6v7VHigsLnGnmmo+KWiKO6Cna6eilm6/awYXaoym4ky9S4T5+WaJwd/tH/n5VY77zyXaXfANd1hU/+4Ux/eaGVnoMAM4ud2emd4qCN2tQQ3HusIVl+5V+S8Uq1y54mBpXv6CAODDGDJeFa+cGPJUSLdv/ZT2F8yfDlDc4J6g=="
|
||||||
],
|
],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
@ -1688,11 +1752,10 @@
|
|||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"privateKey": [
|
"privateKey": [
|
||||||
"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"
|
||||||
],
|
],
|
||||||
"keyUse": ["ENC"],
|
|
||||||
"certificate": [
|
"certificate": [
|
||||||
"MIICnTCCAYUCBgGQBsyq0jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJELXnx8vNnvHeXVVjdNC5xiOWJgTkyodLYKmslUY6ix+rtzX4CVVSHtLRZ8Wu1pGv8kh659SkrFudnM2eLj1y1KOLFwZEMcshV3mYljfB/vVolEPtIXn2ReHrOWT4WNlaXjCvVwJ6YQt+tixS1cnF7pZKSXEPuA4yPfU6OCy8iZo0L7FWie2pqFSecXetnlL/g+39vo8Lmk8IxhN/jFmQA141cbFGNaibhixipy5DTcSTTA4b5ymMPmmt2eFfdH0FcozdVaJYMNw3QOfaOMK1hMvtsR3Oo9hEovPnDOtH1s2VPbKdl5MiaAp1e55sJO6WZA8t87wJHjls669zlnkd8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAD9wQ+CJ0FRgls3JrUzxwHLgrJ3Yo4+mDFpSe1rh2XYK5FEIWDWSqxaXI3p0cOZq75RZmI2xV8oaiJMUz9WMZkbNe/KtGRzHY1N9AZooicGIsnFu1t++b8taFxxpvKWZgnbOum2PZlfcNiXL0QeMv0wwhfn9zKA9W1DRcqYGbIamoyVlumvbNyIjqXJKwGYIOW6GNt7v3wJl5AJw8qAU/O/DQwWwmzcnFGNRxRxAwI7we8EiQ5JlG0Wi+nyAQn74o3RhNr3zsY0ndmFx9bFV4BBo2AiYGozCDOCCG5HvrmoDbrm//wmGRv0tCwueBzWHL2mhtbZ6sGWmMWfiTJ2HPpg=="
|
"MIICnTCCAYUCBgGTulJDCDANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxMjEwMDExM1oXDTM0MTIxMjEwMDI1M1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALp4C+KLC8j/GxOjEio/GTCUxvFgYdytv8QeQSWAmHOz9QiDkWSPaP7ykMdUJz/gl5CCp50dpMyMwtK506pSDpGmX4Zkp+dIxubzQUvaj0/llO1Ht6isbliRcHGhVOUhCWsCR6pwzyvqZLZJMZLnXjB8+omij7PsCnG360Sevt2txakEHRxEIOCI1VPKQWZmoNXOyR2sojOejk+cuo5hOSb2OtPefYj62T10kzFN4TaIlcHciukMHSvv9MKzuvNVYSD/rtqXvdp0PobIDEkkCXoC8dVLBBMlPO7Mm5Rvqd8wCkkvpLdp74lf2tnGIojBNC3ZUN5ZyrEOLdWOsmQYktkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAPhPdLFcXdQT4k06oXB06ZSJ8AkZNXLvQFWCHXI34OmrS2yTse+dLqrqehnC3kPwxElVmawoUVc1sbsk7fUnspfM+Xw20PaABZu4MO2m5TB98f1hEkezP9fSqgPeuWJgTL8ZW5kkZyiD3IaZoqyxzYXaFxKHhU455g+k2+DO+N6FreVKcYz12Q5EMaxZ6U1neZAo3vicNxM3/TA5V8sPK8+oKvon7v5OyjpOH0goJo9v/klKeUk36h4u2h1S67IhVSU7tfzVFYrpns1JhrwGZ2xavVqEoqX8zFp3GKz3yVXkwHRHlrzYkZoGn21rm5boXIP3wEB7yXZbXWTiUko/IFw=="
|
||||||
],
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["RSA-OAEP"]
|
"algorithm": ["RSA-OAEP"]
|
||||||
@ -1704,8 +1767,8 @@
|
|||||||
"providerId": "aes-generated",
|
"providerId": "aes-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"kid": ["1c1d0c8a-6f0b-48a9-a66f-488489137d85"],
|
"kid": ["c36222c6-6a43-4d32-9d44-d5d355e5cabd"],
|
||||||
"secret": ["N4wzheVYYBWxFn9VGWTPQQ"],
|
"secret": ["rzL4qUQ7wTEkZDbgt595VA"],
|
||||||
"priority": ["100"]
|
"priority": ["100"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1715,9 +1778,9 @@
|
|||||||
"providerId": "hmac-generated",
|
"providerId": "hmac-generated",
|
||||||
"subComponents": {},
|
"subComponents": {},
|
||||||
"config": {
|
"config": {
|
||||||
"kid": ["ce43821c-6cfd-4ea9-a29a-a724a37e6955"],
|
"kid": ["06532a54-c310-41c1-829c-58776ce2ab4a"],
|
||||||
"secret": [
|
"secret": [
|
||||||
"j_8WeQHYt5R6coay0IOUeu9hGvCoJsgnENSoYm0gDlDx6IHOg-f6p17QIaesNmgrzXtJDRpYMhSjpTMHOnHCHLxwUM4eVg9TcszffndB850Yj3PHPeCc5aoHcpYzWN9NDZZ02nBYA04nfbkdlLXiGlpS3I3e502e4DX3rFtbFZ0"
|
"9v1ZjFhEFH6UpY6ncFkaCbqJYHMyI4tA0cvx4GuQ5KtMXYbimitSSVDqxIKwa-gBC_8bY2O4FQfpmp1Qn1-L4fFmPFfIF3ZKsO16263BwpADo_FNSBTte8Le4gJLylqFULdsn3ye17FHyq5Jjms_OTt3opzcDLNduCuK22GBBsU"
|
||||||
],
|
],
|
||||||
"priority": ["100"],
|
"priority": ["100"],
|
||||||
"algorithm": ["HS512"]
|
"algorithm": ["HS512"]
|
||||||
@ -2388,7 +2451,7 @@
|
|||||||
"clientSessionMaxLifespan": "0",
|
"clientSessionMaxLifespan": "0",
|
||||||
"organizationsEnabled": "false"
|
"organizationsEnabled": "false"
|
||||||
},
|
},
|
||||||
"keycloakVersion": "25.0.0",
|
"keycloakVersion": "26.0.7",
|
||||||
"userManagedAccessAllowed": false,
|
"userManagedAccessAllowed": false,
|
||||||
"organizationsEnabled": false,
|
"organizationsEnabled": false,
|
||||||
"clientProfiles": {
|
"clientProfiles": {
|
147
src/bin/start-keycloak/realmConfig/dumpContainerConfig.ts
Normal file
147
src/bin/start-keycloak/realmConfig/dumpContainerConfig.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { CONTAINER_NAME } from "../../shared/constants";
|
||||||
|
import child_process from "child_process";
|
||||||
|
import { join as pathJoin } from "path";
|
||||||
|
import chalk from "chalk";
|
||||||
|
import { Deferred } from "evt/tools/Deferred";
|
||||||
|
import { assert, is } from "tsafe/assert";
|
||||||
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
|
import { type ParsedRealmJson, readRealmJsonFile } from "./ParsedRealmJson";
|
||||||
|
|
||||||
|
export type BuildContextLike = {
|
||||||
|
cacheDirPath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||||
|
|
||||||
|
export async function dumpContainerConfig(params: {
|
||||||
|
realmName: string;
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}): Promise<ParsedRealmJson> {
|
||||||
|
const { realmName, keycloakMajorVersionNumber, buildContext } = params;
|
||||||
|
|
||||||
|
{
|
||||||
|
// https://github.com/keycloak/keycloak/issues/33800
|
||||||
|
const doesUseLockedH2Database = keycloakMajorVersionNumber >= 25;
|
||||||
|
|
||||||
|
if (doesUseLockedH2Database) {
|
||||||
|
child_process.execSync(
|
||||||
|
`docker exec ${CONTAINER_NAME} sh -c "cp -rp /opt/keycloak/data/h2 /tmp"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dCompleted = new Deferred<void>();
|
||||||
|
|
||||||
|
const child = child_process.spawn(
|
||||||
|
"docker",
|
||||||
|
[
|
||||||
|
...["exec", CONTAINER_NAME],
|
||||||
|
...["/opt/keycloak/bin/kc.sh", "export"],
|
||||||
|
...["--dir", "/tmp"],
|
||||||
|
...["--realm", realmName],
|
||||||
|
...["--users", "realm_file"],
|
||||||
|
...(!doesUseLockedH2Database
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
...["--db", "dev-file"],
|
||||||
|
...[
|
||||||
|
"--db-url",
|
||||||
|
"'jdbc:h2:file:/tmp/h2/keycloakdb;NON_KEYWORDS=VALUE'"
|
||||||
|
]
|
||||||
|
])
|
||||||
|
],
|
||||||
|
{ shell: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
|
||||||
|
const onExit = (code: number | null) => {
|
||||||
|
dCompleted.reject(new Error(`Exited with code ${code}`));
|
||||||
|
};
|
||||||
|
|
||||||
|
child.once("exit", onExit);
|
||||||
|
|
||||||
|
child.stdout.on("data", data => {
|
||||||
|
const outputStr = data.toString("utf8");
|
||||||
|
|
||||||
|
if (outputStr.includes("Export finished successfully")) {
|
||||||
|
child.removeListener("exit", onExit);
|
||||||
|
|
||||||
|
// NOTE: On older Keycloak versions the process keeps running after the export is done.
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
child.removeListener("exit", onExit2);
|
||||||
|
child.kill();
|
||||||
|
dCompleted.resolve();
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
const onExit2 = () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
dCompleted.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
child.once("exit", onExit2);
|
||||||
|
}
|
||||||
|
|
||||||
|
output += outputStr;
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on("data", data => (output += chalk.red(data.toString("utf8"))));
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dCompleted.pr;
|
||||||
|
} catch (error) {
|
||||||
|
assert(is<Error>(error));
|
||||||
|
|
||||||
|
console.log(chalk.red(error.message));
|
||||||
|
|
||||||
|
console.log(output);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doesUseLockedH2Database) {
|
||||||
|
const dCompleted = new Deferred<void>();
|
||||||
|
|
||||||
|
child_process.exec(
|
||||||
|
`docker exec ${CONTAINER_NAME} sh -c "rm -rf /tmp/h2"`,
|
||||||
|
error => {
|
||||||
|
if (error !== null) {
|
||||||
|
dCompleted.reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dCompleted.resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await dCompleted.pr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetRealmConfigJsonFilePath_tmp = pathJoin(
|
||||||
|
buildContext.cacheDirPath,
|
||||||
|
"realm.json"
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
const dCompleted = new Deferred<void>();
|
||||||
|
|
||||||
|
child_process.exec(
|
||||||
|
`docker cp ${CONTAINER_NAME}:/tmp/${realmName}-realm.json ${targetRealmConfigJsonFilePath_tmp}`,
|
||||||
|
error => {
|
||||||
|
if (error !== null) {
|
||||||
|
dCompleted.reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dCompleted.resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await dCompleted.pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readRealmJsonFile({
|
||||||
|
realmJsonFilePath: targetRealmConfigJsonFilePath_tmp
|
||||||
|
});
|
||||||
|
}
|
1
src/bin/start-keycloak/realmConfig/index.ts
Normal file
1
src/bin/start-keycloak/realmConfig/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./realmConfig";
|
302
src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts
Normal file
302
src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import type { ParsedRealmJson } from "./ParsedRealmJson";
|
||||||
|
import { getDefaultConfig } from "./defaultConfig";
|
||||||
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
|
import { objectKeys } from "tsafe/objectKeys";
|
||||||
|
import { TEST_APP_URL } from "../../shared/constants";
|
||||||
|
import { sameFactory } from "evt/tools/inDepth/same";
|
||||||
|
|
||||||
|
export type BuildContextLike = {
|
||||||
|
themeNames: BuildContext["themeNames"];
|
||||||
|
implementedThemeTypes: BuildContext["implementedThemeTypes"];
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>;
|
||||||
|
|
||||||
|
export function prepareRealmConfig(params: {
|
||||||
|
parsedRealmJson: ParsedRealmJson;
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}): {
|
||||||
|
realmName: string;
|
||||||
|
clientName: string;
|
||||||
|
username: string;
|
||||||
|
} {
|
||||||
|
const { parsedRealmJson, keycloakMajorVersionNumber, buildContext } = params;
|
||||||
|
|
||||||
|
const { username } = addOrEditTestUser({
|
||||||
|
parsedRealmJson,
|
||||||
|
keycloakMajorVersionNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
const { clientId } = addOrEditClient({
|
||||||
|
parsedRealmJson,
|
||||||
|
keycloakMajorVersionNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
editAccountConsoleAndSecurityAdminConsole({ parsedRealmJson });
|
||||||
|
|
||||||
|
enableCustomThemes({
|
||||||
|
parsedRealmJson,
|
||||||
|
themeName: buildContext.themeNames[0],
|
||||||
|
implementedThemeTypes: buildContext.implementedThemeTypes
|
||||||
|
});
|
||||||
|
|
||||||
|
enable_custom_events_listeners: {
|
||||||
|
const name = "keycloakify-logging";
|
||||||
|
|
||||||
|
if (parsedRealmJson.eventsListeners.includes(name)) {
|
||||||
|
break enable_custom_events_listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedRealmJson.eventsListeners.push(name);
|
||||||
|
|
||||||
|
parsedRealmJson.eventsListeners.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
realmName: parsedRealmJson.realm,
|
||||||
|
clientName: clientId,
|
||||||
|
username
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableCustomThemes(params: {
|
||||||
|
parsedRealmJson: ParsedRealmJson;
|
||||||
|
themeName: string;
|
||||||
|
implementedThemeTypes: BuildContextLike["implementedThemeTypes"];
|
||||||
|
}) {
|
||||||
|
const { parsedRealmJson, themeName, implementedThemeTypes } = params;
|
||||||
|
|
||||||
|
for (const themeType of objectKeys(implementedThemeTypes)) {
|
||||||
|
if (!implementedThemeTypes[themeType].isImplemented) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedRealmJson[`${themeType}Theme` as const] = themeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOrEditTestUser(params: {
|
||||||
|
parsedRealmJson: ParsedRealmJson;
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
}): { username: string } {
|
||||||
|
const { parsedRealmJson, keycloakMajorVersionNumber } = params;
|
||||||
|
|
||||||
|
const parsedRealmJson_default = getDefaultConfig({ keycloakMajorVersionNumber });
|
||||||
|
|
||||||
|
const [defaultUser_default] = parsedRealmJson_default.users;
|
||||||
|
|
||||||
|
assert(defaultUser_default !== undefined);
|
||||||
|
|
||||||
|
const defaultUser_preexisting = parsedRealmJson.users.find(
|
||||||
|
user => user.username === defaultUser_default.username
|
||||||
|
);
|
||||||
|
|
||||||
|
const newUser = structuredClone(
|
||||||
|
defaultUser_preexisting ??
|
||||||
|
(() => {
|
||||||
|
const firstUser = parsedRealmJson.users[0];
|
||||||
|
|
||||||
|
if (firstUser === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstUserCopy = structuredClone(firstUser);
|
||||||
|
|
||||||
|
firstUserCopy.id = defaultUser_default.id;
|
||||||
|
|
||||||
|
return firstUserCopy;
|
||||||
|
})() ??
|
||||||
|
defaultUser_default
|
||||||
|
);
|
||||||
|
|
||||||
|
newUser.username = defaultUser_default.username;
|
||||||
|
newUser.email = defaultUser_default.email;
|
||||||
|
|
||||||
|
delete_existing_password_credential_if_any: {
|
||||||
|
const i = newUser.credentials.findIndex(
|
||||||
|
credential => credential.type === "password"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (i === -1) {
|
||||||
|
break delete_existing_password_credential_if_any;
|
||||||
|
}
|
||||||
|
|
||||||
|
newUser.credentials.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const credential = defaultUser_default.credentials.find(
|
||||||
|
credential => credential.type === "password"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(credential !== undefined);
|
||||||
|
|
||||||
|
newUser.credentials.push(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const nameByClientId = Object.fromEntries(
|
||||||
|
parsedRealmJson.clients.map(client => [client.id, client.clientId] as const)
|
||||||
|
);
|
||||||
|
|
||||||
|
const newClientRoles: NonNullable<
|
||||||
|
ParsedRealmJson["users"][number]["clientRoles"]
|
||||||
|
> = {};
|
||||||
|
|
||||||
|
for (const clientRole of Object.values(parsedRealmJson.roles.client).flat()) {
|
||||||
|
const clientName = nameByClientId[clientRole.containerId];
|
||||||
|
|
||||||
|
assert(clientName !== undefined);
|
||||||
|
|
||||||
|
(newClientRoles[clientName] ??= []).push(clientRole.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { same: sameSet } = sameFactory({
|
||||||
|
takeIntoAccountArraysOrdering: false
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const [clientName, roles] of Object.entries(newClientRoles)) {
|
||||||
|
keep_previous_ordering_if_possible: {
|
||||||
|
const roles_previous = newUser.clientRoles?.[clientName];
|
||||||
|
|
||||||
|
if (roles_previous === undefined) {
|
||||||
|
break keep_previous_ordering_if_possible;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sameSet(roles_previous, roles)) {
|
||||||
|
break keep_previous_ordering_if_possible;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
(newUser.clientRoles ??= {})[clientName] = roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultUser_preexisting === undefined) {
|
||||||
|
parsedRealmJson.users.push(newUser);
|
||||||
|
} else {
|
||||||
|
const i = parsedRealmJson.users.indexOf(defaultUser_preexisting);
|
||||||
|
assert(i !== -1);
|
||||||
|
parsedRealmJson.users[i] = newUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { username: newUser.username };
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOrEditClient(params: {
|
||||||
|
parsedRealmJson: ParsedRealmJson;
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
}): { clientId: string } {
|
||||||
|
const { parsedRealmJson, keycloakMajorVersionNumber } = params;
|
||||||
|
|
||||||
|
const parsedRealmJson_default = getDefaultConfig({ keycloakMajorVersionNumber });
|
||||||
|
|
||||||
|
const testClient_default = (() => {
|
||||||
|
const clients = parsedRealmJson_default.clients.filter(client => {
|
||||||
|
return JSON.stringify(client).includes(TEST_APP_URL);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(clients.length === 1);
|
||||||
|
|
||||||
|
return clients[0];
|
||||||
|
})();
|
||||||
|
|
||||||
|
const clientIds_builtIn = parsedRealmJson_default.clients
|
||||||
|
.map(client => client.clientId)
|
||||||
|
.filter(clientId => clientId !== testClient_default.clientId);
|
||||||
|
|
||||||
|
const testClient_preexisting = (() => {
|
||||||
|
const clients = parsedRealmJson.clients
|
||||||
|
.filter(client => !clientIds_builtIn.includes(client.clientId))
|
||||||
|
.filter(client => client.protocol === "openid-connect");
|
||||||
|
|
||||||
|
{
|
||||||
|
const client = clients.find(
|
||||||
|
client => client.clientId === testClient_default.clientId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (client !== undefined) {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const client = clients.find(
|
||||||
|
client =>
|
||||||
|
client.redirectUris?.find(redirectUri =>
|
||||||
|
redirectUri.startsWith(TEST_APP_URL)
|
||||||
|
) !== undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
if (client !== undefined) {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [client] = clients;
|
||||||
|
|
||||||
|
if (client === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return client;
|
||||||
|
})();
|
||||||
|
|
||||||
|
let testClient: typeof testClient_default;
|
||||||
|
|
||||||
|
if (testClient_preexisting !== undefined) {
|
||||||
|
testClient = testClient_preexisting;
|
||||||
|
} else {
|
||||||
|
testClient = structuredClone(testClient_default);
|
||||||
|
delete testClient.protocolMappers;
|
||||||
|
parsedRealmJson.clients.push(testClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
testClient.redirectUris = [
|
||||||
|
`${TEST_APP_URL}/*`,
|
||||||
|
"http://localhost*",
|
||||||
|
"http://127.0.0.1*"
|
||||||
|
]
|
||||||
|
.sort()
|
||||||
|
.reverse();
|
||||||
|
|
||||||
|
(testClient.attributes ??= {})["post.logout.redirect.uris"] = "+";
|
||||||
|
|
||||||
|
testClient.webOrigins = ["*"];
|
||||||
|
|
||||||
|
return { clientId: testClient.clientId };
|
||||||
|
}
|
||||||
|
|
||||||
|
function editAccountConsoleAndSecurityAdminConsole(params: {
|
||||||
|
parsedRealmJson: ParsedRealmJson;
|
||||||
|
}) {
|
||||||
|
const { parsedRealmJson } = params;
|
||||||
|
|
||||||
|
for (const clientId of ["account-console", "security-admin-console"]) {
|
||||||
|
const client = parsedRealmJson.clients.find(
|
||||||
|
client => client.clientId === clientId
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(client !== undefined);
|
||||||
|
|
||||||
|
{
|
||||||
|
const arr = (client.redirectUris ??= []);
|
||||||
|
|
||||||
|
for (const value of ["http://localhost*", "http://127.0.0.1*"]) {
|
||||||
|
if (!arr.includes(value)) {
|
||||||
|
arr.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.redirectUris?.sort().reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
(client.attributes ??= {})["post.logout.redirect.uris"] = "+";
|
||||||
|
|
||||||
|
client.webOrigins = ["*"];
|
||||||
|
}
|
||||||
|
}
|
151
src/bin/start-keycloak/realmConfig/realmConfig.ts
Normal file
151
src/bin/start-keycloak/realmConfig/realmConfig.ts
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import { runPrettier, getIsPrettierAvailable } from "../../tools/runPrettier";
|
||||||
|
import { getDefaultConfig } from "./defaultConfig";
|
||||||
|
import {
|
||||||
|
prepareRealmConfig,
|
||||||
|
type BuildContextLike as BuildContextLike_prepareRealmConfig
|
||||||
|
} from "./prepareRealmConfig";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import {
|
||||||
|
join as pathJoin,
|
||||||
|
dirname as pathDirname,
|
||||||
|
relative as pathRelative,
|
||||||
|
sep as pathSep
|
||||||
|
} from "path";
|
||||||
|
import { existsAsync } from "../../tools/fs.existsAsync";
|
||||||
|
import { readRealmJsonFile, type ParsedRealmJson } from "./ParsedRealmJson";
|
||||||
|
import {
|
||||||
|
dumpContainerConfig,
|
||||||
|
type BuildContextLike as BuildContextLike_dumpContainerConfig
|
||||||
|
} from "./dumpContainerConfig";
|
||||||
|
import * as runExclusive from "run-exclusive";
|
||||||
|
import { waitForDebounceFactory } from "powerhooks/tools/waitForDebounce";
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
|
export type BuildContextLike = BuildContextLike_dumpContainerConfig &
|
||||||
|
BuildContextLike_prepareRealmConfig & {
|
||||||
|
projectDirPath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>;
|
||||||
|
|
||||||
|
export async function getRealmConfig(params: {
|
||||||
|
keycloakMajorVersionNumber: number;
|
||||||
|
realmJsonFilePath_userProvided: string | undefined;
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}): Promise<{
|
||||||
|
realmJsonFilePath: string;
|
||||||
|
clientName: string;
|
||||||
|
realmName: string;
|
||||||
|
username: string;
|
||||||
|
onRealmConfigChange: () => Promise<void>;
|
||||||
|
}> {
|
||||||
|
const { keycloakMajorVersionNumber, realmJsonFilePath_userProvided, buildContext } =
|
||||||
|
params;
|
||||||
|
|
||||||
|
const realmJsonFilePath = pathJoin(
|
||||||
|
buildContext.projectDirPath,
|
||||||
|
".keycloakify",
|
||||||
|
`realm-kc-${keycloakMajorVersionNumber}.json`
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsedRealmJson = await (async () => {
|
||||||
|
if (realmJsonFilePath_userProvided !== undefined) {
|
||||||
|
return readRealmJsonFile({
|
||||||
|
realmJsonFilePath: realmJsonFilePath_userProvided
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await existsAsync(realmJsonFilePath)) {
|
||||||
|
return readRealmJsonFile({
|
||||||
|
realmJsonFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDefaultConfig({ keycloakMajorVersionNumber });
|
||||||
|
})();
|
||||||
|
|
||||||
|
const { clientName, realmName, username } = prepareRealmConfig({
|
||||||
|
parsedRealmJson,
|
||||||
|
buildContext,
|
||||||
|
keycloakMajorVersionNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
const dirPath = pathDirname(realmJsonFilePath);
|
||||||
|
|
||||||
|
if (!(await existsAsync(dirPath))) {
|
||||||
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeRealmJsonFile = async (params: { parsedRealmJson: ParsedRealmJson }) => {
|
||||||
|
const { parsedRealmJson } = params;
|
||||||
|
|
||||||
|
let sourceCode = JSON.stringify(parsedRealmJson, null, 2);
|
||||||
|
|
||||||
|
if (await getIsPrettierAvailable()) {
|
||||||
|
sourceCode = await runPrettier({
|
||||||
|
sourceCode,
|
||||||
|
filePath: realmJsonFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(realmJsonFilePath, sourceCode);
|
||||||
|
};
|
||||||
|
|
||||||
|
await writeRealmJsonFile({ parsedRealmJson });
|
||||||
|
|
||||||
|
const { onRealmConfigChange } = (() => {
|
||||||
|
const run = runExclusive.build(async () => {
|
||||||
|
const start = Date.now();
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
chalk.grey(`Changes detected to the '${realmName}' config, backing up...`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const parsedRealmJson = await dumpContainerConfig({
|
||||||
|
buildContext,
|
||||||
|
realmName,
|
||||||
|
keycloakMajorVersionNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
await writeRealmJsonFile({ parsedRealmJson });
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
[
|
||||||
|
chalk.grey(
|
||||||
|
`Save changed to \`.${pathSep}${pathRelative(buildContext.projectDirPath, realmJsonFilePath)}\``
|
||||||
|
),
|
||||||
|
chalk.grey(
|
||||||
|
`Next time you'll be running \`keycloakify start-keycloak\`, the realm '${realmName}' will be restored to this state.`
|
||||||
|
),
|
||||||
|
chalk.green(
|
||||||
|
`✓ '${realmName}' config backed up completed in ${Date.now() - start}ms`
|
||||||
|
)
|
||||||
|
].join("\n")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const { waitForDebounce } = waitForDebounceFactory({
|
||||||
|
delay: 1_000
|
||||||
|
});
|
||||||
|
|
||||||
|
async function onRealmConfigChange() {
|
||||||
|
await waitForDebounce();
|
||||||
|
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { onRealmConfigChange };
|
||||||
|
})();
|
||||||
|
|
||||||
|
return {
|
||||||
|
realmJsonFilePath,
|
||||||
|
clientName,
|
||||||
|
realmName,
|
||||||
|
username,
|
||||||
|
onRealmConfigChange
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +1,11 @@
|
|||||||
import type { BuildContext } from "../shared/buildContext";
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
import { exclude } from "tsafe/exclude";
|
import { exclude } from "tsafe/exclude";
|
||||||
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
|
import {
|
||||||
import { CONTAINER_NAME } from "../shared/constants";
|
CONTAINER_NAME,
|
||||||
|
KEYCLOAKIFY_SPA_DEV_SERVER_PORT,
|
||||||
|
KEYCLOAKIFY_LOGIN_JAR_BASENAME,
|
||||||
|
TEST_APP_URL
|
||||||
|
} from "../shared/constants";
|
||||||
import { SemVer } from "../tools/SemVer";
|
import { SemVer } from "../tools/SemVer";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
@ -9,8 +13,7 @@ import {
|
|||||||
join as pathJoin,
|
join as pathJoin,
|
||||||
relative as pathRelative,
|
relative as pathRelative,
|
||||||
sep as pathSep,
|
sep as pathSep,
|
||||||
basename as pathBasename,
|
basename as pathBasename
|
||||||
dirname as pathDirname
|
|
||||||
} from "path";
|
} from "path";
|
||||||
import * as child_process from "child_process";
|
import * as child_process from "child_process";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
@ -27,6 +30,10 @@ import { isInside } from "../tools/isInside";
|
|||||||
import { existsAsync } from "../tools/fs.existsAsync";
|
import { existsAsync } from "../tools/fs.existsAsync";
|
||||||
import { rm } from "../tools/fs.rm";
|
import { rm } from "../tools/fs.rm";
|
||||||
import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive";
|
import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive";
|
||||||
|
import { startViteDevServer } from "./startViteDevServer";
|
||||||
|
import { getSupportedKeycloakMajorVersions } from "./realmConfig/defaultConfig";
|
||||||
|
import { getSupportedDockerImageTags } from "./getSupportedDockerImageTags";
|
||||||
|
import { getRealmConfig } from "./realmConfig";
|
||||||
|
|
||||||
export async function command(params: {
|
export async function command(params: {
|
||||||
buildContext: BuildContext;
|
buildContext: BuildContext;
|
||||||
@ -90,9 +97,32 @@ export async function command(params: {
|
|||||||
|
|
||||||
const { cliCommandOptions, buildContext } = params;
|
const { cliCommandOptions, buildContext } = params;
|
||||||
|
|
||||||
|
const availableTags = await getSupportedDockerImageTags({
|
||||||
|
buildContext
|
||||||
|
});
|
||||||
|
|
||||||
const { dockerImageTag } = await (async () => {
|
const { dockerImageTag } = await (async () => {
|
||||||
if (cliCommandOptions.keycloakVersion !== undefined) {
|
if (cliCommandOptions.keycloakVersion !== undefined) {
|
||||||
return { dockerImageTag: cliCommandOptions.keycloakVersion };
|
const cliCommandOptions_keycloakVersion = cliCommandOptions.keycloakVersion;
|
||||||
|
|
||||||
|
const tag = availableTags.find(tag =>
|
||||||
|
tag.startsWith(cliCommandOptions_keycloakVersion)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tag === undefined) {
|
||||||
|
console.log(
|
||||||
|
chalk.red(
|
||||||
|
[
|
||||||
|
`We could not find a Keycloak Docker image for ${cliCommandOptions_keycloakVersion}`,
|
||||||
|
`Example of valid values: --keycloak-version 26, --keycloak-version 26.0.7`
|
||||||
|
].join("\n")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { dockerImageTag: tag };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildContext.startKeycloakOptions.dockerImage !== undefined) {
|
if (buildContext.startKeycloakOptions.dockerImage !== undefined) {
|
||||||
@ -107,50 +137,84 @@ export async function command(params: {
|
|||||||
"On which version of Keycloak do you want to test your theme?"
|
"On which version of Keycloak do you want to test your theme?"
|
||||||
),
|
),
|
||||||
chalk.gray(
|
chalk.gray(
|
||||||
"You can also explicitly provide the version with `npx keycloakify start-keycloak --keycloak-version 25.0.2` (or any other version)"
|
"You can also explicitly provide the version with `npx keycloakify start-keycloak --keycloak-version 26` (or any other version)"
|
||||||
)
|
)
|
||||||
].join("\n")
|
].join("\n")
|
||||||
);
|
);
|
||||||
|
|
||||||
const { keycloakVersion } = await promptKeycloakVersion({
|
const { value: tag } = await cliSelect<string>({
|
||||||
startingFromMajor: 18,
|
values: availableTags
|
||||||
excludeMajorVersions: [22],
|
}).catch(() => {
|
||||||
doOmitPatch: true,
|
process.exit(-1);
|
||||||
buildContext
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`→ ${keycloakVersion}`);
|
console.log(`→ ${tag}`);
|
||||||
|
|
||||||
return { dockerImageTag: keycloakVersion };
|
return { dockerImageTag: tag };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const keycloakMajorVersionNumber = (() => {
|
const keycloakMajorVersionNumber = (() => {
|
||||||
if (buildContext.startKeycloakOptions.dockerImage === undefined) {
|
const [wrap] = getSupportedKeycloakMajorVersions()
|
||||||
return SemVer.parse(dockerImageTag).major;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { tag } = buildContext.startKeycloakOptions.dockerImage;
|
|
||||||
|
|
||||||
const [wrap] = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
|
|
||||||
.map(majorVersionNumber => ({
|
.map(majorVersionNumber => ({
|
||||||
majorVersionNumber,
|
majorVersionNumber,
|
||||||
index: tag.indexOf(`${majorVersionNumber}`)
|
index: dockerImageTag.indexOf(`${majorVersionNumber}`)
|
||||||
}))
|
}))
|
||||||
.filter(({ index }) => index !== -1)
|
.filter(({ index }) => index !== -1)
|
||||||
.sort((a, b) => a.index - b.index);
|
.sort((a, b) => a.index - b.index);
|
||||||
|
|
||||||
if (wrap === undefined) {
|
if (wrap === undefined) {
|
||||||
console.warn(
|
try {
|
||||||
chalk.yellow(
|
const version = SemVer.parse(dockerImageTag);
|
||||||
`Could not determine the major Keycloak version number from the docker image tag ${tag}. Assuming 25`
|
|
||||||
)
|
console.error(
|
||||||
);
|
chalk.yellow(
|
||||||
return 25;
|
`Keycloak version ${version.major} is not supported, supported versions are ${getSupportedKeycloakMajorVersions().join(", ")}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
} catch {
|
||||||
|
// NOTE: Latest version
|
||||||
|
const [n] = getSupportedKeycloakMajorVersions();
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
chalk.yellow(
|
||||||
|
`Could not determine the major Keycloak version number from the docker image tag ${dockerImageTag}. Assuming ${n}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrap.majorVersionNumber;
|
return wrap.majorVersionNumber;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const { clientName, onRealmConfigChange, realmJsonFilePath, realmName, username } =
|
||||||
|
await getRealmConfig({
|
||||||
|
keycloakMajorVersionNumber,
|
||||||
|
realmJsonFilePath_userProvided: await (async () => {
|
||||||
|
if (cliCommandOptions.realmJsonFilePath !== undefined) {
|
||||||
|
return getAbsoluteAndInOsFormatPath({
|
||||||
|
pathIsh: cliCommandOptions.realmJsonFilePath,
|
||||||
|
cwd: process.cwd()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildContext.startKeycloakOptions.realmJsonFilePath !== undefined) {
|
||||||
|
assert(
|
||||||
|
await existsAsync(
|
||||||
|
buildContext.startKeycloakOptions.realmJsonFilePath
|
||||||
|
),
|
||||||
|
`${pathRelative(process.cwd(), buildContext.startKeycloakOptions.realmJsonFilePath)} does not exist`
|
||||||
|
);
|
||||||
|
return buildContext.startKeycloakOptions.realmJsonFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
})(),
|
||||||
|
buildContext
|
||||||
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
const { isAppBuildSuccess } = await appBuild({
|
const { isAppBuildSuccess } = await appBuild({
|
||||||
buildContext
|
buildContext
|
||||||
@ -188,154 +252,48 @@ export async function command(params: {
|
|||||||
|
|
||||||
assert(jarFilePath !== undefined);
|
assert(jarFilePath !== undefined);
|
||||||
|
|
||||||
const extensionJarFilePaths = await Promise.all(
|
const extensionJarFilePaths = [
|
||||||
buildContext.startKeycloakOptions.extensionJars.map(async extensionJar => {
|
...(keycloakMajorVersionNumber <= 20
|
||||||
switch (extensionJar.type) {
|
? (console.log(
|
||||||
case "path": {
|
chalk.yellow(
|
||||||
assert(
|
"WARNING: With older version of keycloak your changes to the realm configuration are not persisted"
|
||||||
await existsAsync(extensionJar.path),
|
)
|
||||||
`${extensionJar.path} does not exist`
|
),
|
||||||
);
|
[])
|
||||||
return extensionJar.path;
|
: [
|
||||||
|
pathJoin(
|
||||||
|
getThisCodebaseRootDirPath(),
|
||||||
|
"src",
|
||||||
|
"bin",
|
||||||
|
"start-keycloak",
|
||||||
|
KEYCLOAKIFY_LOGIN_JAR_BASENAME
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
...(await Promise.all(
|
||||||
|
buildContext.startKeycloakOptions.extensionJars.map(async extensionJar => {
|
||||||
|
switch (extensionJar.type) {
|
||||||
|
case "path": {
|
||||||
|
assert(
|
||||||
|
await existsAsync(extensionJar.path),
|
||||||
|
`${extensionJar.path} does not exist`
|
||||||
|
);
|
||||||
|
return extensionJar.path;
|
||||||
|
}
|
||||||
|
case "url": {
|
||||||
|
const { archiveFilePath } = await downloadAndExtractArchive({
|
||||||
|
cacheDirPath: buildContext.cacheDirPath,
|
||||||
|
fetchOptions: buildContext.fetchOptions,
|
||||||
|
url: extensionJar.url,
|
||||||
|
uniqueIdOfOnArchiveFile: "no extraction",
|
||||||
|
onArchiveFile: async () => {}
|
||||||
|
});
|
||||||
|
return archiveFilePath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case "url": {
|
assert<Equals<typeof extensionJar, never>>(false);
|
||||||
const { archiveFilePath } = await downloadAndExtractArchive({
|
})
|
||||||
cacheDirPath: buildContext.cacheDirPath,
|
))
|
||||||
fetchOptions: buildContext.fetchOptions,
|
];
|
||||||
url: extensionJar.url,
|
|
||||||
uniqueIdOfOnArchiveFile: "no extraction",
|
|
||||||
onArchiveFile: async () => {}
|
|
||||||
});
|
|
||||||
return archiveFilePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert<Equals<typeof extensionJar, never>>(false);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const getRealmJsonFilePath_defaultForKeycloakMajor = (
|
|
||||||
keycloakMajorVersionNumber: number
|
|
||||||
) =>
|
|
||||||
pathJoin(
|
|
||||||
getThisCodebaseRootDirPath(),
|
|
||||||
"src",
|
|
||||||
"bin",
|
|
||||||
"start-keycloak",
|
|
||||||
`myrealm-realm-${keycloakMajorVersionNumber}.json`
|
|
||||||
);
|
|
||||||
|
|
||||||
const realmJsonFilePath = await (async () => {
|
|
||||||
if (cliCommandOptions.realmJsonFilePath !== undefined) {
|
|
||||||
if (cliCommandOptions.realmJsonFilePath === "none") {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return getAbsoluteAndInOsFormatPath({
|
|
||||||
pathIsh: cliCommandOptions.realmJsonFilePath,
|
|
||||||
cwd: process.cwd()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildContext.startKeycloakOptions.realmJsonFilePath !== undefined) {
|
|
||||||
assert(
|
|
||||||
await existsAsync(buildContext.startKeycloakOptions.realmJsonFilePath),
|
|
||||||
`${pathRelative(process.cwd(), buildContext.startKeycloakOptions.realmJsonFilePath)} does not exist`
|
|
||||||
);
|
|
||||||
return buildContext.startKeycloakOptions.realmJsonFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const internalFilePath = await (async () => {
|
|
||||||
const defaultFilePath = getRealmJsonFilePath_defaultForKeycloakMajor(
|
|
||||||
keycloakMajorVersionNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fs.existsSync(defaultFilePath)) {
|
|
||||||
return defaultFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`${chalk.yellow(
|
|
||||||
`Keycloakify do not have a realm configuration for Keycloak ${keycloakMajorVersionNumber} yet.`
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(chalk.cyan("Select what configuration to use:"));
|
|
||||||
|
|
||||||
const dirPath = pathDirname(defaultFilePath);
|
|
||||||
|
|
||||||
const { value } = await cliSelect<string>({
|
|
||||||
values: [
|
|
||||||
...fs
|
|
||||||
.readdirSync(dirPath)
|
|
||||||
.filter(fileBasename => fileBasename.endsWith(".json")),
|
|
||||||
"none"
|
|
||||||
]
|
|
||||||
}).catch(() => {
|
|
||||||
process.exit(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (value === "none") {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pathJoin(dirPath, value);
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (internalFilePath === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const filePath = pathJoin(
|
|
||||||
buildContext.cacheDirPath,
|
|
||||||
pathBasename(internalFilePath)
|
|
||||||
);
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
filePath,
|
|
||||||
Buffer.from(
|
|
||||||
fs
|
|
||||||
.readFileSync(internalFilePath)
|
|
||||||
.toString("utf8")
|
|
||||||
.replace(/keycloakify\-starter/g, buildContext.themeNames[0])
|
|
||||||
),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
|
|
||||||
return filePath;
|
|
||||||
})();
|
|
||||||
|
|
||||||
add_test_user_if_missing: {
|
|
||||||
if (realmJsonFilePath === undefined) {
|
|
||||||
break add_test_user_if_missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
const realm: Record<string, unknown> = JSON.parse(
|
|
||||||
fs.readFileSync(realmJsonFilePath).toString("utf8")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (realm.users !== undefined) {
|
|
||||||
break add_test_user_if_missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
const realmJsonFilePath_internal = (() => {
|
|
||||||
const filePath = getRealmJsonFilePath_defaultForKeycloakMajor(
|
|
||||||
keycloakMajorVersionNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
return getRealmJsonFilePath_defaultForKeycloakMajor(25);
|
|
||||||
}
|
|
||||||
|
|
||||||
return filePath;
|
|
||||||
})();
|
|
||||||
|
|
||||||
const users = JSON.parse(
|
|
||||||
fs.readFileSync(realmJsonFilePath_internal).toString("utf8")
|
|
||||||
).users;
|
|
||||||
|
|
||||||
realm.users = users;
|
|
||||||
|
|
||||||
fs.writeFileSync(realmJsonFilePath, JSON.stringify(realm, null, 2), "utf8");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function extractThemeResourcesFromJar() {
|
async function extractThemeResourcesFromJar() {
|
||||||
await extractArchive({
|
await extractArchive({
|
||||||
@ -375,17 +333,76 @@ export async function command(params: {
|
|||||||
});
|
});
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
const DEFAULT_PORT = 8080;
|
const port = cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? 8080;
|
||||||
const port =
|
|
||||||
cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT;
|
const doStartDevServer = (() => {
|
||||||
|
const hasSpaUi =
|
||||||
|
buildContext.implementedThemeTypes.admin.isImplemented ||
|
||||||
|
(buildContext.implementedThemeTypes.account.isImplemented &&
|
||||||
|
buildContext.implementedThemeTypes.account.type === "Single-Page");
|
||||||
|
|
||||||
|
if (!hasSpaUi) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildContext.bundler !== "vite") {
|
||||||
|
console.log(
|
||||||
|
chalk.yellow(
|
||||||
|
[
|
||||||
|
`WARNING: Since you are using ${buildContext.bundler} instead of Vite,`,
|
||||||
|
`you'll have to wait serval seconds for the changes you made on your account or admin theme to be reflected in the browser.\n`,
|
||||||
|
`For a better development experience, consider migrating to Vite.`
|
||||||
|
].join(" ")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycloakMajorVersionNumber < 25) {
|
||||||
|
console.log(
|
||||||
|
chalk.yellow(
|
||||||
|
[
|
||||||
|
`WARNING: Your account or admin theme can't be tested with hot module replacement on Keycloak ${keycloakMajorVersionNumber}.`,
|
||||||
|
`This mean that you'll have to wait serval seconds for the changes to be reflected in the browser.`,
|
||||||
|
`For a better development experience, select a more recent version of Keycloak.`
|
||||||
|
].join("\n")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})();
|
||||||
|
|
||||||
|
let devServerPort: number | undefined = undefined;
|
||||||
|
|
||||||
|
if (doStartDevServer) {
|
||||||
|
const { port } = await startViteDevServer({ buildContext });
|
||||||
|
|
||||||
|
devServerPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
const SPACE_PLACEHOLDER = "SPACE_PLACEHOLDER_xKLmdPd";
|
const SPACE_PLACEHOLDER = "SPACE_PLACEHOLDER_xKLmdPd";
|
||||||
|
|
||||||
const dockerRunArgs: string[] = [
|
const dockerRunArgs: string[] = [
|
||||||
`-p${SPACE_PLACEHOLDER}${port}:8080`,
|
`-p${SPACE_PLACEHOLDER}${port}:8080`,
|
||||||
`--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`,
|
`--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`,
|
||||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`,
|
...(keycloakMajorVersionNumber >= 26
|
||||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`,
|
? [
|
||||||
|
`-e${SPACE_PLACEHOLDER}KC_BOOTSTRAP_ADMIN_USERNAME=admin`,
|
||||||
|
`-e${SPACE_PLACEHOLDER}KC_BOOTSTRAP_ADMIN_PASSWORD=admin`
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`,
|
||||||
|
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`
|
||||||
|
]),
|
||||||
|
...(devServerPort === undefined
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
`-e${SPACE_PLACEHOLDER}${KEYCLOAKIFY_SPA_DEV_SERVER_PORT}=${devServerPort}`
|
||||||
|
]),
|
||||||
...(buildContext.startKeycloakOptions.dockerExtraArgs.length === 0
|
...(buildContext.startKeycloakOptions.dockerExtraArgs.length === 0
|
||||||
? []
|
? []
|
||||||
: [
|
: [
|
||||||
@ -396,7 +413,7 @@ export async function command(params: {
|
|||||||
...(realmJsonFilePath === undefined
|
...(realmJsonFilePath === undefined
|
||||||
? []
|
? []
|
||||||
: [
|
: [
|
||||||
`-v${SPACE_PLACEHOLDER}"${realmJsonFilePath}":/opt/keycloak/data/import/myrealm-realm.json`
|
`-v${SPACE_PLACEHOLDER}"${realmJsonFilePath}":/opt/keycloak/data/import/${realmName}-realm.json`
|
||||||
]),
|
]),
|
||||||
`-v${SPACE_PLACEHOLDER}"${jarFilePath_cacheDir}":/opt/keycloak/providers/keycloak-theme.jar`,
|
`-v${SPACE_PLACEHOLDER}"${jarFilePath_cacheDir}":/opt/keycloak/providers/keycloak-theme.jar`,
|
||||||
...extensionJarFilePaths.map(
|
...extensionJarFilePaths.map(
|
||||||
@ -471,7 +488,14 @@ export async function command(params: {
|
|||||||
{ shell: true }
|
{ shell: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
child.stdout.on("data", data => process.stdout.write(data));
|
child.stdout.on("data", async data => {
|
||||||
|
if (data.toString("utf8").includes("keycloakify-logging: REALM_CONFIG_CHANGED")) {
|
||||||
|
await onRealmConfigChange();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process.stdout.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
child.stderr.on("data", data => process.stderr.write(data));
|
child.stderr.on("data", data => process.stderr.write(data));
|
||||||
|
|
||||||
@ -518,9 +542,9 @@ export async function command(params: {
|
|||||||
`${chalk.green("Your theme is accessible at:")}`,
|
`${chalk.green("Your theme is accessible at:")}`,
|
||||||
`${chalk.green("➜")} ${chalk.cyan.bold(
|
`${chalk.green("➜")} ${chalk.cyan.bold(
|
||||||
(() => {
|
(() => {
|
||||||
const url = new URL("https://my-theme.keycloakify.dev");
|
const url = new URL(TEST_APP_URL);
|
||||||
|
|
||||||
if (port !== DEFAULT_PORT) {
|
if (port !== 8080) {
|
||||||
url.searchParams.set("port", `${port}`);
|
url.searchParams.set("port", `${port}`);
|
||||||
}
|
}
|
||||||
if (kcHttpRelativePath !== undefined) {
|
if (kcHttpRelativePath !== undefined) {
|
||||||
@ -529,13 +553,20 @@ export async function command(params: {
|
|||||||
kcHttpRelativePath
|
kcHttpRelativePath
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (realmName !== "myrealm") {
|
||||||
|
url.searchParams.set("realm", realmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientName !== "myclient") {
|
||||||
|
url.searchParams.set("client", clientName);
|
||||||
|
}
|
||||||
|
|
||||||
return url.href;
|
return url.href;
|
||||||
})()
|
})()
|
||||||
)}`,
|
)}`,
|
||||||
"",
|
"",
|
||||||
"You can login with the following credentials:",
|
"You can login with the following credentials:",
|
||||||
`- username: ${chalk.cyan.bold("testuser")}`,
|
`- username: ${chalk.cyan.bold(username)}`,
|
||||||
`- password: ${chalk.cyan.bold("password123")}`,
|
`- password: ${chalk.cyan.bold("password123")}`,
|
||||||
"",
|
"",
|
||||||
`Watching for changes in ${chalk.bold(
|
`Watching for changes in ${chalk.bold(
|
||||||
@ -592,6 +623,44 @@ export async function command(params: {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.on("all", async (...[, filePath]) => {
|
.on("all", async (...[, filePath]) => {
|
||||||
|
ignore_account_spa: {
|
||||||
|
const doImplementAccountSpa =
|
||||||
|
buildContext.implementedThemeTypes.account.isImplemented &&
|
||||||
|
buildContext.implementedThemeTypes.account.type === "Single-Page";
|
||||||
|
|
||||||
|
if (!doImplementAccountSpa) {
|
||||||
|
break ignore_account_spa;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isInside({
|
||||||
|
dirPath: pathJoin(buildContext.themeSrcDirPath, "account"),
|
||||||
|
filePath
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
break ignore_account_spa;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_admin: {
|
||||||
|
if (!buildContext.implementedThemeTypes.admin.isImplemented) {
|
||||||
|
break ignore_admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isInside({
|
||||||
|
dirPath: pathJoin(buildContext.themeSrcDirPath, "admin"),
|
||||||
|
filePath
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
break ignore_admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`Detected changes in ${filePath}`);
|
console.log(`Detected changes in ${filePath}`);
|
||||||
|
|
||||||
await waitForDebounce();
|
await waitForDebounce();
|
||||||
|
66
src/bin/start-keycloak/startViteDevServer.ts
Normal file
66
src/bin/start-keycloak/startViteDevServer.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import * as child_process from "child_process";
|
||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import type { BuildContext } from "../shared/buildContext";
|
||||||
|
import chalk from "chalk";
|
||||||
|
import { VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES } from "../shared/constants";
|
||||||
|
import { Deferred } from "evt/tools/Deferred";
|
||||||
|
|
||||||
|
export type BuildContextLike = {
|
||||||
|
projectDirPath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||||
|
|
||||||
|
export function startViteDevServer(params: {
|
||||||
|
buildContext: BuildContextLike;
|
||||||
|
}): Promise<{ port: number }> {
|
||||||
|
const { buildContext } = params;
|
||||||
|
|
||||||
|
console.log(chalk.blue(`$ npx vite dev`));
|
||||||
|
|
||||||
|
const child = child_process.spawn("npx", ["vite", "dev"], {
|
||||||
|
cwd: buildContext.projectDirPath,
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
[VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES.READ_KC_CONTEXT_FROM_URL]: "true"
|
||||||
|
},
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stdout.on("data", data => {
|
||||||
|
if (!data.toString("utf8").includes("[vite] hmr")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process.stdout.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on("data", data => process.stderr.write(data));
|
||||||
|
|
||||||
|
const dPort = new Deferred<number>();
|
||||||
|
|
||||||
|
{
|
||||||
|
const onData = (data: Buffer) => {
|
||||||
|
//Local: http://localhost:8083/
|
||||||
|
const match = data
|
||||||
|
.toString("utf8")
|
||||||
|
.match(/Local:\s*http:\/\/(?:localhost|127\.0\.0\.1):(\d+)\//);
|
||||||
|
|
||||||
|
if (match === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
child.stdout.off("data", onData);
|
||||||
|
|
||||||
|
const port = parseInt(match[1]);
|
||||||
|
|
||||||
|
assert(!isNaN(port));
|
||||||
|
|
||||||
|
dPort.resolve(port);
|
||||||
|
};
|
||||||
|
|
||||||
|
child.stdout.on("data", onData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dPort.pr.then(port => ({ port }));
|
||||||
|
}
|
@ -101,7 +101,7 @@ export async function runPrettier(params: {
|
|||||||
resolveConfig: true
|
resolveConfig: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ignored) {
|
if (ignored || inferredParser === null) {
|
||||||
return sourceCode;
|
return sourceCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ export async function runPrettier(params: {
|
|||||||
formattedSourceCode = await prettier.format(sourceCode, {
|
formattedSourceCode = await prettier.format(sourceCode, {
|
||||||
...config,
|
...config,
|
||||||
filePath,
|
filePath,
|
||||||
parser: inferredParser ?? undefined
|
parser: inferredParser
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -9,6 +9,16 @@ import { getIsPrettierAvailable, runPrettier } from "./tools/runPrettier";
|
|||||||
export async function command(params: { buildContext: BuildContext }) {
|
export async function command(params: { buildContext: BuildContext }) {
|
||||||
const { buildContext } = params;
|
const { buildContext } = params;
|
||||||
|
|
||||||
|
run_copy_assets_to_public: {
|
||||||
|
if (buildContext.bundler !== "webpack") {
|
||||||
|
break run_copy_assets_to_public;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { command } = await import("./copy-keycloak-resources-to-public");
|
||||||
|
|
||||||
|
await command({ buildContext });
|
||||||
|
}
|
||||||
|
|
||||||
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
||||||
commandName: "update-kc-gen",
|
commandName: "update-kc-gen",
|
||||||
buildContext
|
buildContext
|
||||||
@ -52,7 +62,12 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
2
|
2
|
||||||
)};`,
|
)};`,
|
||||||
``,
|
``,
|
||||||
`type KcContext =`,
|
`/**`,
|
||||||
|
` * NOTE: Do not import this type except maybe in your entrypoint. `,
|
||||||
|
` * If you need to import the KcContext import it either from src/login/KcContext.ts or src/account/KcContext.ts.`,
|
||||||
|
` * Depending on the theme type you are working on.`,
|
||||||
|
` */`,
|
||||||
|
`export type KcContext =`,
|
||||||
hasLoginTheme && ` | import("./login/KcContext").KcContext`,
|
hasLoginTheme && ` | import("./login/KcContext").KcContext`,
|
||||||
hasAccountTheme && ` | import("./account/KcContext").KcContext`,
|
hasAccountTheme && ` | import("./account/KcContext").KcContext`,
|
||||||
hasAdminTheme && ` | import("./admin/KcContext").KcContext`,
|
hasAdminTheme && ` | import("./admin/KcContext").KcContext`,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { lazy, Suspense } from "react";
|
import { lazy, Suspense } from "react";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
|
@ -33,7 +33,7 @@ export type KcContext =
|
|||||||
| KcContext.LoginResetPassword
|
| KcContext.LoginResetPassword
|
||||||
| KcContext.LoginVerifyEmail
|
| KcContext.LoginVerifyEmail
|
||||||
| KcContext.Terms
|
| KcContext.Terms
|
||||||
| KcContext.LoginDeviceVerifyUserCode
|
| KcContext.LoginOauth2DeviceVerifyUserCode
|
||||||
| KcContext.LoginOauthGrant
|
| KcContext.LoginOauthGrant
|
||||||
| KcContext.LoginOtp
|
| KcContext.LoginOtp
|
||||||
| KcContext.LoginUsername
|
| KcContext.LoginUsername
|
||||||
@ -277,7 +277,7 @@ export declare namespace KcContext {
|
|||||||
__localizationRealmOverridesTermsText?: string;
|
__localizationRealmOverridesTermsText?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LoginDeviceVerifyUserCode = Common & {
|
export type LoginOauth2DeviceVerifyUserCode = Common & {
|
||||||
pageId: "login-oauth2-device-verify-user-code.ftl";
|
pageId: "login-oauth2-device-verify-user-code.ftl";
|
||||||
url: {
|
url: {
|
||||||
oauth2DeviceVerificationAction: string;
|
oauth2DeviceVerificationAction: string;
|
||||||
|
@ -290,7 +290,7 @@ export const kcContextMocks = [
|
|||||||
...kcContextCommonMock,
|
...kcContextCommonMock,
|
||||||
pageId: "terms.ftl"
|
pageId: "terms.ftl"
|
||||||
}),
|
}),
|
||||||
id<KcContext.LoginDeviceVerifyUserCode>({
|
id<KcContext.LoginOauth2DeviceVerifyUserCode>({
|
||||||
...kcContextCommonMock,
|
...kcContextCommonMock,
|
||||||
pageId: "login-oauth2-device-verify-user-code.ftl",
|
pageId: "login-oauth2-device-verify-user-code.ftl",
|
||||||
url: loginUrl
|
url: loginUrl
|
||||||
|
@ -11,7 +11,6 @@ export type TemplateProps<KcContext, I18n> = {
|
|||||||
displayInfo?: boolean;
|
displayInfo?: boolean;
|
||||||
displayMessage?: boolean;
|
displayMessage?: boolean;
|
||||||
displayRequiredFields?: boolean;
|
displayRequiredFields?: boolean;
|
||||||
showAnotherWayIfPresent?: boolean;
|
|
||||||
headerNode: ReactNode;
|
headerNode: ReactNode;
|
||||||
socialProvidersNode?: ReactNode;
|
socialProvidersNode?: ReactNode;
|
||||||
infoNode?: ReactNode;
|
infoNode?: ReactNode;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useEffect, useReducer, Fragment } from "react";
|
import { useEffect, useReducer, Fragment } from "react";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { type FormAction, type FormFieldError } from "keycloakify/login/lib/useUserProfileForm";
|
import { type FormAction, type FormFieldError } from "keycloakify/login/lib/useUserProfileForm";
|
||||||
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { Attribute } from "keycloakify/login/KcContext";
|
import type { Attribute } from "keycloakify/login/KcContext";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "keycloakify/tools/Object.fromEntries";
|
import "keycloakify/tools/Object.fromEntries";
|
||||||
import { assert, is } from "tsafe/assert";
|
import { assert, is } from "tsafe/assert";
|
||||||
|
import { extractLastParenthesisContent } from "keycloakify/tools/extractLastParenthesisContent";
|
||||||
import messages_defaultSet_fallbackLanguage from "../messages_defaultSet/en";
|
import messages_defaultSet_fallbackLanguage from "../messages_defaultSet/en";
|
||||||
import { fetchMessages_defaultSet } from "../messages_defaultSet";
|
import { fetchMessages_defaultSet } from "../messages_defaultSet";
|
||||||
import type { KcContext } from "../../KcContext";
|
import type { KcContext } from "../../KcContext";
|
||||||
@ -168,12 +169,10 @@ export function createGetI18n<
|
|||||||
break from_server;
|
break from_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cspell: disable-next-line
|
const lastParenthesisContent = extractLastParenthesisContent(supportedEntry.label);
|
||||||
// from "Espagnol (Español)" we want to extract "Español"
|
|
||||||
const match = supportedEntry.label.match(/[^(]+\(([^)]+)\)/);
|
|
||||||
|
|
||||||
if (match !== null) {
|
if (lastParenthesisContent !== undefined) {
|
||||||
return match[1];
|
return lastParenthesisContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return supportedEntry.label;
|
return supportedEntry.label;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import type { GenericI18n_noJsx } from "../noJsx/GenericI18n_noJsx";
|
import type { GenericI18n_noJsx } from "../noJsx/GenericI18n_noJsx";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ export type I18nBuilder<
|
|||||||
}>
|
}>
|
||||||
) => I18nBuilder<
|
) => I18nBuilder<
|
||||||
ThemeName,
|
ThemeName,
|
||||||
MessageKey_themeDefined,
|
string extends MessageKey_themeDefined ? never : MessageKey_themeDefined,
|
||||||
LanguageTag_notInDefaultSet,
|
LanguageTag_notInDefaultSet,
|
||||||
ExcludedMethod | "withCustomTranslations"
|
ExcludedMethod | "withCustomTranslations"
|
||||||
>;
|
>;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { createGetI18n, type KcContextLike } from "../noJsx/getI18n";
|
import { createGetI18n, type KcContextLike } from "../noJsx/getI18n";
|
||||||
@ -47,11 +48,25 @@ export function createUseI18n<
|
|||||||
|
|
||||||
function renderHtmlString(params: { htmlString: string; msgKey: string }): JSX.Element {
|
function renderHtmlString(params: { htmlString: string; msgKey: string }): JSX.Element {
|
||||||
const { htmlString, msgKey } = params;
|
const { htmlString, msgKey } = params;
|
||||||
|
|
||||||
|
const htmlString_sanitized = kcSanitize(htmlString);
|
||||||
|
|
||||||
|
const Element = (() => {
|
||||||
|
if (htmlString_sanitized.includes("<") && htmlString_sanitized.includes(">")) {
|
||||||
|
for (const tagName of ["div", "section", "article", "ul", "ol"]) {
|
||||||
|
if (htmlString_sanitized.includes(`<${tagName}`)) {
|
||||||
|
return "div";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "span";
|
||||||
|
})();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Element
|
||||||
data-kc-msg={msgKey}
|
data-kc-msg={msgKey}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: kcSanitize(htmlString)
|
__html: htmlString_sanitized
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -83,7 +98,7 @@ export function createUseI18n<
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
add_style: {
|
add_style: {
|
||||||
const attributeName = "data-kc-i18n";
|
const attributeName = "data-kc-msg";
|
||||||
|
|
||||||
// Check if already exists in head
|
// Check if already exists in head
|
||||||
if (document.querySelector(`style[${attributeName}]`) !== null) {
|
if (document.querySelector(`style[${attributeName}]`) !== null) {
|
||||||
@ -92,7 +107,7 @@ export function createUseI18n<
|
|||||||
|
|
||||||
const styleElement = document.createElement("style");
|
const styleElement = document.createElement("style");
|
||||||
styleElement.attributes.setNamedItem(document.createAttribute(attributeName));
|
styleElement.attributes.setNamedItem(document.createAttribute(attributeName));
|
||||||
styleElement.textContent = `[data-kc-msg] { display: inline-block; }`;
|
styleElement.textContent = `div[${attributeName}] { display: inline-block; }`;
|
||||||
document.head.prepend(styleElement);
|
document.head.prepend(styleElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import * as reactlessApi from "./getUserProfileApi/index";
|
import * as reactlessApi from "./getUserProfileApi/index";
|
||||||
import type { PasswordPolicies, Attribute, Validators } from "keycloakify/login/KcContext";
|
import type { PasswordPolicies, Attribute, Validators } from "keycloakify/login/KcContext";
|
||||||
import { useEffect, useState, useMemo, Fragment } from "react";
|
import { useEffect, useState, useMemo, Fragment } from "react";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState, useEffect, useReducer } from "react";
|
import { useState, useEffect, useReducer } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
|
@ -52,28 +52,26 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>{msg("loginTotpManualStep3")}</p>
|
<p>{msg("loginTotpManualStep3")}</p>
|
||||||
<p>
|
<ul>
|
||||||
<ul>
|
<li id="kc-totp-type">
|
||||||
<li id="kc-totp-type">
|
{msg("loginTotpType")}: {msg(`loginTotp.${totp.policy.type}`)}
|
||||||
{msg("loginTotpType")}: {msg(`loginTotp.${totp.policy.type}`)}
|
</li>
|
||||||
|
<li id="kc-totp-algorithm">
|
||||||
|
{msg("loginTotpAlgorithm")}: {totp.policy.getAlgorithmKey()}
|
||||||
|
</li>
|
||||||
|
<li id="kc-totp-digits">
|
||||||
|
{msg("loginTotpDigits")}: {totp.policy.digits}
|
||||||
|
</li>
|
||||||
|
{totp.policy.type === "totp" ? (
|
||||||
|
<li id="kc-totp-period">
|
||||||
|
{msg("loginTotpInterval")}: {totp.policy.period}
|
||||||
</li>
|
</li>
|
||||||
<li id="kc-totp-algorithm">
|
) : (
|
||||||
{msg("loginTotpAlgorithm")}: {totp.policy.getAlgorithmKey()}
|
<li id="kc-totp-counter">
|
||||||
|
{msg("loginTotpCounter")}: {totp.policy.initialCounter}
|
||||||
</li>
|
</li>
|
||||||
<li id="kc-totp-digits">
|
)}
|
||||||
{msg("loginTotpDigits")}: {totp.policy.digits}
|
</ul>
|
||||||
</li>
|
|
||||||
{totp.policy.type === "totp" ? (
|
|
||||||
<li id="kc-totp-period">
|
|
||||||
{msg("loginTotpInterval")}: {totp.policy.period}
|
|
||||||
</li>
|
|
||||||
) : (
|
|
||||||
<li id="kc-totp-counter">
|
|
||||||
{msg("loginTotpCounter")}: {totp.policy.initialCounter}
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState, useEffect, useReducer } from "react";
|
import { useState, useEffect, useReducer } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useEffect, useReducer } from "react";
|
import { useEffect, useReducer } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { type TemplateProps, type ClassKey } from "keycloakify/login/TemplateProps";
|
import { type TemplateProps, type ClassKey } from "keycloakify/login/TemplateProps";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
|
5
src/tools/JSX.ts
Normal file
5
src/tools/JSX.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { ReactElement } from "react";
|
||||||
|
|
||||||
|
export namespace JSX {
|
||||||
|
export interface Element extends ReactElement<any, any> {}
|
||||||
|
}
|
43
src/tools/extractLastParenthesisContent.ts
Normal file
43
src/tools/extractLastParenthesisContent.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* "Hello (world)" => "world"
|
||||||
|
* "Hello (world) (foo)" => "foo"
|
||||||
|
* "Hello (world (foo))" => "world (foo)"
|
||||||
|
*/
|
||||||
|
export function extractLastParenthesisContent(str: string): string | undefined {
|
||||||
|
const chars: string[] = [];
|
||||||
|
|
||||||
|
for (const char of str) {
|
||||||
|
chars.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
const extractedChars: string[] = [];
|
||||||
|
let openingCount = 0;
|
||||||
|
|
||||||
|
loop_through_char: for (let i = chars.length - 1; i >= 0; i--) {
|
||||||
|
const char = chars[i];
|
||||||
|
|
||||||
|
if (i === chars.length - 1) {
|
||||||
|
if (char !== ")") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (char) {
|
||||||
|
case ")":
|
||||||
|
openingCount++;
|
||||||
|
break;
|
||||||
|
case "(":
|
||||||
|
if (openingCount === 0) {
|
||||||
|
return extractedChars.join("");
|
||||||
|
}
|
||||||
|
openingCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractedChars.unshift(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
@ -212,6 +212,73 @@ export function keycloakify(params: keycloakify.Params) {
|
|||||||
force: true
|
force: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
transformIndexHtml: html => {
|
||||||
|
const doReadKcContextFromUrl =
|
||||||
|
process.env.NODE_ENV === "development" &&
|
||||||
|
process.env[
|
||||||
|
VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES.READ_KC_CONTEXT_FROM_URL
|
||||||
|
] === "true";
|
||||||
|
|
||||||
|
if (!doReadKcContextFromUrl) {
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scriptContent = `
|
||||||
|
(()=>{
|
||||||
|
|
||||||
|
const kcContext = (()=>{
|
||||||
|
|
||||||
|
const paramName= "kcContext";
|
||||||
|
|
||||||
|
read_from_url_case: {
|
||||||
|
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
|
||||||
|
const paramValue = url.searchParams.get(paramName);
|
||||||
|
|
||||||
|
if( paramValue === null ){
|
||||||
|
break read_from_url_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
url.searchParams.delete(paramName);
|
||||||
|
|
||||||
|
window.history.replaceState({}, "", url);
|
||||||
|
|
||||||
|
const kcContext = JSON.parse(decodeURIComponent(paramValue));
|
||||||
|
|
||||||
|
sessionStorage.setItem(paramName, JSON.stringify(kcContext));
|
||||||
|
|
||||||
|
return kcContext;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
read_from_session_storage_case: {
|
||||||
|
|
||||||
|
const paramValue = sessionStorage.getItem(paramName);
|
||||||
|
|
||||||
|
if( paramValue === null ){
|
||||||
|
break read_from_session_storage_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(paramValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
if( kcContext === undefined ){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.kcContext = kcContext;
|
||||||
|
|
||||||
|
})();
|
||||||
|
`;
|
||||||
|
|
||||||
|
return html.replace(/<head>/, `<head><script>${scriptContent}</script>`);
|
||||||
}
|
}
|
||||||
} satisfies Plugin;
|
} satisfies Plugin;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ export const Default: Story = {
|
|||||||
render: () => (
|
render: () => (
|
||||||
<KcPageStory
|
<KcPageStory
|
||||||
kcContext={{
|
kcContext={{
|
||||||
|
messageHeader: "Message header",
|
||||||
message: {
|
message: {
|
||||||
summary: "Server info message"
|
summary: "Server info message"
|
||||||
}
|
}
|
||||||
@ -29,6 +30,7 @@ export const WithLinkBack: Story = {
|
|||||||
render: () => (
|
render: () => (
|
||||||
<KcPageStory
|
<KcPageStory
|
||||||
kcContext={{
|
kcContext={{
|
||||||
|
messageHeader: "Message header",
|
||||||
message: {
|
message: {
|
||||||
summary: "Server message"
|
summary: "Server message"
|
||||||
},
|
},
|
||||||
@ -42,6 +44,7 @@ export const WithRequiredActions: Story = {
|
|||||||
render: () => (
|
render: () => (
|
||||||
<KcPageStory
|
<KcPageStory
|
||||||
kcContext={{
|
kcContext={{
|
||||||
|
messageHeader: "Message header",
|
||||||
message: {
|
message: {
|
||||||
summary: "Required actions: "
|
summary: "Required actions: "
|
||||||
},
|
},
|
||||||
@ -55,42 +58,3 @@ export const WithRequiredActions: Story = {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
export const WithPageRedirect: Story = {
|
|
||||||
render: () => (
|
|
||||||
<KcPageStory
|
|
||||||
kcContext={{
|
|
||||||
message: { summary: "You will be redirected shortly." },
|
|
||||||
pageRedirectUri: "https://example.com"
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
export const WithoutClientBaseUrl: Story = {
|
|
||||||
render: () => (
|
|
||||||
<KcPageStory
|
|
||||||
kcContext={{
|
|
||||||
message: { summary: "No client base URL defined." },
|
|
||||||
client: { baseUrl: undefined }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
export const WithMessageHeader: Story = {
|
|
||||||
render: () => (
|
|
||||||
<KcPageStory
|
|
||||||
kcContext={{
|
|
||||||
messageHeader: "Important Notice",
|
|
||||||
message: { summary: "This is an important message." }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
export const WithAdvancedMessage: Story = {
|
|
||||||
render: () => (
|
|
||||||
<KcPageStory
|
|
||||||
kcContext={{
|
|
||||||
message: { summary: "Please take note of this <strong>important</strong> information." }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import type { Meta, StoryObj } from "@storybook/react";
|
|
||||||
import { createKcPageStory } from "../KcPageStory";
|
|
||||||
|
|
||||||
const { KcPageStory } = createKcPageStory({ pageId: "login-device-verify-user-code.ftl" });
|
|
||||||
|
|
||||||
const meta = {
|
|
||||||
title: "login/login-device-verify-user-code.ftl",
|
|
||||||
component: KcPageStory
|
|
||||||
} satisfies Meta<typeof KcPageStory>;
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof meta>;
|
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
render: () => <KcPageStory />
|
|
||||||
};
|
|
@ -62,3 +62,65 @@ type I18n = typeof ofTypeI18n;
|
|||||||
|
|
||||||
assert<Equals<typeof node, JSX.Element>>;
|
assert<Equals<typeof node, JSX.Element>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const i18n = Reflect<I18n>();
|
||||||
|
|
||||||
|
i18n.msg("passwordConfirm");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const i18n = Reflect<I18n>();
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
i18n.msg("iDoNotExist");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { ofTypeI18n } = i18nBuilder
|
||||||
|
.withThemeName<"keycloakify-starter">()
|
||||||
|
.withCustomTranslations({})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
type I18n = typeof ofTypeI18n;
|
||||||
|
|
||||||
|
{
|
||||||
|
const i18n = Reflect<I18n>();
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
const node = i18n.msg("iDoNotExist");
|
||||||
|
|
||||||
|
assert<Equals<typeof node, JSX.Element>>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i18nBuilder.withThemeName<"my-theme-1" | "my-theme-2">().withCustomTranslations({
|
||||||
|
en: {
|
||||||
|
myCustomKey1: "my-custom-key-1-en",
|
||||||
|
// @ts-expect-error
|
||||||
|
myCustomKey2: {
|
||||||
|
"my-theme-1": "my-theme-1-en"
|
||||||
|
//"my-theme-2": "my-theme-2-en"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
i18nBuilder
|
||||||
|
.withThemeName<"my-theme-1" | "my-theme-2">()
|
||||||
|
.withExtraLanguages({
|
||||||
|
he: {
|
||||||
|
label: "עברית",
|
||||||
|
getMessages: () => import("./he")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.withCustomTranslations({
|
||||||
|
en: {
|
||||||
|
myCustomKey1: "my-custom-key-1-en",
|
||||||
|
myCustomKey2: "my-custom-key-2-en"
|
||||||
|
},
|
||||||
|
// @ts-expect-error
|
||||||
|
he: {
|
||||||
|
myCustomKey1: "my-custom-key-1-he"
|
||||||
|
//myCustomKey2: "my-custom-key-2-he"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user