Merge pull request #745 from keycloakify/keycloak_config_persistance
Keycloak config persistance
This commit is contained in:
commit
8dd6dcd1fc
@ -12,4 +12,5 @@ node_modules/
|
||||
/sample_react_project/
|
||||
/sample_custom_react_project/
|
||||
/keycloakify_starter_test/
|
||||
/.storybook/static/keycloak-resources/
|
||||
/.storybook/static/keycloak-resources/
|
||||
/src/bin/start-keycloak/*.json
|
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 { run } from "../shared/run";
|
||||
import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
||||
import { downloadKeycloakifyLogging } from "./downloadKeycloakifyLogging";
|
||||
|
||||
(async () => {
|
||||
console.log(chalk.cyan("Building Keycloakify..."));
|
||||
@ -148,9 +149,6 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
|
||||
fs.cpSync(dirBasename, destDirPath, { recursive: true });
|
||||
}
|
||||
|
||||
await createPublicKeycloakifyDevResourcesDir();
|
||||
await createAccountV1Dir();
|
||||
|
||||
transformCodebase({
|
||||
srcDirPath: join("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(
|
||||
chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
|
||||
);
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { CONTAINER_NAME } from "../src/bin/shared/constants";
|
||||
import child_process from "child_process";
|
||||
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 { Deferred } from "evt/tools/Deferred";
|
||||
import { assert, is } from "tsafe/assert";
|
||||
import { run } from "./shared/run";
|
||||
|
||||
(async () => {
|
||||
const keycloakMajorVersionNumber = SemVer.parse(
|
||||
@ -16,103 +18,32 @@ import { run } from "./shared/run";
|
||||
.split(":")[1]
|
||||
).major;
|
||||
|
||||
{
|
||||
// https://github.com/keycloak/keycloak/issues/33800
|
||||
const doesUseLockedH2Database = keycloakMajorVersionNumber >= 26;
|
||||
const parsedRealmJson = await dumpContainerConfig({
|
||||
buildContext: {
|
||||
cacheDirPath
|
||||
},
|
||||
keycloakMajorVersionNumber,
|
||||
realmName: "myrealm"
|
||||
});
|
||||
|
||||
if (doesUseLockedH2Database) {
|
||||
child_process.execSync(
|
||||
`docker exec ${CONTAINER_NAME} sh -c "cp -rp /opt/keycloak/data/h2 /tmp"`
|
||||
);
|
||||
}
|
||||
let sourceCode = JSON.stringify(parsedRealmJson, null, 2);
|
||||
|
||||
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"],
|
||||
...(!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) {
|
||||
run(`docker exec ${CONTAINER_NAME} sh -c "rm -rf /tmp/h2"`);
|
||||
}
|
||||
}
|
||||
|
||||
const targetFilePath = pathRelative(
|
||||
process.cwd(),
|
||||
pathJoin(
|
||||
__dirname,
|
||||
"..",
|
||||
"src",
|
||||
"bin",
|
||||
"start-keycloak",
|
||||
`myrealm-realm-${keycloakMajorVersionNumber}.json`
|
||||
)
|
||||
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}`));
|
||||
})();
|
||||
|
@ -81,3 +81,9 @@ export const CUSTOM_HANDLER_ENV_NAMES = {
|
||||
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";
|
||||
|
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": {
|
||||
"realm": ["offline_access", "uma_authorization"],
|
||||
"client": {
|
||||
"account": ["delete-account", "view-profile", "manage-account"]
|
||||
"account": ["view-profile", "manage-account", "delete-account"]
|
||||
}
|
||||
},
|
||||
"clientRole": false,
|
||||
@ -398,6 +398,26 @@
|
||||
"otpPolicyLookAheadWindow": 1,
|
||||
"otpPolicyPeriod": 30,
|
||||
"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": [
|
||||
{
|
||||
"id": "00a62e75-bcc1-419a-a292-63ee5d161ed3",
|
||||
@ -422,30 +442,43 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"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": [
|
||||
{
|
||||
"clientScope": "offline_access",
|
||||
@ -505,8 +538,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -518,6 +555,7 @@
|
||||
"frontchannelLogout": false,
|
||||
"protocol": "openid-connect",
|
||||
"attributes": {
|
||||
"post.logout.redirect.uris": "+",
|
||||
"pkce.code.challenge.method": "S256"
|
||||
},
|
||||
"authenticationFlowBindingOverrides": {},
|
||||
@ -636,7 +674,7 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"display.on.consent.screen": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false"
|
||||
@ -694,8 +732,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -707,6 +749,7 @@
|
||||
"frontchannelLogout": false,
|
||||
"protocol": "openid-connect",
|
||||
"attributes": {
|
||||
"post.logout.redirect.uris": "+",
|
||||
"pkce.code.challenge.method": "S256"
|
||||
},
|
||||
"authenticationFlowBindingOverrides": {},
|
||||
@ -757,7 +800,8 @@
|
||||
"consentRequired": false,
|
||||
"config": {
|
||||
"id.token.claim": "true",
|
||||
"access.token.claim": "true"
|
||||
"access.token.claim": "true",
|
||||
"userinfo.token.claim": "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -1205,6 +1249,7 @@
|
||||
"consentRequired": false,
|
||||
"config": {
|
||||
"multivalued": "true",
|
||||
"userinfo.token.claim": "true",
|
||||
"user.attribute": "foo",
|
||||
"id.token.claim": "true",
|
||||
"access.token.claim": "true",
|
||||
@ -1271,11 +1316,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1291,14 +1336,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
"saml-role-list-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1347,14 +1392,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-sha256-pairwise-sub-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",
|
||||
"subComponents": {},
|
||||
"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"]
|
||||
}
|
||||
},
|
||||
@ -1403,6 +1454,12 @@
|
||||
"providerId": "rsa-enc-generated",
|
||||
"subComponents": {},
|
||||
"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"],
|
||||
"algorithm": ["RSA-OAEP"]
|
||||
}
|
||||
@ -1413,6 +1470,8 @@
|
||||
"providerId": "aes-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["132fb843-59e9-4f36-ad55-5ce2d3a13fb3"],
|
||||
"secret": ["ETyyqapnrkUsNXLQ-tBVKw"],
|
||||
"priority": ["100"]
|
||||
}
|
||||
},
|
||||
@ -1422,6 +1481,10 @@
|
||||
"providerId": "hmac-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["5110d380-c930-49d9-b91b-87f338f6170b"],
|
||||
"secret": [
|
||||
"uCpQrJvP5OBuTxXfDb4JRL0bCKpXUgfGn5vb8UvL-Sfs_sZ9rtvBmd6vuFWARqyezjJQtpoNlMv7sXgxkN-yxQ"
|
||||
],
|
||||
"priority": ["100"],
|
||||
"algorithm": ["HS256"]
|
||||
}
|
||||
@ -1454,7 +1517,7 @@
|
||||
"defaultLocale": "en",
|
||||
"authenticationFlows": [
|
||||
{
|
||||
"id": "f7f2b89b-43cb-491d-8e7c-f1814024a6da",
|
||||
"id": "223ce532-2038-4f24-a606-2a5c73f7bd65",
|
||||
"alias": "Account verification options",
|
||||
"description": "Method with which to verity the existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1480,7 +1543,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "17cdac6f-d2a3-4907-8d44-a42827610b63",
|
||||
"id": "57e47732-79cc-4d60-bee7-4f0b8fd44540",
|
||||
"alias": "Authentication Options",
|
||||
"description": "Authentication options.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1514,7 +1577,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "53a3e43f-9468-401f-8051-40f982d12f85",
|
||||
"id": "c2735d89-60c0-45a4-9b3c-ae5df17df395",
|
||||
"alias": "Browser - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1540,7 +1603,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "26286808-3b7b-43df-b32e-af55a37af2e9",
|
||||
"id": "11a5a507-2b9a-443f-961b-dffd66f4318d",
|
||||
"alias": "Direct Grant - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"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",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1592,7 +1655,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a6f6804c-4160-4a84-8a1f-c2747a2d3f27",
|
||||
"id": "1db6a489-a3b4-44c4-b480-1d1e8c123d20",
|
||||
"alias": "Handle Existing Account",
|
||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||
"providerId": "basic-flow",
|
||||
@ -1618,7 +1681,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "740baa9e-8328-4035-9e1a-8fc1616d1f0f",
|
||||
"id": "7a38f32d-4f34-450f-8f03-64802d7cb8f1",
|
||||
"alias": "Reset - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1644,7 +1707,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e60187a8-3e16-4a0c-9daa-f3a4a1fcfdba",
|
||||
"id": "0df88739-3739-4d70-8893-47c546f19003",
|
||||
"alias": "User creation or linking",
|
||||
"description": "Flow for the existing/non-existing user alternatives",
|
||||
"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",
|
||||
"description": "Reauthentication of existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1697,7 +1760,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ba02689d-b9e8-4a4b-8fdd-0d1386b198fc",
|
||||
"id": "1813b7f2-c3c2-4b92-8ffc-9ff2d12186c6",
|
||||
"alias": "browser",
|
||||
"description": "browser based authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1739,7 +1802,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f09ac92a-e091-4e84-9cd1-cb905ca57b89",
|
||||
"id": "954283ac-f1c2-40b6-a39f-bf23ff9f3ce8",
|
||||
"alias": "clients",
|
||||
"description": "Base authentication for clients",
|
||||
"providerId": "client-flow",
|
||||
@ -1781,7 +1844,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "aaf72b22-cec4-4714-93d6-f54d5a986ab8",
|
||||
"id": "52a789ce-2cad-4f0f-93b2-295b7fd519f0",
|
||||
"alias": "direct grant",
|
||||
"description": "OpenID Connect Resource Owner Grant",
|
||||
"providerId": "basic-flow",
|
||||
@ -1815,7 +1878,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c4a54bb3-f009-4231-a82b-376c2515e07e",
|
||||
"id": "5a6a71e1-9105-45b6-b5f0-52538461357b",
|
||||
"alias": "docker auth",
|
||||
"description": "Used by Docker clients to authenticate against the IDP",
|
||||
"providerId": "basic-flow",
|
||||
@ -1833,7 +1896,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f55ded54-683a-4f5a-a101-9cfbd7b96781",
|
||||
"id": "8392b6e7-bdbf-4d7f-97b6-885761c200db",
|
||||
"alias": "first broker login",
|
||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1860,7 +1923,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "931d5a82-378f-4533-8c69-2239a4acd047",
|
||||
"id": "52136d70-8d08-42ea-b04b-cf40ea2807aa",
|
||||
"alias": "forms",
|
||||
"description": "Username, password, otp and other auth forms.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1886,7 +1949,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "22b05374-f480-4ca8-aca8-9db8b6dd1729",
|
||||
"id": "26bbc7e6-ef01-4cdb-9dba-520e2f3f8993",
|
||||
"alias": "http challenge",
|
||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||
"providerId": "basic-flow",
|
||||
@ -1912,7 +1975,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c0371832-e4b7-485e-bf23-6babe4c6ac83",
|
||||
"id": "f0887979-04eb-4033-8f19-0ffd8c8b7f6a",
|
||||
"alias": "registration",
|
||||
"description": "registration flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -1931,7 +1994,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4d0445da-073e-465e-b25b-af522915c73f",
|
||||
"id": "a3b7b94b-bfbf-4760-a8c9-7d9cd98d262e",
|
||||
"alias": "registration form",
|
||||
"description": "registration form",
|
||||
"providerId": "form-flow",
|
||||
@ -1973,7 +2036,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "740d467f-4203-425b-8203-9bfd3eed25ae",
|
||||
"id": "dc68a665-2e51-4a22-aaad-bd693ddc77cc",
|
||||
"alias": "reset credentials",
|
||||
"description": "Reset credentials for a user if they forgot their password or something",
|
||||
"providerId": "basic-flow",
|
||||
@ -2015,7 +2078,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cf1a9af9-dadd-4cb9-a26e-fbbba216f8e1",
|
||||
"id": "ae6b73aa-1318-4ae8-a3d9-d01b5e7d957e",
|
||||
"alias": "saml ecp",
|
||||
"description": "SAML ECP Profile Authentication Flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -2035,14 +2098,14 @@
|
||||
],
|
||||
"authenticatorConfig": [
|
||||
{
|
||||
"id": "4e65eb4b-9f0a-4ab8-98b2-6daf50cd1bf8",
|
||||
"id": "0c18de7f-0714-41f4-9a3f-ed4edd53ae9c",
|
||||
"alias": "create unique user config",
|
||||
"config": {
|
||||
"require.password.update.after.registration": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5e8dc1c5-1489-4d39-bb75-9c499583b91b",
|
||||
"id": "65b3c8bb-34a4-4d19-b578-245dc8ff53ea",
|
||||
"alias": "review profile config",
|
||||
"config": {
|
||||
"update.profile.on.first.login": "missing"
|
||||
@ -2132,8 +2195,8 @@
|
||||
"attributes": {
|
||||
"cibaBackchannelTokenDeliveryMode": "poll",
|
||||
"cibaAuthRequestedUserHint": "login_hint",
|
||||
"oauth2DevicePollingInterval": "5",
|
||||
"clientOfflineSessionMaxLifespan": "0",
|
||||
"oauth2DevicePollingInterval": "5",
|
||||
"clientSessionIdleTimeout": "0",
|
||||
"userProfileEnabled": "true",
|
||||
"clientOfflineSessionIdleTimeout": "0",
|
@ -73,7 +73,7 @@
|
||||
"composites": {
|
||||
"realm": ["offline_access", "uma_authorization"],
|
||||
"client": {
|
||||
"account": ["delete-account", "view-profile", "manage-account"]
|
||||
"account": ["view-profile", "manage-account", "delete-account"]
|
||||
}
|
||||
},
|
||||
"clientRole": false,
|
||||
@ -435,13 +435,46 @@
|
||||
"type": "password",
|
||||
"userLabel": "My password",
|
||||
"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\":{}}"
|
||||
}
|
||||
],
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -507,8 +540,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -643,7 +680,6 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"display.on.consent.screen": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
@ -704,8 +740,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1284,11 +1324,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1304,14 +1344,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-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": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"saml-user-property-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-usermodel-property-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",
|
||||
"authenticationFlows": [
|
||||
{
|
||||
"id": "e134634e-f219-4df4-867c-8110688d8e56",
|
||||
"id": "1f4d4e13-1591-4751-8985-17886a8c98a9",
|
||||
"alias": "Account verification options",
|
||||
"description": "Method with which to verity the existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1511,7 +1551,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a611a8eb-9626-4aa4-8b54-ee565ea6e5dc",
|
||||
"id": "126f07c3-1bcb-4a02-bf16-bb44674bf55d",
|
||||
"alias": "Authentication Options",
|
||||
"description": "Authentication options.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1545,7 +1585,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d87cbb31-5c69-45c8-888d-f9649ebbbf97",
|
||||
"id": "eb3a08c8-5f99-49b6-b02b-16b62571f273",
|
||||
"alias": "Browser - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1571,7 +1611,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "752ba282-a369-4592-92e8-b4287192dbbf",
|
||||
"id": "3dc19838-5025-4bbb-b569-b574bd5a8d90",
|
||||
"alias": "Direct Grant - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"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",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1623,7 +1663,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4ff5463d-26d9-4219-ba85-41464401098f",
|
||||
"id": "6e24dcb3-5818-483c-8e44-883858171901",
|
||||
"alias": "Handle Existing Account",
|
||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||
"providerId": "basic-flow",
|
||||
@ -1649,7 +1689,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "87bb6c6d-cca8-4832-b5ab-67ecb9454a42",
|
||||
"id": "ac6254cd-403b-457b-b308-22a2a0e4f99d",
|
||||
"alias": "Reset - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1675,7 +1715,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1fc3d028-0e0a-43a4-aaf9-ba7f7d60b409",
|
||||
"id": "485e74e6-9b3e-4b2c-a9b9-927802dc4f06",
|
||||
"alias": "User creation or linking",
|
||||
"description": "Flow for the existing/non-existing user alternatives",
|
||||
"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",
|
||||
"description": "Reauthentication of existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1728,7 +1768,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2e8b9f28-93b8-4368-84b0-1a8326daafe0",
|
||||
"id": "af8b2470-d581-401c-9984-762b966ebcc2",
|
||||
"alias": "browser",
|
||||
"description": "browser based authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1770,7 +1810,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "0b826105-8493-45ce-87b3-7d917d190b39",
|
||||
"id": "414dbda4-eb3f-4baa-b23a-d3423af1eae6",
|
||||
"alias": "clients",
|
||||
"description": "Base authentication for clients",
|
||||
"providerId": "client-flow",
|
||||
@ -1812,7 +1852,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bf6d9edd-48d8-4392-bbc8-4b17a6866074",
|
||||
"id": "1cae0c4b-8dfb-4f5d-a781-e74d0a13c940",
|
||||
"alias": "direct grant",
|
||||
"description": "OpenID Connect Resource Owner Grant",
|
||||
"providerId": "basic-flow",
|
||||
@ -1846,7 +1886,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "97e31722-dd11-42be-aa99-88788fa2dde6",
|
||||
"id": "e798b655-7d85-4b6b-aee7-1448a3e1e0ea",
|
||||
"alias": "docker auth",
|
||||
"description": "Used by Docker clients to authenticate against the IDP",
|
||||
"providerId": "basic-flow",
|
||||
@ -1864,7 +1904,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3f45cf34-231f-4ea1-8e58-d636c451a76b",
|
||||
"id": "eb94b723-1041-426a-87bf-f7b4bd2f485d",
|
||||
"alias": "first broker login",
|
||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1891,7 +1931,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "9bef2f7c-f989-4871-aaa7-18e2cfa73f22",
|
||||
"id": "452d1d5f-7632-44d7-bc89-77ff2b209b3e",
|
||||
"alias": "forms",
|
||||
"description": "Username, password, otp and other auth forms.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1917,7 +1957,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "0bfaa325-acde-4443-8bd8-1dc2ae759c5f",
|
||||
"id": "7c1b9e8f-6b57-49d1-a9a7-494862f93c0f",
|
||||
"alias": "http challenge",
|
||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||
"providerId": "basic-flow",
|
||||
@ -1943,7 +1983,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "37ddbe8c-abf3-4654-bd6d-ffabbeefbb98",
|
||||
"id": "2b38f34a-1739-499e-bb24-1dff96f32009",
|
||||
"alias": "registration",
|
||||
"description": "registration flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -1962,7 +2002,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5d7b4bc9-e93b-40da-aeb6-ba0c38392f1a",
|
||||
"id": "d26ae72b-a933-44dc-9927-1c82757004b2",
|
||||
"alias": "registration form",
|
||||
"description": "registration form",
|
||||
"providerId": "form-flow",
|
||||
@ -2004,7 +2044,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ee7a56e4-c827-4f24-8b8b-8476050b0b64",
|
||||
"id": "222ee8d6-1892-4768-9ada-720274b6bf9a",
|
||||
"alias": "reset credentials",
|
||||
"description": "Reset credentials for a user if they forgot their password or something",
|
||||
"providerId": "basic-flow",
|
||||
@ -2046,7 +2086,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "360f0031-4c3b-4272-84ca-2172d430b4bc",
|
||||
"id": "e8b4d92c-27c1-4a9b-9b16-7ceb810fa230",
|
||||
"alias": "saml ecp",
|
||||
"description": "SAML ECP Profile Authentication Flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -2066,14 +2106,14 @@
|
||||
],
|
||||
"authenticatorConfig": [
|
||||
{
|
||||
"id": "53630acd-a33a-40e3-8786-cf85464c6f9e",
|
||||
"id": "e5847a0b-855d-4d93-85fd-94714be3ed92",
|
||||
"alias": "create unique user config",
|
||||
"config": {
|
||||
"require.password.update.after.registration": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "c0d2b6a0-caad-4e90-b040-17cacdaf70bb",
|
||||
"id": "a2a18aa4-bd4c-4c2a-9286-e9d6c64f4812",
|
||||
"alias": "review profile config",
|
||||
"config": {
|
||||
"update.profile.on.first.login": "missing"
|
@ -73,7 +73,7 @@
|
||||
"composites": {
|
||||
"realm": ["offline_access", "uma_authorization"],
|
||||
"client": {
|
||||
"account": ["delete-account", "view-profile", "manage-account"]
|
||||
"account": ["view-profile", "manage-account", "delete-account"]
|
||||
}
|
||||
},
|
||||
"clientRole": false,
|
||||
@ -407,7 +407,7 @@
|
||||
"otpPolicyLookAheadWindow": 1,
|
||||
"otpPolicyPeriod": 30,
|
||||
"otpPolicyCodeReusable": false,
|
||||
"otpSupportedApplications": ["totpAppGoogleName", "totpAppFreeOTPName"],
|
||||
"otpSupportedApplications": ["totpAppFreeOTPName", "totpAppGoogleName"],
|
||||
"webAuthnPolicyRpEntityName": "keycloak",
|
||||
"webAuthnPolicySignatureAlgorithms": ["ES256"],
|
||||
"webAuthnPolicyRpId": "",
|
||||
@ -452,6 +452,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -517,8 +551,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -653,7 +691,6 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"display.on.consent.screen": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
@ -714,8 +751,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1294,11 +1335,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1314,14 +1355,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"saml-user-property-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-role-list-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": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
"oidc-usermodel-attribute-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1495,7 +1536,7 @@
|
||||
"defaultLocale": "en",
|
||||
"authenticationFlows": [
|
||||
{
|
||||
"id": "19317acb-fe8e-4c79-82bc-90e159273075",
|
||||
"id": "c40791b4-4d59-4df2-bebd-2b71e793704f",
|
||||
"alias": "Account verification options",
|
||||
"description": "Method with which to verity the existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1521,7 +1562,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "122857d2-33da-4086-8acb-cb0e303aaf1b",
|
||||
"id": "8813b6d1-8b88-4672-b29b-8420ce3f3975",
|
||||
"alias": "Authentication Options",
|
||||
"description": "Authentication options.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1555,7 +1596,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "abf5dd35-4791-4268-a10c-5f4b6a06b84a",
|
||||
"id": "a9937c40-a1ee-4c57-adf7-ede0a9983953",
|
||||
"alias": "Browser - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1581,7 +1622,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a18daeec-a33c-4a43-b014-10c84ec69b81",
|
||||
"id": "2d494b5a-eb73-40d0-94d3-a8d8024a7db4",
|
||||
"alias": "Direct Grant - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"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",
|
||||
"description": "Flow to determine if the OTP is required for the authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1633,7 +1674,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "9db65b7c-98ca-4003-beea-611038831ffe",
|
||||
"id": "6f171b4b-8723-4e6d-bb1e-6b4293a7bb3f",
|
||||
"alias": "Handle Existing Account",
|
||||
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
|
||||
"providerId": "basic-flow",
|
||||
@ -1659,7 +1700,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7bd0854c-d7ae-43d7-a1ae-7b759a34cb1d",
|
||||
"id": "2dbb7f27-757d-4178-8217-4a24fdb0163c",
|
||||
"alias": "Reset - Conditional OTP",
|
||||
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1685,7 +1726,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2de1a450-fe98-443a-9c6c-d24d8a7ebcb3",
|
||||
"id": "7295aaf7-acf4-4b78-8186-d2415ea4ede0",
|
||||
"alias": "User creation or linking",
|
||||
"description": "Flow for the existing/non-existing user alternatives",
|
||||
"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",
|
||||
"description": "Reauthentication of existing account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1738,7 +1779,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "de93418e-8f28-4099-b15e-ad36ec194796",
|
||||
"id": "5f3d0fb0-d95e-4841-89d3-a27d0cdbbcb4",
|
||||
"alias": "browser",
|
||||
"description": "browser based authentication",
|
||||
"providerId": "basic-flow",
|
||||
@ -1780,7 +1821,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "0dd3345c-6e82-4c3a-a39a-d49ae1f5c409",
|
||||
"id": "c246380d-af25-4151-ab19-1f1e5b553008",
|
||||
"alias": "clients",
|
||||
"description": "Base authentication for clients",
|
||||
"providerId": "client-flow",
|
||||
@ -1822,7 +1863,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "87fb4dd0-5326-47a1-b670-982f4872ff89",
|
||||
"id": "abacf398-0f1f-4f28-a310-8d306d588048",
|
||||
"alias": "direct grant",
|
||||
"description": "OpenID Connect Resource Owner Grant",
|
||||
"providerId": "basic-flow",
|
||||
@ -1856,7 +1897,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "344723b3-4ab1-4999-abdd-32398e82327b",
|
||||
"id": "a0f87683-619a-44d4-8b4f-4b053bba2346",
|
||||
"alias": "docker auth",
|
||||
"description": "Used by Docker clients to authenticate against the IDP",
|
||||
"providerId": "basic-flow",
|
||||
@ -1874,7 +1915,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f3341938-caf9-4c8a-9cd5-eb34609809ab",
|
||||
"id": "e8820c7c-22a7-4618-beb7-3e09be72c00c",
|
||||
"alias": "first broker login",
|
||||
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||
"providerId": "basic-flow",
|
||||
@ -1901,7 +1942,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ba7b7357-e324-4b71-9bda-f8512a760e02",
|
||||
"id": "cac00c38-ee44-44c9-b95e-cc755bab36ef",
|
||||
"alias": "forms",
|
||||
"description": "Username, password, otp and other auth forms.",
|
||||
"providerId": "basic-flow",
|
||||
@ -1927,7 +1968,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "134971e6-bf63-432c-806e-74ca4fb09963",
|
||||
"id": "688cde36-507e-4a68-afdf-18ec4ad626a7",
|
||||
"alias": "http challenge",
|
||||
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
|
||||
"providerId": "basic-flow",
|
||||
@ -1953,7 +1994,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6ea9e2cf-5684-4c65-8c07-930d1cbb0b46",
|
||||
"id": "e058697c-f450-4f14-ae64-04e9299fa24f",
|
||||
"alias": "registration",
|
||||
"description": "registration flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -1972,7 +2013,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "67e3c8c7-1b5e-4119-84a2-e90876293150",
|
||||
"id": "ad768088-32c9-4979-90dd-61bf111fd72e",
|
||||
"alias": "registration form",
|
||||
"description": "registration form",
|
||||
"providerId": "form-flow",
|
||||
@ -2014,7 +2055,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fc6d48ec-a1f1-41b1-9310-54f58861d5aa",
|
||||
"id": "47d4b090-f965-4588-b5bc-029ccb59876f",
|
||||
"alias": "reset credentials",
|
||||
"description": "Reset credentials for a user if they forgot their password or something",
|
||||
"providerId": "basic-flow",
|
||||
@ -2056,7 +2097,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "80b1d464-c2ec-4eb1-82e8-32cbede779a8",
|
||||
"id": "1f68feec-7f99-4c49-afe6-45d46684ca21",
|
||||
"alias": "saml ecp",
|
||||
"description": "SAML ECP Profile Authentication Flow",
|
||||
"providerId": "basic-flow",
|
||||
@ -2076,14 +2117,14 @@
|
||||
],
|
||||
"authenticatorConfig": [
|
||||
{
|
||||
"id": "86b1d5fa-450c-40d8-899c-725861ac39fc",
|
||||
"id": "bd7365c7-842b-4bc6-a4ca-498cf025c210",
|
||||
"alias": "create unique user config",
|
||||
"config": {
|
||||
"require.password.update.after.registration": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ea724f02-029a-493d-b4d3-08972be21cfb",
|
||||
"id": "b929192d-f650-4a09-9701-3d3216547552",
|
||||
"alias": "review profile config",
|
||||
"config": {
|
||||
"update.profile.on.first.login": "missing"
|
@ -73,7 +73,7 @@
|
||||
"composites": {
|
||||
"realm": ["offline_access", "uma_authorization"],
|
||||
"client": {
|
||||
"account": ["delete-account", "view-profile", "manage-account"]
|
||||
"account": ["view-profile", "manage-account", "delete-account"]
|
||||
}
|
||||
},
|
||||
"clientRole": false,
|
||||
@ -456,6 +456,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -521,8 +555,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -657,7 +695,6 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"display.on.consent.screen": "false",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
@ -718,8 +755,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1298,11 +1339,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1318,13 +1359,13 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"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-full-name-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-address-mapper"
|
||||
]
|
||||
}
|
||||
@ -1374,14 +1415,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-usermodel-property-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-user-property-mapper"
|
||||
"saml-user-attribute-mapper"
|
||||
]
|
||||
}
|
||||
},
|
@ -55,7 +55,7 @@
|
||||
"composites": {
|
||||
"realm": ["offline_access", "uma_authorization"],
|
||||
"client": {
|
||||
"account": ["delete-account", "view-profile", "manage-account"]
|
||||
"account": ["view-profile", "delete-account", "manage-account"]
|
||||
}
|
||||
},
|
||||
"clientRole": false,
|
||||
@ -459,6 +459,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -505,7 +539,6 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
@ -532,8 +565,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -649,7 +686,11 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"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": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
@ -664,8 +705,7 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false"
|
||||
@ -725,8 +765,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1336,12 +1380,12 @@
|
||||
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1357,13 +1401,13 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
]
|
||||
}
|
||||
@ -1433,13 +1477,13 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"saml-role-list-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
]
|
||||
}
|
@ -468,6 +468,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -514,7 +548,6 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
@ -541,8 +574,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/realms/myrealm/account/*"],
|
||||
"webOrigins": [],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -658,7 +695,11 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"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": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
@ -673,8 +714,7 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false"
|
||||
@ -840,8 +880,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1451,12 +1495,12 @@
|
||||
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloak",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1504,11 +1548,11 @@
|
||||
"saml-role-list-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-user-property-mapper"
|
||||
"oidc-full-name-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1540,14 +1584,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-property-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-usermodel-attribute-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"saml-user-attribute-mapper"
|
||||
"saml-user-property-mapper"
|
||||
]
|
||||
}
|
||||
},
|
@ -538,10 +538,10 @@
|
||||
"emailVerified": true,
|
||||
"attributes": {
|
||||
"additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"],
|
||||
"gender": ["prefer_not_to_say"],
|
||||
"favorite_pet": ["cats"],
|
||||
"favourite_pet": ["cat"],
|
||||
"gender": ["prefer_not_to_say"],
|
||||
"bio": ["Hello I'm Test User and I do not exist."],
|
||||
"favourite_pet": ["cat"],
|
||||
"phone_number": ["1111111111"],
|
||||
"locale": ["en"],
|
||||
"favorite_media": ["movies", "series"]
|
||||
@ -562,6 +562,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -636,7 +670,7 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["*"],
|
||||
"redirectUris": ["http://localhost*", "http://127.0.0.1*", "*"],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
@ -798,8 +832,7 @@
|
||||
"attributes": {
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false"
|
||||
@ -892,8 +925,12 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -1551,11 +1588,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1581,14 +1618,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-address-mapper"
|
||||
"oidc-address-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1618,14 +1655,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-full-name-mapper"
|
||||
"oidc-full-name-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-property-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1678,6 +1715,12 @@
|
||||
"providerId": "rsa-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"privateKey": [
|
||||
"MIIEowIBAAKCAQEAso89qpvLhf9DIcCb2JAbxItRLSIvP/NCZhMdAExTHyrhM5B27ZQ6MZ7dJQbnMu7QJ7yiClsD1XnDN7Wlj07sY2As3lY3v9kjODBeADYlPuN1m7/fXFHX3qfRT+PwVSaAhMykmqvWp86UTg7t7rNjVBnXPPXItmRLIF+jZUMWQduwNznr6Jh54ZdIwEy4hvX1bpNw0nPl4KXiOi2elvg+rk7BhFywGwQ/HUCGkrcq0XS/aNOy1ChmqDbtq817mYpVeteCDe8xP3MPrZ/s2LiEt4Ip1cNo0dY+a4JwOzwL42h3GaR+80iK3pZNo+Mr0KBOY9GXvdV/MvcPHLQ7VujUGQIDAQABAoIBAAHV0OQwmDxUazqiVGe61Bzmcqs5q03SC1K/FmCi/YVikdskvGLaOmk5UQa4+1uDEq7J30onH9ML8+qeFRQek0rn2ZDfxtBpDqsx7LwTUmQtqc8z6buKQs37db5ctnhlk34UmAotQyDz5wMmCkzWWVUWCT02PdMev5qW/mKuIxaCWLHUFiMJaGrYCCwB/Ra8KLcadKgRbytSUth9qILC4krFfmWtzIx1P6nM1pzQ1nydxNnNPJKjoWtLRJ5b701Y5/h2vAAg6Mr+jKe1DPa9QmAqhQudjGbZ31av+0f1/I+XkflpZfokfU+MrAqNYRTYkevRYgc3wakK5mfVYUiMuOECgYEA7fk55O2OJFsR0Vjy4Dx4eSIwgwobvwEuHxlyWn0RC7nFb00eh6OPuc5sHrOk8bK3P367q67sEhxGyBF16nwxgX/T+c8gTC8QRuwNymosA4Je/zJHbKvyzLGOouCP5gYwq/wUmVWzNApVC7LBfxbsqYyivHABc5xgPmTgecY0VWkCgYEAwBXcUKoyq1KZegyNJcTuwuvBXoYVveFGm6QKKKwzojCCKaR3XXtdSon1qYfuKT0MLxgEDyyBks9DgfCodSsTmajX90Yolhyz3ptcOmRURqTRoJhM4g6qA+Ybd3uy8vAz32RdS+4rCTgnMG/5Xpn5B4ojOnhRcnA2TPCJgWz6QzECgYEAhj1FjD75JMb+mRJNB3L1HpfLt8+28RsQUli/ag4M1Il5txxQsYDxbYXk9biuvezrc/Tglqs43cp3nxpCYwClyIA8KjnN5UvTKb601M7pfx1GyzwokEO61f7/ECAO7FnnkMzFLe3rBdsiOFQg1LkwzT/Y+OVR3E6E+A1dlzPYh6kCgYBIP3CwfnO0cMr9Vv8394x+kEIZFYHT+4mdPOP9TFfXZztuAkhLRv1d7eoSq+fuZuHQTM4qDullmMOhei1CdMNYhmNExIS7gWw+DF1yMQ5py9B1ARPZ6v4TnVczZ7l1GtfH7G4TAy/4tcA3vcYjyPIb3d9GPL8VthMWeVqe7ahr4QKBgEwA7ASbs4NxfBsStEGQYQYAeWOoKnTc50FeYz38O4KrOirtTFPNsJcyCiTE0o4cqu/OebSA5irrauV7SEDl/gfH54g3ZWusQbLt2uMnZYtkd2+Ka3T9XM0QfQW/vYl3eJtdQj89TqzLzyP0AgvAyIgeG3RMH8ojqCh3YKY0FTv/"
|
||||
],
|
||||
"certificate": [
|
||||
"MIICnTCCAYUCBgGTy2TGBjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE3MzQ1OVoXDTM0MTIxNTE3MzYzOVowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKPPaqby4X/QyHAm9iQG8SLUS0iLz/zQmYTHQBMUx8q4TOQdu2UOjGe3SUG5zLu0Ce8ogpbA9V5wze1pY9O7GNgLN5WN7/ZIzgwXgA2JT7jdZu/31xR196n0U/j8FUmgITMpJqr1qfOlE4O7e6zY1QZ1zz1yLZkSyBfo2VDFkHbsDc56+iYeeGXSMBMuIb19W6TcNJz5eCl4jotnpb4Pq5OwYRcsBsEPx1AhpK3KtF0v2jTstQoZqg27avNe5mKVXrXgg3vMT9zD62f7Ni4hLeCKdXDaNHWPmuCcDs8C+NodxmkfvNIit6WTaPjK9CgTmPRl73VfzL3Dxy0O1bo1BkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAggzxmYvHqUaCPLxxSidLQMgpu1pTozg3rTq8dcxhcHINI//A/z7qQyDA/QQN5cuSpYvdt2MRWoNop+uRNKqSr3C8aRErbY0j4acl7yG/ghNfQUZ9KxDBxKrd0HLFUibdZobg10+Ih/qXo3Mi2VtkqyZQRl/iy0O3ITgqb7YJUEx5tuEWyGbn+SerFvqZNcmsLziOJefm1n4uqroHgIfmgY6Deh+wZK0DwO3WZ6ThjhMp5GFi1oNeZ9xoExNEXrYp07b2xTQFF57oypc7prf733lqGjPRLfoVJP6qcsjvAlOA7f8TG9sKwGuRsPfadYY9PxmdHxl2k7PHDJeDhA7VdQ=="
|
||||
],
|
||||
"priority": ["100"]
|
||||
}
|
||||
},
|
||||
@ -1687,6 +1730,12 @@
|
||||
"providerId": "rsa-enc-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"privateKey": [
|
||||
"MIIEowIBAAKCAQEAxoEvnv+YHCqUWANGuku5QYscAZyUE0WHSlcAzZ0bQugPow63piQsuxPz0cpPIuLab6adssXUqKEFheT1H0BqtmT9L/7iOKB6MRuInN4aRzzTH9q02TKPkcpSAzAHTGcsJBMMawlbnIdMu5+mevMPxqeVVxvrnKG27S8H3W5jqIkQw8bo646Hr3l5Dxq/jY7slcSXXXe4ZdefeCvnSqea+fy5c+r/r546nX4FTGiklu6KLQaDc9SfGccrZDmljY7DX1kHrmvIdLShcuukTHc0hi2qbgMcUte/7/svSJLUWOZObKxetd4y1OA49v36xrMqGhwGDdwrWf0VuMBN8eHOCQIDAQABAoIBABz/hUXnFRZURWHKxLvKpnBZPTOiZzfzfxfl4tOmq54CtDoVQyXNq2J+6oOPWC/X+ky3hy+1BQ5x9hJrx+qTU04m2EfOe8da8M7DX28kZlauyjF2loG+MvP7ctn4BluWcip+RTZOYn2DfxBPpRcunR409V+JesoMY7fSwtrfA/Gm0PrXgBK7OuE0nxqFFWnsLOc+HxZECS5r0n1MHEBHe774HkqGcK91j8S+QU+/diTnK+N/ClnKWnabMK8bUO5wAUuKwf2deYkGP91pCEJlVnVZyaXshEM+uxTuMRUlq9h1QAIUatvdQwfOKqZ9XvmTVC8b79qLwmezjoDxNCKbaMMCgYEA71WDpMnA2uS2wCJ/MVwzWGSBDjfeKUPRy33BeUfwLGp4Dro+S1sTrLHgi1HGmvmC8ReZrifUlUHUi3ZHauR6vbNsEoSQ3hplO013kj12EfcBpvKYFg1ODCwevb/JtBTWbDG1P+E9DGiF/2u0aicoJoPolNeNVzgO6YK1OI/S/LMCgYEA1FPTqFPulXxcOK12LgYap8typqJ7zu4fByr42010yrKM+LLNA3bT/i/oRkKc7J1ztKSqlVckADWgK4Y27lI4j1tSgTOxFzwxnTZOeF7ZwGSxq9iy9A84nDiW+m6Hj5RDyBjTSoP2Qqv6d5kTUx+pczZvOVTWRlIEnFETbbxOoFMCgYEA0r1etHx+V4AqtxXpH6KLB5s/1DA3a+hu1BrAgLVqcwGxA27VKW9h7J+YE7UHBzELLpVUWfhyhJa5u6+DhUj4Fw/k6o1WLmvZlZVJ4zhBPeJczw8wAcLnZWp4CybUScBLamt+qGgBZGqpCtZgv1QJU5i09FK0/wa6grz4K3zhEGcCgYAlnGe8xIlZr3rCi2+IvYoROQepHtUhlaqnYWRNrI3IrhIsp7eLKoxo1WGmuHwFqepqEFUrORFmfBlQPGkUlDnyovGdc2OmQwJi39DMn7igzPVwBGXGt7+GZLvRxqx6sX/EPSmIZJHFw6MNdm8m5U/l2bmgBTgjormwWug/IwEmgwKBgEouISIuXsjGxeLmhrOXHKXb6IfKglNJeBM6lTQ6MLaVOso7KdelIntwZNtZwMIi3hlwaUb1X1QmztFbnrvnPhWwJR4ZgMEWanRHthtm0SHzg8EHKT40S91oKabsgHk3wpOvq/iWs+k8qWN4HYp6UO603uLMOfxPYJCFxRtg2TsJ"
|
||||
],
|
||||
"certificate": [
|
||||
"MIICnTCCAYUCBgGTy2TG/jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE3MzQ1OVoXDTM0MTIxNTE3MzYzOVowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMaBL57/mBwqlFgDRrpLuUGLHAGclBNFh0pXAM2dG0LoD6MOt6YkLLsT89HKTyLi2m+mnbLF1KihBYXk9R9AarZk/S/+4jigejEbiJzeGkc80x/atNkyj5HKUgMwB0xnLCQTDGsJW5yHTLufpnrzD8anlVcb65yhtu0vB91uY6iJEMPG6OuOh695eQ8av42O7JXEl113uGXXn3gr50qnmvn8uXPq/6+eOp1+BUxopJbuii0Gg3PUnxnHK2Q5pY2Ow19ZB65ryHS0oXLrpEx3NIYtqm4DHFLXv+/7L0iS1FjmTmysXrXeMtTgOPb9+sazKhocBg3cK1n9FbjATfHhzgkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdUIlJ91E0UkFS45AByjFufRnQbAi1smnHkC3WSN39bhcFT7Hgip97qtABODR58zVHSTS0XcMiL4mMObH3Vyz9J3gmwWZnbokAuo9tYeyrhPh/gqXv3LGtGhTpWlUJ7JEJxH7RVI4UZZyG6Y6FR+3zwiZ0j1p3QsZclfcNmacoi/Ano+4TfloOnY4k8yP7G6LWUTJHpcRNWVVozM3RwekYgpJRAtXDoYfm9p2hRQ090e7NvbblSuVQ/FXhUn4g0wz91WdCWlwXZfvNaRjbynPCHejJpszqiyjPkx3aRKTWqer0ZocKNmY8+RO27XIsXmwOYcjdpX2TCFDv6O+VLfNdw=="
|
||||
],
|
||||
"priority": ["100"],
|
||||
"algorithm": ["RSA-OAEP"]
|
||||
}
|
||||
@ -1697,6 +1746,8 @@
|
||||
"providerId": "aes-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["95db7eb8-b57b-475e-90cd-58841a9388d3"],
|
||||
"secret": ["dp6bv53YrC2PZuJCxa3aNA"],
|
||||
"priority": ["100"]
|
||||
}
|
||||
},
|
||||
@ -1706,6 +1757,10 @@
|
||||
"providerId": "hmac-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["d0254883-059e-4fdd-bf03-704c76650aab"],
|
||||
"secret": [
|
||||
"bcW7E4rcbgSKZIQysWOSuhezRGYs5Kzmp3ZESthdTUMyFivK8RbBAdBE4PhFPk5B9TuByDO2RWvd8F7F5YhGJitf6cfYB1BfDuAk-2iBAtdZA98g7a2h4jpwzh-GIgtoRbGbH9qnquUn52f5qteo34g5WifKE2bWjOELza9FrTo"
|
||||
],
|
||||
"priority": ["100"],
|
||||
"algorithm": ["HS512"]
|
||||
}
|
@ -563,6 +563,40 @@
|
||||
"disableableCredentialTypes": [],
|
||||
"requiredActions": [],
|
||||
"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,
|
||||
"groups": []
|
||||
}
|
||||
@ -638,7 +672,11 @@
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["*"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/realms/myrealm/account/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
@ -805,8 +843,7 @@
|
||||
"realm_client": "false",
|
||||
"oidc.ciba.grant.enabled": "false",
|
||||
"backchannel.logout.session.required": "true",
|
||||
"login_theme": "keycloakify-starter",
|
||||
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
|
||||
"post.logout.redirect.uris": "+",
|
||||
"oauth2.device.authorization.grant.enabled": "false",
|
||||
"display.on.consent.screen": "false",
|
||||
"backchannel.logout.revoke.offline.tokens": "false"
|
||||
@ -894,14 +931,20 @@
|
||||
"id": "fce8a109-6f32-4814-9a20-2ff2435d2da6",
|
||||
"clientId": "security-admin-console",
|
||||
"name": "${client_security-admin-console}",
|
||||
"description": "",
|
||||
"rootUrl": "${authAdminUrl}",
|
||||
"adminUrl": "",
|
||||
"baseUrl": "/admin/myrealm/console/",
|
||||
"surrogateAuthRequired": false,
|
||||
"enabled": true,
|
||||
"alwaysDisplayInConsole": false,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"redirectUris": ["/admin/myrealm/console/*"],
|
||||
"webOrigins": ["+"],
|
||||
"redirectUris": [
|
||||
"http://localhost*",
|
||||
"http://127.0.0.1*",
|
||||
"/admin/myrealm/console/*"
|
||||
],
|
||||
"webOrigins": ["*"],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
"consentRequired": false,
|
||||
@ -914,9 +957,14 @@
|
||||
"protocol": "openid-connect",
|
||||
"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": "+",
|
||||
"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": {},
|
||||
"fullScopeAllowed": true,
|
||||
@ -1561,11 +1609,11 @@
|
||||
},
|
||||
"smtpServer": {},
|
||||
"loginTheme": "keycloakify-starter",
|
||||
"accountTheme": "keycloakify-starter",
|
||||
"accountTheme": "",
|
||||
"adminTheme": "",
|
||||
"emailTheme": "",
|
||||
"eventsEnabled": false,
|
||||
"eventsListeners": ["jboss-logging"],
|
||||
"eventsListeners": ["keycloakify-logging", "jboss-logging"],
|
||||
"enabledEventTypes": [],
|
||||
"adminEventsEnabled": false,
|
||||
"adminEventsDetailsEnabled": false,
|
||||
@ -1591,14 +1639,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-usermodel-attribute-mapper"
|
||||
"saml-user-attribute-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"oidc-address-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"saml-role-list-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1628,14 +1676,14 @@
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"allowed-protocol-mapper-types": [
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-address-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper",
|
||||
"saml-user-attribute-mapper",
|
||||
"oidc-sha256-pairwise-sub-mapper"
|
||||
"oidc-usermodel-property-mapper",
|
||||
"oidc-full-name-mapper",
|
||||
"saml-role-list-mapper",
|
||||
"saml-user-property-mapper",
|
||||
"oidc-usermodel-attribute-mapper",
|
||||
"oidc-address-mapper"
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -1688,6 +1736,12 @@
|
||||
"providerId": "rsa-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"privateKey": [
|
||||
"MIIEoQIBAAKCAQEAxTFMvRiNiQjY9zajvLsah6Vy4pn8U7smsnBcHS9SkLJ1j9O8+90B90tIZk4IqEE4gdJA/mbbeUnou1vWuc0k69diQMFelzdIaDqJaFFeOS+J1DoApjThjGIz7FIgmGi6qoN8xnrPVD/6oMYAuxTvQaJH7mENiIG0198dvaufV1mFPg+krTsh7Womo2CJeZmNuAXv7RDQYxwPYDCFZLbppez48D7+2D+1V6Stk6Xwz8IDQZvljxDF6W2P9rhPWV1C5tcJpC/9RPyGDo+ke8UN3fM6X7YOgpbMztVrg8J0aTqPXZ7dt6QFUqVOufo+5wYL2jCafpYNV8cmaGlY+Q3d5QIDAQABAoH/DIPcaZaJTLG4FeUKGOaT40nesEiINRY99aeIkp+hdGj1EgTEn49TyLENGnhrrdbIvOJDeD6Z6dbpJBDvfFevxa589EnVKaGaaW5U91FDyVYH2YPU411dAeOp0z1xwxXzlJqX3h42ZJnvLAp/2l1Xo64vGCoTJtYlppAvpe2MjANxPNObAc65Phdi/sConAlwMeBylWXJ574uryFrJ64W/sUuIUMSunGGz0db4Y1hfkX9U2YnxB3DdXCBH09jQJyKDSj6feNXR87+1KhqcFMd5DUiGSAOqRBzuBMsDf1QDJd8A/DDlK7e/PA1Yk/Dii4hsf+LCeOdmhlifuyROqJBAoGBAOEm4gLvaBWwnUhmr4sW8xywIhGGbU+MX6vm/KkGtScres7pPhmfy6ARUzCxxyBqIE+nhCRNBpOEPhP7dv8naJhZZ4fRvNzuXpUMT2X3bc5yNzdhaOxBJl95YQbrYUHhjcIw2kdXnIkpdbB/RqmY0F5BUTYECrd0tKWbjuL5RIRNAoGBAOA1wTXrYyVorouxV+mGNb62Py+utHJQKSa5cxF9nbbwWJd+FdreiBOJddjATmH8ovKjueQFVqK7koDveOb+pgRY2bpT88/NW8UF6a2wMiI0p6pxrR+hgzas480YiOCWr6XlsprqsSKBbEu4W97GicleZ6P5Iso/gBr9aHj9EWv5AoGAYhRzHj42RESUr4Zz8A5GR3f+z02U7rNCtfrAk80lOvP44ou+jqEKrib961d2XAt/GdPqf3nCZJ6WAFRp6Qq8yKkhrYvTTxbTwvAC4nNftTASF6DqeQiEc9DHUKFW08Ey5KYtYCitOx8BcqpvGNBF7NldTD+Ef5hqXT4fh4Z4r30CgYEAy2OYGMymTRowNKK06C+Kc62plhy6rnRPUESswLIeLwTKqOqE8t4pvOdWk0CoGjVusAOcLuA03jyfwvz5xTo96fWb1W4w31IgLJOXjqsmX2c6reCfNvFyMVgW8keOa4XmYu0C34uFEpMrZWkhVe7usVBFXjczuxptoI4+hnqzoikCgYBICBVR9Z7n2LvmWH19/Nnns8dsMn5peL7H6Mey76Lo9RMEMp4qhiJTqVZzWgxEyVjr0KFCHmdmwkTOm6A1yYmkqqXDdiJ9v4J4fXe0lRAoUoYPTOWynrCyd6uqq+3zlzTKW8jY9luywHq6msn07D636PvveeZ93DNCcO8Whw36rQ=="
|
||||
],
|
||||
"certificate": [
|
||||
"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"]
|
||||
}
|
||||
},
|
||||
@ -1697,6 +1751,12 @@
|
||||
"providerId": "rsa-enc-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"privateKey": [
|
||||
"MIIEogIBAAKCAQEAungL4osLyP8bE6MSKj8ZMJTG8WBh3K2/xB5BJYCYc7P1CIORZI9o/vKQx1QnP+CXkIKnnR2kzIzC0rnTqlIOkaZfhmSn50jG5vNBS9qPT+WU7Ue3qKxuWJFwcaFU5SEJawJHqnDPK+pktkkxkudeMHz6iaKPs+wKcbfrRJ6+3a3FqQQdHEQg4IjVU8pBZmag1c7JHayiM56OT5y6jmE5JvY60959iPrZPXSTMU3hNoiVwdyK6QwdK+/0wrO681VhIP+u2pe92nQ+hsgMSSQJegLx1UsEEyU87syblG+p3zAKSS+kt2nviV/a2cYiiME0LdlQ3lnKsQ4t1Y6yZBiS2QIDAQABAoIBABhozI18TC+kjWPVrfQPzHlakGxahJUBvZ+rojWJjutefE4AAxFZ4JG3KRKexoCLIuwM3monzkHkj0BMiRO7qCKS1+Bc3snc8gSbhUmrs6Tu1b7162nOIKfBainFx7oyx+vVIZKDL+t8xHBERpQHa4IHajiIKi2QUZGvVMHn0e5srkPK0eSMjb5Z5j61aFb8InQzs7tczr99ke4VavOPT1gmRWGnbTavUbw/zIQ9sxAuMiD2v0nrGlOLZrMhaqzsT6PjIWVCSZrWex1pin9gA4XwGZ39E7+zFWgg+2OX0dEvehVDluAQR0K4PBUknuL1LFFW8dpvCrUSTmGGQOSVuB0CgYEA+bQjbjTNiMTEfoxx/WvVDgtLRL/x9RVyeYTPia2TGNBwpEcU64lLMOwUt5X/QuGXayPr0EGAxMA8kwq/E8Wj2t9+SuqkGK9SIwvghi2fOh0KWghuQbKYMogG5hsJAI8+/mBIOJJ8pyh0RX58vaTlYctbThO22aVahhZQ2weaW58CgYEAvyu4vIe44/7F19Hjh2BW+9lHsHA2zwHvC5T1kFaEdBYEwGsLMW6leCsiEMfpc2Uq3k9+buZgVpTE5APs9cSJX1aUXEG5QHQmYDxAAMiTyvpj0o2cKbDi1A5QZCRo23lC+uDyR7g2zLDJuHek0uyCtd83hbgyxIVFUnfvI9EmfocCgYBtpcZxHEqspgrKrw1XBMTXl+oDVG4A+tv7tHAVutx+5vivim8LRox3/RLT0s/2JG2DJJDmL/1FaEyxHOTu37il4cHpT8Oi+0mMDikXgm0K7bmf81fHDY97kPPGk1SOpFg7BzhvbxPBqyfzZCmOdRwsp0l+rXV7ePqZKq9ynpIPbQKBgFO/LZC5zE9k/vrK4egeVjzCNNugbQJGkJf8S49Nt3y7YJ2Cx0aCeE6qZqP/T8/Tk/IL1RF0LuP/DDnvVlFcJen0Hc5EpIkN2Pnzqv4s4EHdavmEO9MvwE6xbppQMPdkqekJvlmY47jMAbKkBzq3jZNrFAGqbeMVlwbHr6V7LGflAoGANFbzOnUMJwUfIdoI9uEG2QOTAcBb7vzt9MurO67wiTexOYadOSlcV1lQX3RKR9mCFJwy4kud0TN0gD++Ggl10eNB6f8JOF95e5+tWrtz88xZ5EalBOMfh+ATdKq8Q9MBSWZvO9bizhW1dhZZds/QmHgEItdwsTKDAq1PEiXhD0c="
|
||||
],
|
||||
"certificate": [
|
||||
"MIICnTCCAYUCBgGTulJDCDANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxMjEwMDExM1oXDTM0MTIxMjEwMDI1M1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALp4C+KLC8j/GxOjEio/GTCUxvFgYdytv8QeQSWAmHOz9QiDkWSPaP7ykMdUJz/gl5CCp50dpMyMwtK506pSDpGmX4Zkp+dIxubzQUvaj0/llO1Ht6isbliRcHGhVOUhCWsCR6pwzyvqZLZJMZLnXjB8+omij7PsCnG360Sevt2txakEHRxEIOCI1VPKQWZmoNXOyR2sojOejk+cuo5hOSb2OtPefYj62T10kzFN4TaIlcHciukMHSvv9MKzuvNVYSD/rtqXvdp0PobIDEkkCXoC8dVLBBMlPO7Mm5Rvqd8wCkkvpLdp74lf2tnGIojBNC3ZUN5ZyrEOLdWOsmQYktkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAPhPdLFcXdQT4k06oXB06ZSJ8AkZNXLvQFWCHXI34OmrS2yTse+dLqrqehnC3kPwxElVmawoUVc1sbsk7fUnspfM+Xw20PaABZu4MO2m5TB98f1hEkezP9fSqgPeuWJgTL8ZW5kkZyiD3IaZoqyxzYXaFxKHhU455g+k2+DO+N6FreVKcYz12Q5EMaxZ6U1neZAo3vicNxM3/TA5V8sPK8+oKvon7v5OyjpOH0goJo9v/klKeUk36h4u2h1S67IhVSU7tfzVFYrpns1JhrwGZ2xavVqEoqX8zFp3GKz3yVXkwHRHlrzYkZoGn21rm5boXIP3wEB7yXZbXWTiUko/IFw=="
|
||||
],
|
||||
"priority": ["100"],
|
||||
"algorithm": ["RSA-OAEP"]
|
||||
}
|
||||
@ -1707,6 +1767,8 @@
|
||||
"providerId": "aes-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["c36222c6-6a43-4d32-9d44-d5d355e5cabd"],
|
||||
"secret": ["rzL4qUQ7wTEkZDbgt595VA"],
|
||||
"priority": ["100"]
|
||||
}
|
||||
},
|
||||
@ -1716,6 +1778,10 @@
|
||||
"providerId": "hmac-generated",
|
||||
"subComponents": {},
|
||||
"config": {
|
||||
"kid": ["06532a54-c310-41c1-829c-58776ce2ab4a"],
|
||||
"secret": [
|
||||
"9v1ZjFhEFH6UpY6ncFkaCbqJYHMyI4tA0cvx4GuQ5KtMXYbimitSSVDqxIKwa-gBC_8bY2O4FQfpmp1Qn1-L4fFmPFfIF3ZKsO16263BwpADo_FNSBTte8Le4gJLylqFULdsn3ye17FHyq5Jjms_OTt3opzcDLNduCuK22GBBsU"
|
||||
],
|
||||
"priority": ["100"],
|
||||
"algorithm": ["HS512"]
|
||||
}
|
||||
@ -2385,7 +2451,7 @@
|
||||
"clientSessionMaxLifespan": "0",
|
||||
"organizationsEnabled": "false"
|
||||
},
|
||||
"keycloakVersion": "26.0.6",
|
||||
"keycloakVersion": "26.0.7",
|
||||
"userManagedAccessAllowed": false,
|
||||
"organizationsEnabled": false,
|
||||
"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 { exclude } from "tsafe/exclude";
|
||||
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
|
||||
import { CONTAINER_NAME, KEYCLOAKIFY_SPA_DEV_SERVER_PORT } from "../shared/constants";
|
||||
import {
|
||||
CONTAINER_NAME,
|
||||
KEYCLOAKIFY_SPA_DEV_SERVER_PORT,
|
||||
KEYCLOAKIFY_LOGIN_JAR_BASENAME,
|
||||
TEST_APP_URL
|
||||
} from "../shared/constants";
|
||||
import { SemVer } from "../tools/SemVer";
|
||||
import { assert, type Equals } from "tsafe/assert";
|
||||
import * as fs from "fs";
|
||||
@ -9,8 +13,7 @@ import {
|
||||
join as pathJoin,
|
||||
relative as pathRelative,
|
||||
sep as pathSep,
|
||||
basename as pathBasename,
|
||||
dirname as pathDirname
|
||||
basename as pathBasename
|
||||
} from "path";
|
||||
import * as child_process from "child_process";
|
||||
import chalk from "chalk";
|
||||
@ -28,6 +31,9 @@ import { existsAsync } from "../tools/fs.existsAsync";
|
||||
import { rm } from "../tools/fs.rm";
|
||||
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: {
|
||||
buildContext: BuildContext;
|
||||
@ -91,9 +97,32 @@ export async function command(params: {
|
||||
|
||||
const { cliCommandOptions, buildContext } = params;
|
||||
|
||||
const availableTags = await getSupportedDockerImageTags({
|
||||
buildContext
|
||||
});
|
||||
|
||||
const { dockerImageTag } = await (async () => {
|
||||
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) {
|
||||
@ -108,50 +137,84 @@ export async function command(params: {
|
||||
"On which version of Keycloak do you want to test your theme?"
|
||||
),
|
||||
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")
|
||||
);
|
||||
|
||||
const { keycloakVersion } = await promptKeycloakVersion({
|
||||
startingFromMajor: 18,
|
||||
excludeMajorVersions: [22],
|
||||
doOmitPatch: true,
|
||||
buildContext
|
||||
const { value: tag } = await cliSelect<string>({
|
||||
values: availableTags
|
||||
}).catch(() => {
|
||||
process.exit(-1);
|
||||
});
|
||||
|
||||
console.log(`→ ${keycloakVersion}`);
|
||||
console.log(`→ ${tag}`);
|
||||
|
||||
return { dockerImageTag: keycloakVersion };
|
||||
return { dockerImageTag: tag };
|
||||
})();
|
||||
|
||||
const keycloakMajorVersionNumber = (() => {
|
||||
if (buildContext.startKeycloakOptions.dockerImage === undefined) {
|
||||
return SemVer.parse(dockerImageTag).major;
|
||||
}
|
||||
|
||||
const { tag } = buildContext.startKeycloakOptions.dockerImage;
|
||||
|
||||
const [wrap] = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
|
||||
const [wrap] = getSupportedKeycloakMajorVersions()
|
||||
.map(majorVersionNumber => ({
|
||||
majorVersionNumber,
|
||||
index: tag.indexOf(`${majorVersionNumber}`)
|
||||
index: dockerImageTag.indexOf(`${majorVersionNumber}`)
|
||||
}))
|
||||
.filter(({ index }) => index !== -1)
|
||||
.sort((a, b) => a.index - b.index);
|
||||
|
||||
if (wrap === undefined) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Could not determine the major Keycloak version number from the docker image tag ${tag}. Assuming 25`
|
||||
)
|
||||
);
|
||||
return 25;
|
||||
try {
|
||||
const version = SemVer.parse(dockerImageTag);
|
||||
|
||||
console.error(
|
||||
chalk.yellow(
|
||||
`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;
|
||||
})();
|
||||
|
||||
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({
|
||||
buildContext
|
||||
@ -189,154 +252,48 @@ export async function command(params: {
|
||||
|
||||
assert(jarFilePath !== undefined);
|
||||
|
||||
const extensionJarFilePaths = 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;
|
||||
const extensionJarFilePaths = [
|
||||
...(keycloakMajorVersionNumber <= 20
|
||||
? (console.log(
|
||||
chalk.yellow(
|
||||
"WARNING: With older version of keycloak your changes to the realm configuration are not persisted"
|
||||
)
|
||||
),
|
||||
[])
|
||||
: [
|
||||
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": {
|
||||
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");
|
||||
}
|
||||
assert<Equals<typeof extensionJar, never>>(false);
|
||||
})
|
||||
))
|
||||
];
|
||||
|
||||
async function extractThemeResourcesFromJar() {
|
||||
await extractArchive({
|
||||
@ -376,9 +333,7 @@ export async function command(params: {
|
||||
});
|
||||
} catch {}
|
||||
|
||||
const DEFAULT_PORT = 8080;
|
||||
const port =
|
||||
cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT;
|
||||
const port = cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? 8080;
|
||||
|
||||
const doStartDevServer = (() => {
|
||||
const hasSpaUi =
|
||||
@ -434,8 +389,15 @@ export async function command(params: {
|
||||
const dockerRunArgs: string[] = [
|
||||
`-p${SPACE_PLACEHOLDER}${port}:8080`,
|
||||
`--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`,
|
||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`,
|
||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`,
|
||||
...(keycloakMajorVersionNumber >= 26
|
||||
? [
|
||||
`-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
|
||||
? []
|
||||
: [
|
||||
@ -451,7 +413,7 @@ export async function command(params: {
|
||||
...(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`,
|
||||
...extensionJarFilePaths.map(
|
||||
@ -526,7 +488,14 @@ export async function command(params: {
|
||||
{ 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));
|
||||
|
||||
@ -573,9 +542,9 @@ export async function command(params: {
|
||||
`${chalk.green("Your theme is accessible at:")}`,
|
||||
`${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}`);
|
||||
}
|
||||
if (kcHttpRelativePath !== undefined) {
|
||||
@ -584,13 +553,20 @@ export async function command(params: {
|
||||
kcHttpRelativePath
|
||||
);
|
||||
}
|
||||
if (realmName !== "myrealm") {
|
||||
url.searchParams.set("realm", realmName);
|
||||
}
|
||||
|
||||
if (clientName !== "myclient") {
|
||||
url.searchParams.set("client", clientName);
|
||||
}
|
||||
|
||||
return url.href;
|
||||
})()
|
||||
)}`,
|
||||
"",
|
||||
"You can login with the following credentials:",
|
||||
`- username: ${chalk.cyan.bold("testuser")}`,
|
||||
`- username: ${chalk.cyan.bold(username)}`,
|
||||
`- password: ${chalk.cyan.bold("password123")}`,
|
||||
"",
|
||||
`Watching for changes in ${chalk.bold(
|
||||
|
Loading…
x
Reference in New Issue
Block a user