Compare commits

...

31 Commits

Author SHA1 Message Date
70570faed6 Bump version 2024-12-16 18:04:01 +01:00
5d3b7c9a82 Add necessary token claim to access admin in dev mode 2024-12-16 18:04:01 +01:00
95b9b12a3b Try to fix error on windows 2024-12-16 18:04:01 +01:00
0e027055cb Bump version 2024-12-15 19:48:42 +01:00
e47b002535 #744 2024-12-15 19:48:23 +01:00
8dd6dcd1fc Merge pull request #745 from keycloakify/keycloak_config_persistance
Keycloak config persistance
2024-12-15 19:45:52 +01:00
10cfa1cf41 Update default realm configs 2024-12-15 19:45:05 +01:00
3938584aeb Update default realm configs 2024-12-15 18:43:53 +01:00
163b060dc5 Additional teaks 2024-12-15 18:15:36 +01:00
67f8ae41fc Update prepare realm script 2024-12-15 17:42:45 +01:00
b6e9fe2585 Update default realm config for kc 26 2024-12-15 13:28:05 +01:00
5b83bd8fa9 Update dump realm local script 2024-12-15 13:27:49 +01:00
d0f43b6318 Add logging and debug for backup configuration process 2024-12-15 13:11:01 +01:00
df338ed6a0 Improve ordering to minimize diff 2024-12-15 12:28:09 +01:00
295994d02a Use KC_BOOTSTRAP_ADMIN_ in newer keycloak 2024-12-15 11:57:45 +01:00
f9e15f93c4 Fix spelling mistake 2024-12-15 11:49:33 +01:00
2659cf391c Fix schema validation error 2024-12-15 11:47:59 +01:00
76416ddd5b Put persisted realm configs in .keycloakify 2024-12-15 11:45:00 +01:00
8e8a0ccf54 Store https://my-theme.keycloakify.dev as a constant 2024-12-15 11:38:50 +01:00
db0ec954df Fix zod schema error 2024-12-15 11:34:41 +01:00
dc942aa5de Implement cache for fetching available docker images tags 2024-12-15 08:53:54 +01:00
029cfcb591 Fix fetching of keycloak versions 2024-12-14 18:37:54 +01:00
b1b6919395 Assuming latest supported 2024-12-14 14:44:30 +01:00
9185740d35 Keycloak config persistance implemented (to test) 2024-12-14 14:36:11 +01:00
8d59fe7b67 Change structure 2024-12-13 12:16:41 +01:00
92b505dd56 Load custom extention for logging realm change 2024-12-13 12:07:21 +01:00
c0e6661d3d Add function to dump the realm config 2024-12-13 11:31:01 +01:00
0cae2c68d8 Add utils to edit the realm 2024-12-13 09:07:11 +01:00
1e43343529 Update keycloak 26 realm default config (fmt) 2024-12-12 11:19:06 +01:00
0a74dca7c2 Prettier ignore realm default config 2024-12-12 11:16:01 +01:00
a66a373256 Update dump-keycloak-realm internal script https://github.com/keycloak/keycloak/issues/33800 2024-12-10 04:12:56 +01:00
24 changed files with 2061 additions and 498 deletions

View File

@ -12,4 +12,5 @@ node_modules/
/sample_react_project/ /sample_react_project/
/sample_custom_react_project/ /sample_custom_react_project/
/keycloakify_starter_test/ /keycloakify_starter_test/
/.storybook/static/keycloak-resources/ /.storybook/static/keycloak-resources/
/src/bin/start-keycloak/*.json

View File

@ -1,6 +1,6 @@
{ {
"name": "keycloakify", "name": "keycloakify",
"version": "11.4.5", "version": "11.5.1",
"description": "Framework to create custom Keycloak UIs", "description": "Framework to create custom Keycloak UIs",
"repository": { "repository": {
"type": "git", "type": "git",

View 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);
}

View File

@ -7,6 +7,7 @@ import { createAccountV1Dir } from "./createAccountV1Dir";
import chalk from "chalk"; import chalk from "chalk";
import { run } from "../shared/run"; import { run } from "../shared/run";
import { vendorFrontendDependencies } from "./vendorFrontendDependencies"; import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
import { downloadKeycloakifyLogging } from "./downloadKeycloakifyLogging";
(async () => { (async () => {
console.log(chalk.cyan("Building Keycloakify...")); console.log(chalk.cyan("Building Keycloakify..."));
@ -148,9 +149,6 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
fs.cpSync(dirBasename, destDirPath, { recursive: true }); fs.cpSync(dirBasename, destDirPath, { recursive: true });
} }
await createPublicKeycloakifyDevResourcesDir();
await createAccountV1Dir();
transformCodebase({ transformCodebase({
srcDirPath: join("stories"), srcDirPath: join("stories"),
destDirPath: join("dist", "stories"), destDirPath: join("dist", "stories"),
@ -163,6 +161,12 @@ import { vendorFrontendDependencies } from "./vendorFrontendDependencies";
} }
}); });
await createPublicKeycloakifyDevResourcesDir();
await createAccountV1Dir();
await downloadKeycloakifyLogging({
distDirPath: join(process.cwd(), "dist")
});
console.log( console.log(
chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`) chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
); );

View File

@ -1,65 +1,15 @@
import { CONTAINER_NAME } from "../src/bin/shared/constants"; import { CONTAINER_NAME } from "../src/bin/shared/constants";
import child_process from "child_process"; import child_process from "child_process";
import { SemVer } from "../src/bin/tools/SemVer"; import { SemVer } from "../src/bin/tools/SemVer";
import { join as pathJoin, relative as pathRelative } from "path"; import { dumpContainerConfig } from "../src/bin/start-keycloak/realmConfig/dumpContainerConfig";
import { cacheDirPath } from "./shared/cacheDirPath";
import { runPrettier } from "../src/bin/tools/runPrettier";
import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath";
import { join as pathJoin } from "path";
import * as fs from "fs";
import chalk from "chalk"; import chalk from "chalk";
import { Deferred } from "evt/tools/Deferred";
import { assert, is } from "tsafe/assert";
import { run } from "./shared/run";
(async () => { (async () => {
{
const dCompleted = new Deferred<void>();
const child = child_process.spawn(
"docker",
[
...["exec", CONTAINER_NAME],
...["/opt/keycloak/bin/kc.sh", "export"],
...["--dir", "/tmp"],
...["--realm", "myrealm"],
...["--users", "realm_file"]
],
{ shell: true }
);
let output = "";
const onExit = (code: number | null) => {
dCompleted.reject(new Error(`Exited with code ${code}`));
};
child.on("exit", onExit);
child.stdout.on("data", data => {
const outputStr = data.toString("utf8");
if (outputStr.includes("Export finished successfully")) {
child.removeListener("exit", onExit);
child.kill();
dCompleted.resolve();
}
output += outputStr;
});
child.stderr.on("data", data => (output += chalk.red(data.toString("utf8"))));
try {
await dCompleted.pr;
} catch (error) {
assert(is<Error>(error));
console.log(chalk.red(error.message));
console.log(output);
process.exit(1);
}
}
const keycloakMajorVersionNumber = SemVer.parse( const keycloakMajorVersionNumber = SemVer.parse(
child_process child_process
.execSync(`docker inspect --format '{{.Config.Image}}' ${CONTAINER_NAME}`) .execSync(`docker inspect --format '{{.Config.Image}}' ${CONTAINER_NAME}`)
@ -68,19 +18,32 @@ import { run } from "./shared/run";
.split(":")[1] .split(":")[1]
).major; ).major;
const targetFilePath = pathRelative( const parsedRealmJson = await dumpContainerConfig({
process.cwd(), buildContext: {
pathJoin( cacheDirPath
__dirname, },
"..", keycloakMajorVersionNumber,
"src", realmName: "myrealm"
"bin", });
"start-keycloak",
`myrealm-realm-${keycloakMajorVersionNumber}.json` let sourceCode = JSON.stringify(parsedRealmJson, null, 2);
)
const filePath = pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak",
"realmConfig",
"defaultConfig",
`realm-kc-${keycloakMajorVersionNumber}.json`
); );
run(`docker cp ${CONTAINER_NAME}:/tmp/myrealm-realm.json ${targetFilePath}`); sourceCode = await runPrettier({
sourceCode,
filePath
});
console.log(`${chalk.green(`✓ Exported realm to`)} ${chalk.bold(targetFilePath)}`); fs.writeFileSync(filePath, Buffer.from(sourceCode, "utf8"));
console.log(chalk.green(`Realm config dumped to ${filePath}`));
})(); })();

View File

@ -81,3 +81,9 @@ export const CUSTOM_HANDLER_ENV_NAMES = {
export const KEYCLOAK_THEME = "keycloak-theme"; export const KEYCLOAK_THEME = "keycloak-theme";
export const KEYCLOAKIFY_SPA_DEV_SERVER_PORT = "KEYCLOAKIFY_SPA_DEV_SERVER_PORT"; export const KEYCLOAKIFY_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";

View 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
};
})();

View File

@ -0,0 +1,136 @@
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?: {
id: string;
name: string;
protocol: string; // "openid-connect" or something else
protocolMapper: string; // "oidc-hardcoded-claim-mapper" or something else
consentRequired: boolean;
config?: Record<string, string>;
}[];
}[];
};
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.object({
id: z.string(),
name: z.string(),
protocol: z.string(),
protocolMapper: z.string(),
consentRequired: z.boolean(),
config: z.record(z.string()).optional()
})
)
.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;
}

View File

@ -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
})
});
}

View File

@ -0,0 +1 @@
export * from "./defaultConfig";

View File

@ -73,7 +73,7 @@
"composites": { "composites": {
"realm": ["offline_access", "uma_authorization"], "realm": ["offline_access", "uma_authorization"],
"client": { "client": {
"account": ["delete-account", "view-profile", "manage-account"] "account": ["view-profile", "manage-account", "delete-account"]
} }
}, },
"clientRole": false, "clientRole": false,
@ -398,6 +398,26 @@
"otpPolicyLookAheadWindow": 1, "otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30, "otpPolicyPeriod": 30,
"otpSupportedApplications": ["FreeOTP", "Google Authenticator"], "otpSupportedApplications": ["FreeOTP", "Google Authenticator"],
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
"webAuthnPolicyRequireResidentKey": "not specified",
"webAuthnPolicyUserVerificationRequirement": "not specified",
"webAuthnPolicyCreateTimeout": 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
"webAuthnPolicyPasswordlessCreateTimeout": 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
"users": [ "users": [
{ {
"id": "00a62e75-bcc1-419a-a292-63ee5d161ed3", "id": "00a62e75-bcc1-419a-a292-63ee5d161ed3",
@ -422,30 +442,43 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"create-client",
"view-identity-providers",
"manage-realm",
"query-groups",
"manage-clients",
"query-users",
"realm-admin",
"view-authorization",
"view-events",
"view-clients",
"view-realm",
"manage-events",
"query-realms",
"query-clients",
"manage-identity-providers",
"manage-users",
"view-users",
"impersonation",
"manage-authorization"
],
"broker": ["read-token"],
"account": [
"view-profile",
"manage-account-links",
"view-applications",
"manage-consent",
"delete-account",
"manage-account",
"view-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
], ],
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
"webAuthnPolicyRequireResidentKey": "not specified",
"webAuthnPolicyUserVerificationRequirement": "not specified",
"webAuthnPolicyCreateTimeout": 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
"webAuthnPolicyPasswordlessCreateTimeout": 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
"scopeMappings": [ "scopeMappings": [
{ {
"clientScope": "offline_access", "clientScope": "offline_access",
@ -505,8 +538,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -518,6 +555,7 @@
"frontchannelLogout": false, "frontchannelLogout": false,
"protocol": "openid-connect", "protocol": "openid-connect",
"attributes": { "attributes": {
"post.logout.redirect.uris": "+",
"pkce.code.challenge.method": "S256" "pkce.code.challenge.method": "S256"
}, },
"authenticationFlowBindingOverrides": {}, "authenticationFlowBindingOverrides": {},
@ -636,7 +674,7 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter", "post.logout.redirect.uris": "+",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.revoke.offline.tokens": "false" "backchannel.logout.revoke.offline.tokens": "false"
@ -694,8 +732,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -707,6 +749,7 @@
"frontchannelLogout": false, "frontchannelLogout": false,
"protocol": "openid-connect", "protocol": "openid-connect",
"attributes": { "attributes": {
"post.logout.redirect.uris": "+",
"pkce.code.challenge.method": "S256" "pkce.code.challenge.method": "S256"
}, },
"authenticationFlowBindingOverrides": {}, "authenticationFlowBindingOverrides": {},
@ -757,7 +800,8 @@
"consentRequired": false, "consentRequired": false,
"config": { "config": {
"id.token.claim": "true", "id.token.claim": "true",
"access.token.claim": "true" "access.token.claim": "true",
"userinfo.token.claim": "true"
} }
} }
] ]
@ -1205,6 +1249,7 @@
"consentRequired": false, "consentRequired": false,
"config": { "config": {
"multivalued": "true", "multivalued": "true",
"userinfo.token.claim": "true",
"user.attribute": "foo", "user.attribute": "foo",
"id.token.claim": "true", "id.token.claim": "true",
"access.token.claim": "true", "access.token.claim": "true",
@ -1271,11 +1316,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1291,14 +1336,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-user-attribute-mapper",
"oidc-usermodel-property-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"saml-user-attribute-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-sha256-pairwise-sub-mapper", "oidc-sha256-pairwise-sub-mapper",
"saml-role-list-mapper", "saml-role-list-mapper"
"oidc-usermodel-property-mapper"
] ]
} }
}, },
@ -1347,14 +1392,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-usermodel-property-mapper",
"oidc-address-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"oidc-usermodel-property-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"saml-role-list-mapper" "oidc-sha256-pairwise-sub-mapper",
"saml-role-list-mapper",
"oidc-address-mapper",
"saml-user-attribute-mapper"
] ]
} }
}, },
@ -1394,6 +1439,12 @@
"providerId": "rsa-generated", "providerId": "rsa-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"privateKey": [
"MIIEpAIBAAKCAQEA+VQAcuaRivrzLVI8H/tt8PKbtRznTQKmmxOdLRR37leY/ph7sFnEmZt6K02Rvut7R0dxUFtTdiEHUKxhyM8CADMznGUjDYj/EXQzLfZ3LEwbwmR39zp+fZL/H24UDO03zt23Ov9C8Aly0ufXZ1Ic1c33KW6UtUEK/3M52pU8Y0daWdjx7nBj1eRlzWfVG+BYotTTWEnFJuEoZPFQMiXqeA5ob1zZdXjL5JDuGEiBsYjtiiaKbKL5545+FmEBnoCmWXqGu0qWxI2TzvV2dohxfl5KjNzRoKt40ydraiVk5rtBpoNDpeEApuphbokH5dJVwJ5cvWu1CSTnYPW2jXeG4wIDAQABAoIBAQDHV6AcPbhz8/xlafBkabQXBwHzJi7QZaQrLN1n44uX5jWOqP+LmdoULjjZUmWKzd98t+QjKUFrmzCsEYcE9G1XF5jWHA6Qjc3ReKRKxVm28wrmu0knQ39KizKrQGmLhEYwgRg0dU5heExzz6VrGD2xu8E3QRBocp6GauwAlXz4qcnTPHOl8OBPeDHAc0RUdaL5+jRLgKQzf9nnnKB19imBKP++zwrwFrkOZti2ZPs1I7j/ym27mHUbi8TDI2VepDX4QwjjC5a+v3vTsVAGE+1tUAZtqpxpIP9hiUkLH3ajyvp3typhnmZHklqsSZdwtRcK94WiMzL3TkiY70y8abMhAoGBAP8I4EQRXxcKfBn23eaRw8Cd4PFrOouz4zFbYLrBODsvXfku/jnQOMFD0If4IzT6y0FGgBd+t/yqnFJi98oZOKm3P8w+NZBXTbFLH8rgmsElXyS0+9LVMjVa7+UlqZB1eRZbUeLREp03Fsz1y2rflnoWgUnpDIlyhmJqGhCsJdebAoGBAPpFmJ9P42mUTeDWpCyCxgg0zpp6rlpAP8StqZkcvr7kYjhbWrJfJuxrTXtzTTA1zZ59L9EvEAxuug/gl9BkuZ11Uzg8ZLOr4gSuAJZlAORaxJlcoylmNMYIL1fP/K0dxhdO0eHZOpPVpBmGctgev2HBtWp9ZwzQ3DddKimZfNZZAoGAfNOOWSKbhT6HgXnYIHtl8YgUynUuYaR5ZfYQwTfDWwyTFVzP5+IndUjI71Qff1XlWBy2o0lNqmijPJveJlfz6PWdT01/kBd7GnTnqbgHZtPw3pmKzCW3fm/1DRZDCUbGLpAh4z9rufF1wnnnx3aKQ1VykId1sGySo+bEvTZVC1MCgYAlv6uWk/ksKpdYi2d14z+1aymieVClAj3cD4meM4y9xDrgXz8d2mZHkKO+NBT3aZYbCqzUs3GLPoRH8stTPm4UxuaHe+yAgTN1Gz2xcYih6OLwct2VV/oryH5Dk3Z8Mhp314amtxozxCydQP8/g9vABfS0HDgX4cTlgOLkJWeD+QKBgQDuRtsstQ4Q3yK44himPi1JQMMvbYAqyGgRxWH8G1Kr41DV2sQ4wt9CbYxeh6RwMsE+YYNMkTAw1kksUTugWdcDnYpcSVG7xHLJk8WMti0WTqI/7KlkoRehXXv18WJNEXaCr5mJTtJL9wuQcd8nhkEDrrCZubZiJzX9IDnEqZc4Mg=="
],
"certificate": [
"MIICnTCCAYUCBgGTy58etTANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE4Mzg0M1oXDTM0MTIxNTE4NDAyM1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPlUAHLmkYr68y1SPB/7bfDym7Uc500CppsTnS0Ud+5XmP6Ye7BZxJmbeitNkb7re0dHcVBbU3YhB1CsYcjPAgAzM5xlIw2I/xF0My32dyxMG8Jkd/c6fn2S/x9uFAztN87dtzr/QvAJctLn12dSHNXN9ylulLVBCv9zOdqVPGNHWlnY8e5wY9XkZc1n1RvgWKLU01hJxSbhKGTxUDIl6ngOaG9c2XV4y+SQ7hhIgbGI7Yomimyi+eeOfhZhAZ6Apll6hrtKlsSNk871dnaIcX5eSozc0aCreNMna2olZOa7QaaDQ6XhAKbqYW6JB+XSVcCeXL1rtQkk52D1to13huMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAH/nsEi88hFiNPCWYvTB3lERZpeUCbpDzAXQT/4TONmOw8zi7Cd2OlX8BGBFqjh/fESHv+adlzsY1mUdMvpVaYgHr3gYi8sBSrq5TMUfSYaWp4WCD7utiXXGprG08GCdbye1lpyyNnniWp12Bgjao+rtGamL/M1d6+WZTC+XL+H30u4VHURAiFBsAEoX6tlGV8ynhYOr/b8B43jy0/R0JfrzLjwSKEcA6RfKM7ozbZ0QZuQDALULymPIesrV4mvZ2Qwg4YgpAKaki9Sse45yiIhsIY0p5RnuNZRZnCbukyeBzIyDJobEBGhpui/KT2dqXBlRgRuOhCUf7OGCcPVHKNQ=="
],
"priority": ["100"] "priority": ["100"]
} }
}, },
@ -1403,6 +1454,12 @@
"providerId": "rsa-enc-generated", "providerId": "rsa-enc-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"privateKey": [
"MIIEogIBAAKCAQEAn82AU+InXwYlE8u9lMwhQghZB7oQ71Hg3PdFqS9ICGzw1u1JcENooCsZse55V6nqptdYF1oZA8QrxnhHzCVCGIqFHtXSoPGHVtozO3Fe1cVIVFm1D9TNS3JHe1C8SBQQT4hGItO5cjDyfGdK3x09RkoAcelrzH5uQ78zd0FKHkzbsTMsP2V8V94c35+ViIUjyGhH2T2BpIyGRLignL+6d0wHbw463L1Ewj/J9z8BtNLCH9PaVLWiGQARjlWyL9vtWBig9XXL0Z9tZUuoLihjh4StkXt2lQ++DKxUklsAjyenRAG5d72T2rY8MO5a1Z2ZSt8+s86D5esrAEIFZc9mqwIDAQABAoIBAAmmCcqGzCPDpjd0xMSYMqXfBSkfReh9RBtzXqRhc3L2yO/hMd7yYv3QvGNu56qwWreqJup6CSqeDJqWJpef5EbBDlqXRHltO+O1lwROyxATMlPNes4y5hZZFxHOBSBA/d8fdkSiDf9kDzANuIqSJGH7E93M3zJgq92xTLU1nvkHR/VYJQv+j+Pjye7MWvjIePfhwFeBqEWlWPTlw/080Mpfp8Hhbl6JeKjx2inkSphp43v4wR1Wmp+E2JIHF4P4sVXPPuPf3JDwg5uGOrROw1ziloD3jTI+LnQ+kRm6R2EbqRqqVsehXT7mZy2puQNqVc4vVqWQdxIErMBazYEpZOECgYEA+8PEcDiIPr2PTYZk+/jErRVYwsxyLgDJexPak7onLxLBJRNRnp1Uk6b1LXM6af5qp+Y510kyAe1k+9xkQLx1gW8rMka9rvVsM+1A2ACvF99V23sRw29CVxeFV/zNn83MinYPX5biUl6MkOX2PvWUhdwRGhKByjiYcAeBOsXkz3ECgYEAon2yYXGzph8Vb8Fetv0wFFbjQOixuL02OjVp/nU1XVE8Aw9BJ7uzA6GQ7akPG0HsaUq7AEHP1uUOsJWQTNQ8WYD9LDuDOl/JFqkG+zrmdUdm0mAIYyH1/GBqgaTLvMq78qqosua8BBJojEyoXDz69UBHpu7cwtUgmzRNQSYqgdsCgYASvD3JEBvrd1XLsh2ftqKEMtt5G5e/nqVfuFmCts6lrSKcbLSdNh4OItWJ/VIygxFSz0osoDDNfeoO6Ba5zox8BlbTlfoVpAPaVWSG7n4ZK7CK9bybq5LnQkPVCWYP51O6VhDMz0CmWozhV4ucoc/cqkTHiOsJrm6Bn71ZL1LYsQKBgFNb8qgk4YnGhoPHiuSLbR/yFzGUbqAciXZBMrg0vwS5iPT03XMZytOBDk2uHi7YmgTGLrsKCCrxZaDXiaiwdKliD/+iJEdNHmc+nXNDGzltQOWKGKNqp7wqZllOBqs6wkLSpCrrTec03mejZ/ex3Pj2WgvcnGpjVg/pO/zBLKtjAoGACzGQNEF93fabHQJTsHmb/g+jO2iumjF6ZIWzdFh2KzQABONcoBvy1MJNASFQj3iVy/8kEo4SfmexvMWLBW9igi2z1pHeHY32EuImzuc4xnVDm6dkmDdsO43Ex6CFBx8lM40H4l27mXu+EZRzGClUY8TnmV/FBGmX+LPtOiiwT7s="
],
"certificate": [
"MIICnTCCAYUCBgGTy58fHjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MTIxNTE4Mzg0M1oXDTM0MTIxNTE4NDAyM1owEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ/NgFPiJ18GJRPLvZTMIUIIWQe6EO9R4Nz3RakvSAhs8NbtSXBDaKArGbHueVep6qbXWBdaGQPEK8Z4R8wlQhiKhR7V0qDxh1baMztxXtXFSFRZtQ/UzUtyR3tQvEgUEE+IRiLTuXIw8nxnSt8dPUZKAHHpa8x+bkO/M3dBSh5M27EzLD9lfFfeHN+flYiFI8hoR9k9gaSMhkS4oJy/undMB28OOty9RMI/yfc/AbTSwh/T2lS1ohkAEY5Vsi/b7VgYoPV1y9GfbWVLqC4oY4eErZF7dpUPvgysVJJbAI8np0QBuXe9k9q2PDDuWtWdmUrfPrPOg+XrKwBCBWXPZqsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATwmKBzLiZiUjyB9BWUR4BCXh46DxsiM0BCublewlUFY6FBTn7ea6q3G+X3QP2WM6xa0oAmQz9dq1KChbIoC2WPbceAbwd5XZZfziWsRCv6+xPswtpHPIrsenz8TR4K4P73aeCC+vTVs/y+2tGPEVbnSkcNnOP71hRQGlt0LvjKlEetJSRyYz5depSdJOjl4F3ehpxQtTK/48xUVAytu9ZotJj6AUA7jWFlP5GHgoB+mPk6QTHNWddnc7BQx2FMvg151vxu722ywLh5Dh7WzgFhJNwkX4xpwzhfo0Q1gSygGTdZaJCGj5jfF+KwdiKpN04UxJ8OrRgJqklQgrSVnsgQ=="
],
"priority": ["100"], "priority": ["100"],
"algorithm": ["RSA-OAEP"] "algorithm": ["RSA-OAEP"]
} }
@ -1413,6 +1470,8 @@
"providerId": "aes-generated", "providerId": "aes-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["132fb843-59e9-4f36-ad55-5ce2d3a13fb3"],
"secret": ["ETyyqapnrkUsNXLQ-tBVKw"],
"priority": ["100"] "priority": ["100"]
} }
}, },
@ -1422,6 +1481,10 @@
"providerId": "hmac-generated", "providerId": "hmac-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["5110d380-c930-49d9-b91b-87f338f6170b"],
"secret": [
"uCpQrJvP5OBuTxXfDb4JRL0bCKpXUgfGn5vb8UvL-Sfs_sZ9rtvBmd6vuFWARqyezjJQtpoNlMv7sXgxkN-yxQ"
],
"priority": ["100"], "priority": ["100"],
"algorithm": ["HS256"] "algorithm": ["HS256"]
} }
@ -1454,7 +1517,7 @@
"defaultLocale": "en", "defaultLocale": "en",
"authenticationFlows": [ "authenticationFlows": [
{ {
"id": "f7f2b89b-43cb-491d-8e7c-f1814024a6da", "id": "223ce532-2038-4f24-a606-2a5c73f7bd65",
"alias": "Account verification options", "alias": "Account verification options",
"description": "Method with which to verity the existing account", "description": "Method with which to verity the existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1480,7 +1543,7 @@
] ]
}, },
{ {
"id": "17cdac6f-d2a3-4907-8d44-a42827610b63", "id": "57e47732-79cc-4d60-bee7-4f0b8fd44540",
"alias": "Authentication Options", "alias": "Authentication Options",
"description": "Authentication options.", "description": "Authentication options.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1514,7 +1577,7 @@
] ]
}, },
{ {
"id": "53a3e43f-9468-401f-8051-40f982d12f85", "id": "c2735d89-60c0-45a4-9b3c-ae5df17df395",
"alias": "Browser - Conditional OTP", "alias": "Browser - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1540,7 +1603,7 @@
] ]
}, },
{ {
"id": "26286808-3b7b-43df-b32e-af55a37af2e9", "id": "11a5a507-2b9a-443f-961b-dffd66f4318d",
"alias": "Direct Grant - Conditional OTP", "alias": "Direct Grant - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1566,7 +1629,7 @@
] ]
}, },
{ {
"id": "8a6a752a-9a9a-4d38-b1f8-edf0a9433490", "id": "963bd753-6ea7-4d93-ab56-30f9ab59d597",
"alias": "First broker login - Conditional OTP", "alias": "First broker login - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1592,7 +1655,7 @@
] ]
}, },
{ {
"id": "a6f6804c-4160-4a84-8a1f-c2747a2d3f27", "id": "1db6a489-a3b4-44c4-b480-1d1e8c123d20",
"alias": "Handle Existing Account", "alias": "Handle Existing Account",
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1618,7 +1681,7 @@
] ]
}, },
{ {
"id": "740baa9e-8328-4035-9e1a-8fc1616d1f0f", "id": "7a38f32d-4f34-450f-8f03-64802d7cb8f1",
"alias": "Reset - Conditional OTP", "alias": "Reset - Conditional OTP",
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1644,7 +1707,7 @@
] ]
}, },
{ {
"id": "e60187a8-3e16-4a0c-9daa-f3a4a1fcfdba", "id": "0df88739-3739-4d70-8893-47c546f19003",
"alias": "User creation or linking", "alias": "User creation or linking",
"description": "Flow for the existing/non-existing user alternatives", "description": "Flow for the existing/non-existing user alternatives",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1671,7 +1734,7 @@
] ]
}, },
{ {
"id": "d959d0c2-4004-4633-b280-f80d6423f574", "id": "35025424-e291-4c54-8a29-70aadba549ce",
"alias": "Verify Existing Account by Re-authentication", "alias": "Verify Existing Account by Re-authentication",
"description": "Reauthentication of existing account", "description": "Reauthentication of existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1697,7 +1760,7 @@
] ]
}, },
{ {
"id": "ba02689d-b9e8-4a4b-8fdd-0d1386b198fc", "id": "1813b7f2-c3c2-4b92-8ffc-9ff2d12186c6",
"alias": "browser", "alias": "browser",
"description": "browser based authentication", "description": "browser based authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1739,7 +1802,7 @@
] ]
}, },
{ {
"id": "f09ac92a-e091-4e84-9cd1-cb905ca57b89", "id": "954283ac-f1c2-40b6-a39f-bf23ff9f3ce8",
"alias": "clients", "alias": "clients",
"description": "Base authentication for clients", "description": "Base authentication for clients",
"providerId": "client-flow", "providerId": "client-flow",
@ -1781,7 +1844,7 @@
] ]
}, },
{ {
"id": "aaf72b22-cec4-4714-93d6-f54d5a986ab8", "id": "52a789ce-2cad-4f0f-93b2-295b7fd519f0",
"alias": "direct grant", "alias": "direct grant",
"description": "OpenID Connect Resource Owner Grant", "description": "OpenID Connect Resource Owner Grant",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1815,7 +1878,7 @@
] ]
}, },
{ {
"id": "c4a54bb3-f009-4231-a82b-376c2515e07e", "id": "5a6a71e1-9105-45b6-b5f0-52538461357b",
"alias": "docker auth", "alias": "docker auth",
"description": "Used by Docker clients to authenticate against the IDP", "description": "Used by Docker clients to authenticate against the IDP",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1833,7 +1896,7 @@
] ]
}, },
{ {
"id": "f55ded54-683a-4f5a-a101-9cfbd7b96781", "id": "8392b6e7-bdbf-4d7f-97b6-885761c200db",
"alias": "first broker login", "alias": "first broker login",
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1860,7 +1923,7 @@
] ]
}, },
{ {
"id": "931d5a82-378f-4533-8c69-2239a4acd047", "id": "52136d70-8d08-42ea-b04b-cf40ea2807aa",
"alias": "forms", "alias": "forms",
"description": "Username, password, otp and other auth forms.", "description": "Username, password, otp and other auth forms.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1886,7 +1949,7 @@
] ]
}, },
{ {
"id": "22b05374-f480-4ca8-aca8-9db8b6dd1729", "id": "26bbc7e6-ef01-4cdb-9dba-520e2f3f8993",
"alias": "http challenge", "alias": "http challenge",
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes", "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1912,7 +1975,7 @@
] ]
}, },
{ {
"id": "c0371832-e4b7-485e-bf23-6babe4c6ac83", "id": "f0887979-04eb-4033-8f19-0ffd8c8b7f6a",
"alias": "registration", "alias": "registration",
"description": "registration flow", "description": "registration flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1931,7 +1994,7 @@
] ]
}, },
{ {
"id": "4d0445da-073e-465e-b25b-af522915c73f", "id": "a3b7b94b-bfbf-4760-a8c9-7d9cd98d262e",
"alias": "registration form", "alias": "registration form",
"description": "registration form", "description": "registration form",
"providerId": "form-flow", "providerId": "form-flow",
@ -1973,7 +2036,7 @@
] ]
}, },
{ {
"id": "740d467f-4203-425b-8203-9bfd3eed25ae", "id": "dc68a665-2e51-4a22-aaad-bd693ddc77cc",
"alias": "reset credentials", "alias": "reset credentials",
"description": "Reset credentials for a user if they forgot their password or something", "description": "Reset credentials for a user if they forgot their password or something",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2015,7 +2078,7 @@
] ]
}, },
{ {
"id": "cf1a9af9-dadd-4cb9-a26e-fbbba216f8e1", "id": "ae6b73aa-1318-4ae8-a3d9-d01b5e7d957e",
"alias": "saml ecp", "alias": "saml ecp",
"description": "SAML ECP Profile Authentication Flow", "description": "SAML ECP Profile Authentication Flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2035,14 +2098,14 @@
], ],
"authenticatorConfig": [ "authenticatorConfig": [
{ {
"id": "4e65eb4b-9f0a-4ab8-98b2-6daf50cd1bf8", "id": "0c18de7f-0714-41f4-9a3f-ed4edd53ae9c",
"alias": "create unique user config", "alias": "create unique user config",
"config": { "config": {
"require.password.update.after.registration": "false" "require.password.update.after.registration": "false"
} }
}, },
{ {
"id": "5e8dc1c5-1489-4d39-bb75-9c499583b91b", "id": "65b3c8bb-34a4-4d19-b578-245dc8ff53ea",
"alias": "review profile config", "alias": "review profile config",
"config": { "config": {
"update.profile.on.first.login": "missing" "update.profile.on.first.login": "missing"
@ -2132,8 +2195,8 @@
"attributes": { "attributes": {
"cibaBackchannelTokenDeliveryMode": "poll", "cibaBackchannelTokenDeliveryMode": "poll",
"cibaAuthRequestedUserHint": "login_hint", "cibaAuthRequestedUserHint": "login_hint",
"oauth2DevicePollingInterval": "5",
"clientOfflineSessionMaxLifespan": "0", "clientOfflineSessionMaxLifespan": "0",
"oauth2DevicePollingInterval": "5",
"clientSessionIdleTimeout": "0", "clientSessionIdleTimeout": "0",
"userProfileEnabled": "true", "userProfileEnabled": "true",
"clientOfflineSessionIdleTimeout": "0", "clientOfflineSessionIdleTimeout": "0",

View File

@ -73,7 +73,7 @@
"composites": { "composites": {
"realm": ["offline_access", "uma_authorization"], "realm": ["offline_access", "uma_authorization"],
"client": { "client": {
"account": ["delete-account", "view-profile", "manage-account"] "account": ["view-profile", "manage-account", "delete-account"]
} }
}, },
"clientRole": false, "clientRole": false,
@ -435,13 +435,46 @@
"type": "password", "type": "password",
"userLabel": "My password", "userLabel": "My password",
"createdDate": 1716214710762, "createdDate": 1716214710762,
"secretData": "{\"value\":\"OaI4sKqQn+NZtS6N/bcqoZ8Q+ucpBby1n4XmzVmioKw=\",\"salt\":\"temixVCSbpA7Genml2KTAw==\",\"additionalParameters\":{}}", "secretData": "{\"value\":\"QzJjOdXU0L9Pdxdx1V5xUs7BY9beGlmN8NpR2qiWxbkjrQ434Q1GwSiJKekZQ/zrLDtNZ7sAbVu+SS+XIe9Zaw==\",\"salt\":\"x8cABpa0Hk/nJ2BPKdFXTg==\",\"additionalParameters\":{}}",
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
} }
], ],
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"create-client",
"view-identity-providers",
"manage-realm",
"query-groups",
"manage-clients",
"query-users",
"realm-admin",
"view-authorization",
"view-events",
"view-clients",
"view-realm",
"manage-events",
"query-realms",
"query-clients",
"manage-identity-providers",
"manage-users",
"view-users",
"impersonation",
"manage-authorization"
],
"broker": ["read-token"],
"account": [
"view-profile",
"manage-account-links",
"view-applications",
"manage-consent",
"delete-account",
"manage-account",
"view-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -507,8 +540,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -643,7 +680,6 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
@ -704,8 +740,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1284,11 +1324,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1304,14 +1344,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-full-name-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-property-mapper",
"oidc-address-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"oidc-usermodel-attribute-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"saml-role-list-mapper" "oidc-full-name-mapper",
"oidc-usermodel-property-mapper",
"oidc-usermodel-attribute-mapper",
"oidc-address-mapper",
"saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper"
] ]
} }
}, },
@ -1360,14 +1400,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-user-property-mapper",
"saml-user-attribute-mapper",
"oidc-full-name-mapper",
"oidc-sha256-pairwise-sub-mapper", "oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"oidc-address-mapper", "oidc-usermodel-property-mapper",
"saml-role-list-mapper", "saml-role-list-mapper",
"oidc-usermodel-property-mapper" "oidc-full-name-mapper",
"saml-user-property-mapper",
"oidc-address-mapper",
"saml-user-attribute-mapper"
] ]
} }
}, },
@ -1485,7 +1525,7 @@
"defaultLocale": "en", "defaultLocale": "en",
"authenticationFlows": [ "authenticationFlows": [
{ {
"id": "e134634e-f219-4df4-867c-8110688d8e56", "id": "1f4d4e13-1591-4751-8985-17886a8c98a9",
"alias": "Account verification options", "alias": "Account verification options",
"description": "Method with which to verity the existing account", "description": "Method with which to verity the existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1511,7 +1551,7 @@
] ]
}, },
{ {
"id": "a611a8eb-9626-4aa4-8b54-ee565ea6e5dc", "id": "126f07c3-1bcb-4a02-bf16-bb44674bf55d",
"alias": "Authentication Options", "alias": "Authentication Options",
"description": "Authentication options.", "description": "Authentication options.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1545,7 +1585,7 @@
] ]
}, },
{ {
"id": "d87cbb31-5c69-45c8-888d-f9649ebbbf97", "id": "eb3a08c8-5f99-49b6-b02b-16b62571f273",
"alias": "Browser - Conditional OTP", "alias": "Browser - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1571,7 +1611,7 @@
] ]
}, },
{ {
"id": "752ba282-a369-4592-92e8-b4287192dbbf", "id": "3dc19838-5025-4bbb-b569-b574bd5a8d90",
"alias": "Direct Grant - Conditional OTP", "alias": "Direct Grant - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1597,7 +1637,7 @@
] ]
}, },
{ {
"id": "2349282e-40ff-431a-984d-53911511e3d3", "id": "70d6fd40-d740-4dae-b0e6-350f8e9d4a1c",
"alias": "First broker login - Conditional OTP", "alias": "First broker login - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1623,7 +1663,7 @@
] ]
}, },
{ {
"id": "4ff5463d-26d9-4219-ba85-41464401098f", "id": "6e24dcb3-5818-483c-8e44-883858171901",
"alias": "Handle Existing Account", "alias": "Handle Existing Account",
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1649,7 +1689,7 @@
] ]
}, },
{ {
"id": "87bb6c6d-cca8-4832-b5ab-67ecb9454a42", "id": "ac6254cd-403b-457b-b308-22a2a0e4f99d",
"alias": "Reset - Conditional OTP", "alias": "Reset - Conditional OTP",
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1675,7 +1715,7 @@
] ]
}, },
{ {
"id": "1fc3d028-0e0a-43a4-aaf9-ba7f7d60b409", "id": "485e74e6-9b3e-4b2c-a9b9-927802dc4f06",
"alias": "User creation or linking", "alias": "User creation or linking",
"description": "Flow for the existing/non-existing user alternatives", "description": "Flow for the existing/non-existing user alternatives",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1702,7 +1742,7 @@
] ]
}, },
{ {
"id": "036aae59-641f-4799-9124-c7e5034af6c1", "id": "ff9bb879-1d6a-4d1c-9836-1e4fab6f8997",
"alias": "Verify Existing Account by Re-authentication", "alias": "Verify Existing Account by Re-authentication",
"description": "Reauthentication of existing account", "description": "Reauthentication of existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1728,7 +1768,7 @@
] ]
}, },
{ {
"id": "2e8b9f28-93b8-4368-84b0-1a8326daafe0", "id": "af8b2470-d581-401c-9984-762b966ebcc2",
"alias": "browser", "alias": "browser",
"description": "browser based authentication", "description": "browser based authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1770,7 +1810,7 @@
] ]
}, },
{ {
"id": "0b826105-8493-45ce-87b3-7d917d190b39", "id": "414dbda4-eb3f-4baa-b23a-d3423af1eae6",
"alias": "clients", "alias": "clients",
"description": "Base authentication for clients", "description": "Base authentication for clients",
"providerId": "client-flow", "providerId": "client-flow",
@ -1812,7 +1852,7 @@
] ]
}, },
{ {
"id": "bf6d9edd-48d8-4392-bbc8-4b17a6866074", "id": "1cae0c4b-8dfb-4f5d-a781-e74d0a13c940",
"alias": "direct grant", "alias": "direct grant",
"description": "OpenID Connect Resource Owner Grant", "description": "OpenID Connect Resource Owner Grant",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1846,7 +1886,7 @@
] ]
}, },
{ {
"id": "97e31722-dd11-42be-aa99-88788fa2dde6", "id": "e798b655-7d85-4b6b-aee7-1448a3e1e0ea",
"alias": "docker auth", "alias": "docker auth",
"description": "Used by Docker clients to authenticate against the IDP", "description": "Used by Docker clients to authenticate against the IDP",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1864,7 +1904,7 @@
] ]
}, },
{ {
"id": "3f45cf34-231f-4ea1-8e58-d636c451a76b", "id": "eb94b723-1041-426a-87bf-f7b4bd2f485d",
"alias": "first broker login", "alias": "first broker login",
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1891,7 +1931,7 @@
] ]
}, },
{ {
"id": "9bef2f7c-f989-4871-aaa7-18e2cfa73f22", "id": "452d1d5f-7632-44d7-bc89-77ff2b209b3e",
"alias": "forms", "alias": "forms",
"description": "Username, password, otp and other auth forms.", "description": "Username, password, otp and other auth forms.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1917,7 +1957,7 @@
] ]
}, },
{ {
"id": "0bfaa325-acde-4443-8bd8-1dc2ae759c5f", "id": "7c1b9e8f-6b57-49d1-a9a7-494862f93c0f",
"alias": "http challenge", "alias": "http challenge",
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes", "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1943,7 +1983,7 @@
] ]
}, },
{ {
"id": "37ddbe8c-abf3-4654-bd6d-ffabbeefbb98", "id": "2b38f34a-1739-499e-bb24-1dff96f32009",
"alias": "registration", "alias": "registration",
"description": "registration flow", "description": "registration flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1962,7 +2002,7 @@
] ]
}, },
{ {
"id": "5d7b4bc9-e93b-40da-aeb6-ba0c38392f1a", "id": "d26ae72b-a933-44dc-9927-1c82757004b2",
"alias": "registration form", "alias": "registration form",
"description": "registration form", "description": "registration form",
"providerId": "form-flow", "providerId": "form-flow",
@ -2004,7 +2044,7 @@
] ]
}, },
{ {
"id": "ee7a56e4-c827-4f24-8b8b-8476050b0b64", "id": "222ee8d6-1892-4768-9ada-720274b6bf9a",
"alias": "reset credentials", "alias": "reset credentials",
"description": "Reset credentials for a user if they forgot their password or something", "description": "Reset credentials for a user if they forgot their password or something",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2046,7 +2086,7 @@
] ]
}, },
{ {
"id": "360f0031-4c3b-4272-84ca-2172d430b4bc", "id": "e8b4d92c-27c1-4a9b-9b16-7ceb810fa230",
"alias": "saml ecp", "alias": "saml ecp",
"description": "SAML ECP Profile Authentication Flow", "description": "SAML ECP Profile Authentication Flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2066,14 +2106,14 @@
], ],
"authenticatorConfig": [ "authenticatorConfig": [
{ {
"id": "53630acd-a33a-40e3-8786-cf85464c6f9e", "id": "e5847a0b-855d-4d93-85fd-94714be3ed92",
"alias": "create unique user config", "alias": "create unique user config",
"config": { "config": {
"require.password.update.after.registration": "false" "require.password.update.after.registration": "false"
} }
}, },
{ {
"id": "c0d2b6a0-caad-4e90-b040-17cacdaf70bb", "id": "a2a18aa4-bd4c-4c2a-9286-e9d6c64f4812",
"alias": "review profile config", "alias": "review profile config",
"config": { "config": {
"update.profile.on.first.login": "missing" "update.profile.on.first.login": "missing"

View File

@ -73,7 +73,7 @@
"composites": { "composites": {
"realm": ["offline_access", "uma_authorization"], "realm": ["offline_access", "uma_authorization"],
"client": { "client": {
"account": ["delete-account", "view-profile", "manage-account"] "account": ["view-profile", "manage-account", "delete-account"]
} }
}, },
"clientRole": false, "clientRole": false,
@ -407,7 +407,7 @@
"otpPolicyLookAheadWindow": 1, "otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30, "otpPolicyPeriod": 30,
"otpPolicyCodeReusable": false, "otpPolicyCodeReusable": false,
"otpSupportedApplications": ["totpAppGoogleName", "totpAppFreeOTPName"], "otpSupportedApplications": ["totpAppFreeOTPName", "totpAppGoogleName"],
"webAuthnPolicyRpEntityName": "keycloak", "webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": ["ES256"], "webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "", "webAuthnPolicyRpId": "",
@ -452,6 +452,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"create-client",
"view-identity-providers",
"manage-realm",
"query-groups",
"manage-clients",
"query-users",
"realm-admin",
"view-authorization",
"view-events",
"view-clients",
"view-realm",
"manage-events",
"query-realms",
"query-clients",
"manage-identity-providers",
"manage-users",
"view-users",
"impersonation",
"manage-authorization"
],
"broker": ["read-token"],
"account": [
"view-profile",
"manage-account-links",
"view-applications",
"manage-consent",
"delete-account",
"manage-account",
"view-groups",
"view-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -517,8 +551,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -653,7 +691,6 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
@ -714,8 +751,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1294,11 +1335,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1314,14 +1355,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-user-property-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper",
"saml-user-attribute-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"saml-role-list-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"oidc-usermodel-property-mapper" "saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-property-mapper",
"oidc-usermodel-attribute-mapper",
"saml-user-property-mapper",
"saml-user-attribute-mapper"
] ]
} }
}, },
@ -1370,14 +1411,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"oidc-address-mapper",
"saml-role-list-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"oidc-usermodel-attribute-mapper", "saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"oidc-usermodel-property-mapper",
"oidc-address-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"oidc-usermodel-property-mapper" "oidc-usermodel-attribute-mapper"
] ]
} }
}, },
@ -1495,7 +1536,7 @@
"defaultLocale": "en", "defaultLocale": "en",
"authenticationFlows": [ "authenticationFlows": [
{ {
"id": "19317acb-fe8e-4c79-82bc-90e159273075", "id": "c40791b4-4d59-4df2-bebd-2b71e793704f",
"alias": "Account verification options", "alias": "Account verification options",
"description": "Method with which to verity the existing account", "description": "Method with which to verity the existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1521,7 +1562,7 @@
] ]
}, },
{ {
"id": "122857d2-33da-4086-8acb-cb0e303aaf1b", "id": "8813b6d1-8b88-4672-b29b-8420ce3f3975",
"alias": "Authentication Options", "alias": "Authentication Options",
"description": "Authentication options.", "description": "Authentication options.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1555,7 +1596,7 @@
] ]
}, },
{ {
"id": "abf5dd35-4791-4268-a10c-5f4b6a06b84a", "id": "a9937c40-a1ee-4c57-adf7-ede0a9983953",
"alias": "Browser - Conditional OTP", "alias": "Browser - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1581,7 +1622,7 @@
] ]
}, },
{ {
"id": "a18daeec-a33c-4a43-b014-10c84ec69b81", "id": "2d494b5a-eb73-40d0-94d3-a8d8024a7db4",
"alias": "Direct Grant - Conditional OTP", "alias": "Direct Grant - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1607,7 +1648,7 @@
] ]
}, },
{ {
"id": "e9f032a7-32f7-457c-becf-011a1a35cc6a", "id": "2e977f5a-8110-412b-b704-3e15164dbb1b",
"alias": "First broker login - Conditional OTP", "alias": "First broker login - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication", "description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1633,7 +1674,7 @@
] ]
}, },
{ {
"id": "9db65b7c-98ca-4003-beea-611038831ffe", "id": "6f171b4b-8723-4e6d-bb1e-6b4293a7bb3f",
"alias": "Handle Existing Account", "alias": "Handle Existing Account",
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1659,7 +1700,7 @@
] ]
}, },
{ {
"id": "7bd0854c-d7ae-43d7-a1ae-7b759a34cb1d", "id": "2dbb7f27-757d-4178-8217-4a24fdb0163c",
"alias": "Reset - Conditional OTP", "alias": "Reset - Conditional OTP",
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1685,7 +1726,7 @@
] ]
}, },
{ {
"id": "2de1a450-fe98-443a-9c6c-d24d8a7ebcb3", "id": "7295aaf7-acf4-4b78-8186-d2415ea4ede0",
"alias": "User creation or linking", "alias": "User creation or linking",
"description": "Flow for the existing/non-existing user alternatives", "description": "Flow for the existing/non-existing user alternatives",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1712,7 +1753,7 @@
] ]
}, },
{ {
"id": "7b3efad5-4b7d-4385-a41c-fecc73afdcc4", "id": "e0d34d7c-7bbb-4847-8864-fbd97a1f3e89",
"alias": "Verify Existing Account by Re-authentication", "alias": "Verify Existing Account by Re-authentication",
"description": "Reauthentication of existing account", "description": "Reauthentication of existing account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1738,7 +1779,7 @@
] ]
}, },
{ {
"id": "de93418e-8f28-4099-b15e-ad36ec194796", "id": "5f3d0fb0-d95e-4841-89d3-a27d0cdbbcb4",
"alias": "browser", "alias": "browser",
"description": "browser based authentication", "description": "browser based authentication",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1780,7 +1821,7 @@
] ]
}, },
{ {
"id": "0dd3345c-6e82-4c3a-a39a-d49ae1f5c409", "id": "c246380d-af25-4151-ab19-1f1e5b553008",
"alias": "clients", "alias": "clients",
"description": "Base authentication for clients", "description": "Base authentication for clients",
"providerId": "client-flow", "providerId": "client-flow",
@ -1822,7 +1863,7 @@
] ]
}, },
{ {
"id": "87fb4dd0-5326-47a1-b670-982f4872ff89", "id": "abacf398-0f1f-4f28-a310-8d306d588048",
"alias": "direct grant", "alias": "direct grant",
"description": "OpenID Connect Resource Owner Grant", "description": "OpenID Connect Resource Owner Grant",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1856,7 +1897,7 @@
] ]
}, },
{ {
"id": "344723b3-4ab1-4999-abdd-32398e82327b", "id": "a0f87683-619a-44d4-8b4f-4b053bba2346",
"alias": "docker auth", "alias": "docker auth",
"description": "Used by Docker clients to authenticate against the IDP", "description": "Used by Docker clients to authenticate against the IDP",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1874,7 +1915,7 @@
] ]
}, },
{ {
"id": "f3341938-caf9-4c8a-9cd5-eb34609809ab", "id": "e8820c7c-22a7-4618-beb7-3e09be72c00c",
"alias": "first broker login", "alias": "first broker login",
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1901,7 +1942,7 @@
] ]
}, },
{ {
"id": "ba7b7357-e324-4b71-9bda-f8512a760e02", "id": "cac00c38-ee44-44c9-b95e-cc755bab36ef",
"alias": "forms", "alias": "forms",
"description": "Username, password, otp and other auth forms.", "description": "Username, password, otp and other auth forms.",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1927,7 +1968,7 @@
] ]
}, },
{ {
"id": "134971e6-bf63-432c-806e-74ca4fb09963", "id": "688cde36-507e-4a68-afdf-18ec4ad626a7",
"alias": "http challenge", "alias": "http challenge",
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes", "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1953,7 +1994,7 @@
] ]
}, },
{ {
"id": "6ea9e2cf-5684-4c65-8c07-930d1cbb0b46", "id": "e058697c-f450-4f14-ae64-04e9299fa24f",
"alias": "registration", "alias": "registration",
"description": "registration flow", "description": "registration flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -1972,7 +2013,7 @@
] ]
}, },
{ {
"id": "67e3c8c7-1b5e-4119-84a2-e90876293150", "id": "ad768088-32c9-4979-90dd-61bf111fd72e",
"alias": "registration form", "alias": "registration form",
"description": "registration form", "description": "registration form",
"providerId": "form-flow", "providerId": "form-flow",
@ -2014,7 +2055,7 @@
] ]
}, },
{ {
"id": "fc6d48ec-a1f1-41b1-9310-54f58861d5aa", "id": "47d4b090-f965-4588-b5bc-029ccb59876f",
"alias": "reset credentials", "alias": "reset credentials",
"description": "Reset credentials for a user if they forgot their password or something", "description": "Reset credentials for a user if they forgot their password or something",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2056,7 +2097,7 @@
] ]
}, },
{ {
"id": "80b1d464-c2ec-4eb1-82e8-32cbede779a8", "id": "1f68feec-7f99-4c49-afe6-45d46684ca21",
"alias": "saml ecp", "alias": "saml ecp",
"description": "SAML ECP Profile Authentication Flow", "description": "SAML ECP Profile Authentication Flow",
"providerId": "basic-flow", "providerId": "basic-flow",
@ -2076,14 +2117,14 @@
], ],
"authenticatorConfig": [ "authenticatorConfig": [
{ {
"id": "86b1d5fa-450c-40d8-899c-725861ac39fc", "id": "bd7365c7-842b-4bc6-a4ca-498cf025c210",
"alias": "create unique user config", "alias": "create unique user config",
"config": { "config": {
"require.password.update.after.registration": "false" "require.password.update.after.registration": "false"
} }
}, },
{ {
"id": "ea724f02-029a-493d-b4d3-08972be21cfb", "id": "b929192d-f650-4a09-9701-3d3216547552",
"alias": "review profile config", "alias": "review profile config",
"config": { "config": {
"update.profile.on.first.login": "missing" "update.profile.on.first.login": "missing"

View File

@ -73,7 +73,7 @@
"composites": { "composites": {
"realm": ["offline_access", "uma_authorization"], "realm": ["offline_access", "uma_authorization"],
"client": { "client": {
"account": ["delete-account", "view-profile", "manage-account"] "account": ["view-profile", "manage-account", "delete-account"]
} }
}, },
"clientRole": false, "clientRole": false,
@ -456,6 +456,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"create-client",
"view-identity-providers",
"manage-realm",
"query-groups",
"manage-clients",
"query-users",
"realm-admin",
"view-authorization",
"view-events",
"view-clients",
"view-realm",
"manage-events",
"query-realms",
"query-clients",
"manage-identity-providers",
"manage-users",
"view-users",
"impersonation",
"manage-authorization"
],
"broker": ["read-token"],
"account": [
"view-profile",
"manage-account-links",
"view-applications",
"manage-consent",
"delete-account",
"manage-account",
"view-groups",
"view-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -521,8 +555,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -657,7 +695,6 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
@ -718,8 +755,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1298,11 +1339,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1318,13 +1359,13 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-usermodel-property-mapper", "saml-user-attribute-mapper",
"saml-user-property-mapper",
"oidc-sha256-pairwise-sub-mapper",
"saml-role-list-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"saml-user-property-mapper", "oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-address-mapper" "oidc-address-mapper"
] ]
} }
@ -1374,14 +1415,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-full-name-mapper",
"oidc-usermodel-property-mapper", "oidc-usermodel-property-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"saml-user-attribute-mapper", "oidc-full-name-mapper",
"oidc-sha256-pairwise-sub-mapper",
"saml-user-property-mapper",
"saml-role-list-mapper", "saml-role-list-mapper",
"saml-user-property-mapper" "saml-user-attribute-mapper"
] ]
} }
}, },

View File

@ -55,7 +55,7 @@
"composites": { "composites": {
"realm": ["offline_access", "uma_authorization"], "realm": ["offline_access", "uma_authorization"],
"client": { "client": {
"account": ["delete-account", "view-profile", "manage-account"] "account": ["view-profile", "delete-account", "manage-account"]
} }
}, },
"clientRole": false, "clientRole": false,
@ -459,6 +459,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"query-clients",
"manage-identity-providers",
"create-client",
"view-users",
"query-groups",
"view-realm",
"manage-authorization",
"view-authorization",
"query-users",
"impersonation",
"realm-admin",
"manage-users",
"view-identity-providers",
"manage-realm",
"manage-clients",
"query-realms",
"view-events",
"manage-events",
"view-clients"
],
"broker": ["read-token"],
"account": [
"manage-account",
"view-consent",
"view-groups",
"delete-account",
"view-applications",
"manage-account-links",
"view-profile",
"manage-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -505,7 +539,6 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
@ -532,8 +565,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -649,7 +686,11 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["https://my-theme.keycloakify.dev/*", "http://localhost*"], "redirectUris": [
"https://my-theme.keycloakify.dev/*",
"http://localhost*",
"http://127.0.0.1*"
],
"webOrigins": ["*"], "webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
@ -664,8 +705,7 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter", "post.logout.redirect.uris": "+",
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false" "backchannel.logout.revoke.offline.tokens": "false"
@ -725,8 +765,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1336,12 +1380,12 @@
"strictTransportSecurity": "max-age=31536000; includeSubDomains" "strictTransportSecurity": "max-age=31536000; includeSubDomains"
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1357,13 +1401,13 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"saml-user-property-mapper",
"oidc-address-mapper",
"oidc-full-name-mapper",
"saml-role-list-mapper", "saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"oidc-full-name-mapper",
"oidc-address-mapper",
"saml-user-property-mapper",
"oidc-usermodel-property-mapper" "oidc-usermodel-property-mapper"
] ]
} }
@ -1433,13 +1477,13 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-role-list-mapper",
"oidc-full-name-mapper",
"oidc-address-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"oidc-address-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"oidc-full-name-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-property-mapper" "oidc-usermodel-property-mapper"
] ]
} }

View File

@ -468,6 +468,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"manage-clients",
"manage-users",
"view-identity-providers",
"view-users",
"impersonation",
"manage-identity-providers",
"query-users",
"query-realms",
"realm-admin",
"view-events",
"view-realm",
"manage-events",
"manage-authorization",
"manage-realm",
"query-clients",
"query-groups",
"view-clients",
"create-client",
"view-authorization"
],
"broker": ["read-token"],
"account": [
"manage-consent",
"manage-account-links",
"view-applications",
"view-consent",
"manage-account",
"view-profile",
"view-groups",
"delete-account"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -514,7 +548,6 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
@ -541,8 +574,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/realms/myrealm/account/*"], "redirectUris": [
"webOrigins": [], "http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -658,7 +695,11 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["https://my-theme.keycloakify.dev/*", "http://localhost*"], "redirectUris": [
"https://my-theme.keycloakify.dev/*",
"http://localhost*",
"http://127.0.0.1*"
],
"webOrigins": ["*"], "webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
@ -673,8 +714,7 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter", "post.logout.redirect.uris": "+",
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false" "backchannel.logout.revoke.offline.tokens": "false"
@ -840,8 +880,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1451,12 +1495,12 @@
"strictTransportSecurity": "max-age=31536000; includeSubDomains" "strictTransportSecurity": "max-age=31536000; includeSubDomains"
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloak", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1504,11 +1548,11 @@
"saml-role-list-mapper", "saml-role-list-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-usermodel-property-mapper", "oidc-usermodel-property-mapper",
"oidc-sha256-pairwise-sub-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"saml-user-property-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper"
"saml-user-property-mapper"
] ]
} }
}, },
@ -1540,14 +1584,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-property-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"oidc-usermodel-property-mapper",
"saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper",
"saml-role-list-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-usermodel-attribute-mapper", "oidc-usermodel-attribute-mapper",
"saml-user-property-mapper", "saml-user-property-mapper"
"saml-role-list-mapper",
"saml-user-attribute-mapper"
] ]
} }
}, },

View File

@ -538,10 +538,10 @@
"emailVerified": true, "emailVerified": true,
"attributes": { "attributes": {
"additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"], "additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"],
"gender": ["prefer_not_to_say"],
"favorite_pet": ["cats"], "favorite_pet": ["cats"],
"favourite_pet": ["cat"], "gender": ["prefer_not_to_say"],
"bio": ["Hello I'm Test User and I do not exist."], "bio": ["Hello I'm Test User and I do not exist."],
"favourite_pet": ["cat"],
"phone_number": ["1111111111"], "phone_number": ["1111111111"],
"locale": ["en"], "locale": ["en"],
"favorite_media": ["movies", "series"] "favorite_media": ["movies", "series"]
@ -562,6 +562,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"manage-users",
"create-client",
"view-users",
"view-realm",
"query-realms",
"impersonation",
"view-events",
"realm-admin",
"manage-authorization",
"manage-events",
"view-authorization",
"manage-clients",
"query-users",
"query-groups",
"manage-realm",
"query-clients",
"manage-identity-providers",
"view-clients",
"view-identity-providers"
],
"broker": ["read-token"],
"account": [
"delete-account",
"view-applications",
"manage-account",
"view-consent",
"view-groups",
"view-profile",
"manage-account-links",
"manage-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -636,7 +670,7 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["*"], "redirectUris": ["http://localhost*", "http://127.0.0.1*", "*"],
"webOrigins": ["*"], "webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
@ -798,8 +832,7 @@
"attributes": { "attributes": {
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter", "post.logout.redirect.uris": "+",
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false" "backchannel.logout.revoke.offline.tokens": "false"
@ -892,8 +925,12 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -1551,11 +1588,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1581,14 +1618,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"oidc-full-name-mapper",
"oidc-usermodel-property-mapper",
"saml-role-list-mapper", "saml-role-list-mapper",
"saml-user-attribute-mapper", "oidc-full-name-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"saml-user-attribute-mapper",
"oidc-usermodel-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": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-sha256-pairwise-sub-mapper",
"saml-user-property-mapper",
"oidc-usermodel-attribute-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"saml-role-list-mapper",
"oidc-usermodel-property-mapper",
"saml-user-attribute-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", "providerId": "rsa-generated",
"subComponents": {}, "subComponents": {},
"config": { "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"] "priority": ["100"]
} }
}, },
@ -1687,6 +1730,12 @@
"providerId": "rsa-enc-generated", "providerId": "rsa-enc-generated",
"subComponents": {}, "subComponents": {},
"config": { "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"], "priority": ["100"],
"algorithm": ["RSA-OAEP"] "algorithm": ["RSA-OAEP"]
} }
@ -1697,6 +1746,8 @@
"providerId": "aes-generated", "providerId": "aes-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["95db7eb8-b57b-475e-90cd-58841a9388d3"],
"secret": ["dp6bv53YrC2PZuJCxa3aNA"],
"priority": ["100"] "priority": ["100"]
} }
}, },
@ -1706,6 +1757,10 @@
"providerId": "hmac-generated", "providerId": "hmac-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["d0254883-059e-4fdd-bf03-704c76650aab"],
"secret": [
"bcW7E4rcbgSKZIQysWOSuhezRGYs5Kzmp3ZESthdTUMyFivK8RbBAdBE4PhFPk5B9TuByDO2RWvd8F7F5YhGJitf6cfYB1BfDuAk-2iBAtdZA98g7a2h4jpwzh-GIgtoRbGbH9qnquUn52f5qteo34g5WifKE2bWjOELza9FrTo"
],
"priority": ["100"], "priority": ["100"],
"algorithm": ["HS512"] "algorithm": ["HS512"]
} }

View File

@ -563,6 +563,40 @@
"disableableCredentialTypes": [], "disableableCredentialTypes": [],
"requiredActions": [], "requiredActions": [],
"realmRoles": ["default-roles-myrealm"], "realmRoles": ["default-roles-myrealm"],
"clientRoles": {
"realm-management": [
"manage-users",
"create-client",
"view-users",
"view-realm",
"query-realms",
"impersonation",
"view-events",
"realm-admin",
"manage-authorization",
"view-authorization",
"manage-events",
"manage-clients",
"query-users",
"query-groups",
"manage-realm",
"query-clients",
"manage-identity-providers",
"view-identity-providers",
"view-clients"
],
"broker": ["read-token"],
"account": [
"delete-account",
"view-applications",
"manage-account",
"view-consent",
"view-groups",
"view-profile",
"manage-account-links",
"manage-consent"
]
},
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
} }
@ -638,7 +672,11 @@
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["*"], "redirectUris": [
"http://localhost*",
"http://127.0.0.1*",
"/realms/myrealm/account/*"
],
"webOrigins": ["*"], "webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
@ -805,8 +843,7 @@
"realm_client": "false", "realm_client": "false",
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"login_theme": "keycloakify-starter", "post.logout.redirect.uris": "+",
"post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false" "backchannel.logout.revoke.offline.tokens": "false"
@ -894,14 +931,20 @@
"id": "fce8a109-6f32-4814-9a20-2ff2435d2da6", "id": "fce8a109-6f32-4814-9a20-2ff2435d2da6",
"clientId": "security-admin-console", "clientId": "security-admin-console",
"name": "${client_security-admin-console}", "name": "${client_security-admin-console}",
"description": "",
"rootUrl": "${authAdminUrl}", "rootUrl": "${authAdminUrl}",
"adminUrl": "",
"baseUrl": "/admin/myrealm/console/", "baseUrl": "/admin/myrealm/console/",
"surrogateAuthRequired": false, "surrogateAuthRequired": false,
"enabled": true, "enabled": true,
"alwaysDisplayInConsole": false, "alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret", "clientAuthenticatorType": "client-secret",
"redirectUris": ["/admin/myrealm/console/*"], "redirectUris": [
"webOrigins": ["+"], "http://localhost*",
"http://127.0.0.1*",
"/admin/myrealm/console/*"
],
"webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
"consentRequired": false, "consentRequired": false,
@ -914,9 +957,14 @@
"protocol": "openid-connect", "protocol": "openid-connect",
"attributes": { "attributes": {
"realm_client": "false", "realm_client": "false",
"oidc.ciba.grant.enabled": "false",
"client.use.lightweight.access.token.enabled": "true", "client.use.lightweight.access.token.enabled": "true",
"backchannel.logout.session.required": "true",
"post.logout.redirect.uris": "+", "post.logout.redirect.uris": "+",
"pkce.code.challenge.method": "S256" "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false",
"pkce.code.challenge.method": "S256",
"backchannel.logout.revoke.offline.tokens": "false"
}, },
"authenticationFlowBindingOverrides": {}, "authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true, "fullScopeAllowed": true,
@ -937,6 +985,24 @@
"claim.name": "locale", "claim.name": "locale",
"jsonType.label": "String" "jsonType.label": "String"
} }
},
{
"id": "8fd0d584-7052-4d04-a615-d18a71050873",
"name": "allowed-origins",
"protocol": "openid-connect",
"protocolMapper": "oidc-hardcoded-claim-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"claim.value": "[\"*\"]",
"userinfo.token.claim": "true",
"id.token.claim": "false",
"lightweight.claim": "false",
"access.token.claim": "true",
"claim.name": "allowed-origins",
"jsonType.label": "JSON",
"access.tokenResponse.claim": "false"
}
} }
], ],
"defaultClientScopes": [ "defaultClientScopes": [
@ -1561,11 +1627,11 @@
}, },
"smtpServer": {}, "smtpServer": {},
"loginTheme": "keycloakify-starter", "loginTheme": "keycloakify-starter",
"accountTheme": "keycloakify-starter", "accountTheme": "",
"adminTheme": "", "adminTheme": "",
"emailTheme": "", "emailTheme": "",
"eventsEnabled": false, "eventsEnabled": false,
"eventsListeners": ["jboss-logging"], "eventsListeners": ["keycloakify-logging", "jboss-logging"],
"enabledEventTypes": [], "enabledEventTypes": [],
"adminEventsEnabled": false, "adminEventsEnabled": false,
"adminEventsDetailsEnabled": false, "adminEventsDetailsEnabled": false,
@ -1591,14 +1657,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-user-attribute-mapper", "oidc-usermodel-property-mapper",
"oidc-sha256-pairwise-sub-mapper",
"oidc-full-name-mapper",
"saml-user-property-mapper", "saml-user-property-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-usermodel-property-mapper", "saml-user-attribute-mapper",
"saml-role-list-mapper", "saml-role-list-mapper",
"oidc-usermodel-attribute-mapper" "oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper",
"oidc-full-name-mapper"
] ]
} }
}, },
@ -1628,14 +1694,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "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",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper" "oidc-full-name-mapper",
"oidc-sha256-pairwise-sub-mapper",
"saml-user-property-mapper",
"oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"oidc-address-mapper",
"oidc-usermodel-attribute-mapper"
] ]
} }
}, },
@ -1688,6 +1754,12 @@
"providerId": "rsa-generated", "providerId": "rsa-generated",
"subComponents": {}, "subComponents": {},
"config": { "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"] "priority": ["100"]
} }
}, },
@ -1697,6 +1769,12 @@
"providerId": "rsa-enc-generated", "providerId": "rsa-enc-generated",
"subComponents": {}, "subComponents": {},
"config": { "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"], "priority": ["100"],
"algorithm": ["RSA-OAEP"] "algorithm": ["RSA-OAEP"]
} }
@ -1707,6 +1785,8 @@
"providerId": "aes-generated", "providerId": "aes-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["c36222c6-6a43-4d32-9d44-d5d355e5cabd"],
"secret": ["rzL4qUQ7wTEkZDbgt595VA"],
"priority": ["100"] "priority": ["100"]
} }
}, },
@ -1716,6 +1796,10 @@
"providerId": "hmac-generated", "providerId": "hmac-generated",
"subComponents": {}, "subComponents": {},
"config": { "config": {
"kid": ["06532a54-c310-41c1-829c-58776ce2ab4a"],
"secret": [
"9v1ZjFhEFH6UpY6ncFkaCbqJYHMyI4tA0cvx4GuQ5KtMXYbimitSSVDqxIKwa-gBC_8bY2O4FQfpmp1Qn1-L4fFmPFfIF3ZKsO16263BwpADo_FNSBTte8Le4gJLylqFULdsn3ye17FHyq5Jjms_OTt3opzcDLNduCuK22GBBsU"
],
"priority": ["100"], "priority": ["100"],
"algorithm": ["HS512"] "algorithm": ["HS512"]
} }
@ -2385,7 +2469,7 @@
"clientSessionMaxLifespan": "0", "clientSessionMaxLifespan": "0",
"organizationsEnabled": "false" "organizationsEnabled": "false"
}, },
"keycloakVersion": "26.0.6", "keycloakVersion": "26.0.7",
"userManagedAccessAllowed": false, "userManagedAccessAllowed": false,
"organizationsEnabled": false, "organizationsEnabled": false,
"clientProfiles": { "clientProfiles": {

View File

@ -0,0 +1,194 @@
import { CONTAINER_NAME } from "../../shared/constants";
import child_process from "child_process";
import { join as pathJoin, dirname as pathDirname, basename as pathBasename } 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) {
const dCompleted = new Deferred<void>();
const cmd = `docker exec ${CONTAINER_NAME} sh -c "cp -rp /opt/keycloak/data/h2 /tmp"`;
child_process.exec(cmd, error => {
if (error !== null) {
dCompleted.reject(error);
return;
}
dCompleted.resolve();
});
try {
await dCompleted.pr;
} catch (error) {
assert(is<Error>(error));
console.log(chalk.red(`Docker command failed: ${cmd}`));
console.log(chalk.red(error.message));
throw error;
}
}
{
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(`docker exec kc.sh export command failed 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);
throw error;
}
}
if (doesUseLockedH2Database) {
const dCompleted = new Deferred<void>();
const cmd = `docker exec ${CONTAINER_NAME} sh -c "rm -rf /tmp/h2"`;
child_process.exec(cmd, error => {
if (error !== null) {
dCompleted.reject(error);
return;
}
dCompleted.resolve();
});
try {
await dCompleted.pr;
} catch (error) {
assert(is<Error>(error));
console.log(chalk.red(`Docker command failed: ${cmd}`));
console.log(chalk.red(error.message));
throw error;
}
}
const targetRealmConfigJsonFilePath_tmp = pathJoin(
buildContext.cacheDirPath,
"realm.json"
);
{
const dCompleted = new Deferred<void>();
const cmd = `docker cp ${CONTAINER_NAME}:/tmp/${realmName}-realm.json ${pathBasename(targetRealmConfigJsonFilePath_tmp)}`;
child_process.exec(
cmd,
{
cwd: pathDirname(targetRealmConfigJsonFilePath_tmp)
},
error => {
if (error !== null) {
dCompleted.reject(error);
return;
}
dCompleted.resolve();
}
);
try {
await dCompleted.pr;
} catch (error) {
assert(is<Error>(error));
console.log(chalk.red(`Docker command failed: ${cmd}`));
console.log(chalk.red(error.message));
throw error;
}
}
return readRealmJsonFile({
realmJsonFilePath: targetRealmConfigJsonFilePath_tmp
});
}

View File

@ -0,0 +1 @@
export * from "./realmConfig";

View File

@ -0,0 +1,365 @@
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"] as const) {
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 = ["*"];
admin_specific: {
if (clientId !== "security-admin-console") {
break admin_specific;
}
const protocolMapper_preexisting = client.protocolMappers?.find(
protocolMapper => {
if (protocolMapper.protocolMapper !== "oidc-hardcoded-claim-mapper") {
return false;
}
if (protocolMapper.protocol !== "openid-connect") {
return false;
}
if (protocolMapper.config === undefined) {
return false;
}
if (protocolMapper.config["claim.name"] !== "allowed-origins") {
return false;
}
return true;
}
);
let protocolMapper: NonNullable<typeof protocolMapper_preexisting>;
const config = {
"introspection.token.claim": "true",
"claim.value": '["*"]',
"userinfo.token.claim": "true",
"id.token.claim": "false",
"lightweight.claim": "false",
"access.token.claim": "true",
"claim.name": "allowed-origins",
"jsonType.label": "JSON",
"access.tokenResponse.claim": "false"
};
if (protocolMapper_preexisting !== undefined) {
protocolMapper = protocolMapper_preexisting;
} else {
protocolMapper = {
id: "8fd0d584-7052-4d04-a615-d18a71050873",
name: "allowed-origins",
protocol: "openid-connect",
protocolMapper: "oidc-hardcoded-claim-mapper",
consentRequired: false,
config
};
(client.protocolMappers ??= []).push(protocolMapper);
}
assert(protocolMapper.config !== undefined);
if (config !== protocolMapper.config) {
Object.assign(protocolMapper.config, config);
}
}
}
}

View File

@ -0,0 +1,159 @@
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...`)
);
let parsedRealmJson: ParsedRealmJson;
try {
parsedRealmJson = await dumpContainerConfig({
buildContext,
realmName,
keycloakMajorVersionNumber
});
} catch (error) {
console.log(chalk.red(`Failed to backup '${realmName}' config:`));
return;
}
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
};
}

View File

@ -1,7 +1,11 @@
import type { BuildContext } from "../shared/buildContext"; import type { BuildContext } from "../shared/buildContext";
import { exclude } from "tsafe/exclude"; import { exclude } from "tsafe/exclude";
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion"; import {
import { CONTAINER_NAME, KEYCLOAKIFY_SPA_DEV_SERVER_PORT } from "../shared/constants"; CONTAINER_NAME,
KEYCLOAKIFY_SPA_DEV_SERVER_PORT,
KEYCLOAKIFY_LOGIN_JAR_BASENAME,
TEST_APP_URL
} from "../shared/constants";
import { SemVer } from "../tools/SemVer"; import { SemVer } from "../tools/SemVer";
import { assert, type Equals } from "tsafe/assert"; import { assert, type Equals } from "tsafe/assert";
import * as fs from "fs"; import * as fs from "fs";
@ -9,8 +13,7 @@ import {
join as pathJoin, join as pathJoin,
relative as pathRelative, relative as pathRelative,
sep as pathSep, sep as pathSep,
basename as pathBasename, basename as pathBasename
dirname as pathDirname
} from "path"; } from "path";
import * as child_process from "child_process"; import * as child_process from "child_process";
import chalk from "chalk"; import chalk from "chalk";
@ -28,6 +31,9 @@ import { existsAsync } from "../tools/fs.existsAsync";
import { rm } from "../tools/fs.rm"; import { rm } from "../tools/fs.rm";
import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive"; import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive";
import { startViteDevServer } from "./startViteDevServer"; import { startViteDevServer } from "./startViteDevServer";
import { getSupportedKeycloakMajorVersions } from "./realmConfig/defaultConfig";
import { getSupportedDockerImageTags } from "./getSupportedDockerImageTags";
import { getRealmConfig } from "./realmConfig";
export async function command(params: { export async function command(params: {
buildContext: BuildContext; buildContext: BuildContext;
@ -91,9 +97,32 @@ export async function command(params: {
const { cliCommandOptions, buildContext } = params; const { cliCommandOptions, buildContext } = params;
const availableTags = await getSupportedDockerImageTags({
buildContext
});
const { dockerImageTag } = await (async () => { const { dockerImageTag } = await (async () => {
if (cliCommandOptions.keycloakVersion !== undefined) { if (cliCommandOptions.keycloakVersion !== undefined) {
return { dockerImageTag: cliCommandOptions.keycloakVersion }; const cliCommandOptions_keycloakVersion = cliCommandOptions.keycloakVersion;
const tag = availableTags.find(tag =>
tag.startsWith(cliCommandOptions_keycloakVersion)
);
if (tag === undefined) {
console.log(
chalk.red(
[
`We could not find a Keycloak Docker image for ${cliCommandOptions_keycloakVersion}`,
`Example of valid values: --keycloak-version 26, --keycloak-version 26.0.7`
].join("\n")
)
);
process.exit(1);
}
return { dockerImageTag: tag };
} }
if (buildContext.startKeycloakOptions.dockerImage !== undefined) { if (buildContext.startKeycloakOptions.dockerImage !== undefined) {
@ -108,50 +137,84 @@ export async function command(params: {
"On which version of Keycloak do you want to test your theme?" "On which version of Keycloak do you want to test your theme?"
), ),
chalk.gray( chalk.gray(
"You can also explicitly provide the version with `npx keycloakify start-keycloak --keycloak-version 25.0.2` (or any other version)" "You can also explicitly provide the version with `npx keycloakify start-keycloak --keycloak-version 26` (or any other version)"
) )
].join("\n") ].join("\n")
); );
const { keycloakVersion } = await promptKeycloakVersion({ const { value: tag } = await cliSelect<string>({
startingFromMajor: 18, values: availableTags
excludeMajorVersions: [22], }).catch(() => {
doOmitPatch: true, process.exit(-1);
buildContext
}); });
console.log(`${keycloakVersion}`); console.log(`${tag}`);
return { dockerImageTag: keycloakVersion }; return { dockerImageTag: tag };
})(); })();
const keycloakMajorVersionNumber = (() => { const keycloakMajorVersionNumber = (() => {
if (buildContext.startKeycloakOptions.dockerImage === undefined) { const [wrap] = getSupportedKeycloakMajorVersions()
return SemVer.parse(dockerImageTag).major;
}
const { tag } = buildContext.startKeycloakOptions.dockerImage;
const [wrap] = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
.map(majorVersionNumber => ({ .map(majorVersionNumber => ({
majorVersionNumber, majorVersionNumber,
index: tag.indexOf(`${majorVersionNumber}`) index: dockerImageTag.indexOf(`${majorVersionNumber}`)
})) }))
.filter(({ index }) => index !== -1) .filter(({ index }) => index !== -1)
.sort((a, b) => a.index - b.index); .sort((a, b) => a.index - b.index);
if (wrap === undefined) { if (wrap === undefined) {
console.warn( try {
chalk.yellow( const version = SemVer.parse(dockerImageTag);
`Could not determine the major Keycloak version number from the docker image tag ${tag}. Assuming 25`
) console.error(
); chalk.yellow(
return 25; `Keycloak version ${version.major} is not supported, supported versions are ${getSupportedKeycloakMajorVersions().join(", ")}`
)
);
process.exit(1);
} catch {
// NOTE: Latest version
const [n] = getSupportedKeycloakMajorVersions();
console.warn(
chalk.yellow(
`Could not determine the major Keycloak version number from the docker image tag ${dockerImageTag}. Assuming ${n}`
)
);
return n;
}
} }
return wrap.majorVersionNumber; return wrap.majorVersionNumber;
})(); })();
const { clientName, onRealmConfigChange, realmJsonFilePath, realmName, username } =
await getRealmConfig({
keycloakMajorVersionNumber,
realmJsonFilePath_userProvided: await (async () => {
if (cliCommandOptions.realmJsonFilePath !== undefined) {
return getAbsoluteAndInOsFormatPath({
pathIsh: cliCommandOptions.realmJsonFilePath,
cwd: process.cwd()
});
}
if (buildContext.startKeycloakOptions.realmJsonFilePath !== undefined) {
assert(
await existsAsync(
buildContext.startKeycloakOptions.realmJsonFilePath
),
`${pathRelative(process.cwd(), buildContext.startKeycloakOptions.realmJsonFilePath)} does not exist`
);
return buildContext.startKeycloakOptions.realmJsonFilePath;
}
return undefined;
})(),
buildContext
});
{ {
const { isAppBuildSuccess } = await appBuild({ const { isAppBuildSuccess } = await appBuild({
buildContext buildContext
@ -189,154 +252,48 @@ export async function command(params: {
assert(jarFilePath !== undefined); assert(jarFilePath !== undefined);
const extensionJarFilePaths = await Promise.all( const extensionJarFilePaths = [
buildContext.startKeycloakOptions.extensionJars.map(async extensionJar => { ...(keycloakMajorVersionNumber <= 20
switch (extensionJar.type) { ? (console.log(
case "path": { chalk.yellow(
assert( "WARNING: With older version of keycloak your changes to the realm configuration are not persisted"
await existsAsync(extensionJar.path), )
`${extensionJar.path} does not exist` ),
); [])
return extensionJar.path; : [
pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak",
KEYCLOAKIFY_LOGIN_JAR_BASENAME
)
]),
...(await Promise.all(
buildContext.startKeycloakOptions.extensionJars.map(async extensionJar => {
switch (extensionJar.type) {
case "path": {
assert(
await existsAsync(extensionJar.path),
`${extensionJar.path} does not exist`
);
return extensionJar.path;
}
case "url": {
const { archiveFilePath } = await downloadAndExtractArchive({
cacheDirPath: buildContext.cacheDirPath,
fetchOptions: buildContext.fetchOptions,
url: extensionJar.url,
uniqueIdOfOnArchiveFile: "no extraction",
onArchiveFile: async () => {}
});
return archiveFilePath;
}
} }
case "url": { assert<Equals<typeof extensionJar, never>>(false);
const { archiveFilePath } = await downloadAndExtractArchive({ })
cacheDirPath: buildContext.cacheDirPath, ))
fetchOptions: buildContext.fetchOptions, ];
url: extensionJar.url,
uniqueIdOfOnArchiveFile: "no extraction",
onArchiveFile: async () => {}
});
return archiveFilePath;
}
}
assert<Equals<typeof extensionJar, never>>(false);
})
);
const getRealmJsonFilePath_defaultForKeycloakMajor = (
keycloakMajorVersionNumber: number
) =>
pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak",
`myrealm-realm-${keycloakMajorVersionNumber}.json`
);
const realmJsonFilePath = await (async () => {
if (cliCommandOptions.realmJsonFilePath !== undefined) {
if (cliCommandOptions.realmJsonFilePath === "none") {
return undefined;
}
return getAbsoluteAndInOsFormatPath({
pathIsh: cliCommandOptions.realmJsonFilePath,
cwd: process.cwd()
});
}
if (buildContext.startKeycloakOptions.realmJsonFilePath !== undefined) {
assert(
await existsAsync(buildContext.startKeycloakOptions.realmJsonFilePath),
`${pathRelative(process.cwd(), buildContext.startKeycloakOptions.realmJsonFilePath)} does not exist`
);
return buildContext.startKeycloakOptions.realmJsonFilePath;
}
const internalFilePath = await (async () => {
const defaultFilePath = getRealmJsonFilePath_defaultForKeycloakMajor(
keycloakMajorVersionNumber
);
if (fs.existsSync(defaultFilePath)) {
return defaultFilePath;
}
console.log(
`${chalk.yellow(
`Keycloakify do not have a realm configuration for Keycloak ${keycloakMajorVersionNumber} yet.`
)}`
);
console.log(chalk.cyan("Select what configuration to use:"));
const dirPath = pathDirname(defaultFilePath);
const { value } = await cliSelect<string>({
values: [
...fs
.readdirSync(dirPath)
.filter(fileBasename => fileBasename.endsWith(".json")),
"none"
]
}).catch(() => {
process.exit(-1);
});
if (value === "none") {
return undefined;
}
return pathJoin(dirPath, value);
})();
if (internalFilePath === undefined) {
return undefined;
}
const filePath = pathJoin(
buildContext.cacheDirPath,
pathBasename(internalFilePath)
);
fs.writeFileSync(
filePath,
Buffer.from(
fs
.readFileSync(internalFilePath)
.toString("utf8")
.replace(/keycloakify\-starter/g, buildContext.themeNames[0])
),
"utf8"
);
return filePath;
})();
add_test_user_if_missing: {
if (realmJsonFilePath === undefined) {
break add_test_user_if_missing;
}
const realm: Record<string, unknown> = JSON.parse(
fs.readFileSync(realmJsonFilePath).toString("utf8")
);
if (realm.users !== undefined) {
break add_test_user_if_missing;
}
const realmJsonFilePath_internal = (() => {
const filePath = getRealmJsonFilePath_defaultForKeycloakMajor(
keycloakMajorVersionNumber
);
if (!fs.existsSync(filePath)) {
return getRealmJsonFilePath_defaultForKeycloakMajor(25);
}
return filePath;
})();
const users = JSON.parse(
fs.readFileSync(realmJsonFilePath_internal).toString("utf8")
).users;
realm.users = users;
fs.writeFileSync(realmJsonFilePath, JSON.stringify(realm, null, 2), "utf8");
}
async function extractThemeResourcesFromJar() { async function extractThemeResourcesFromJar() {
await extractArchive({ await extractArchive({
@ -376,9 +333,7 @@ export async function command(params: {
}); });
} catch {} } catch {}
const DEFAULT_PORT = 8080; const port = cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? 8080;
const port =
cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT;
const doStartDevServer = (() => { const doStartDevServer = (() => {
const hasSpaUi = const hasSpaUi =
@ -434,8 +389,15 @@ export async function command(params: {
const dockerRunArgs: string[] = [ const dockerRunArgs: string[] = [
`-p${SPACE_PLACEHOLDER}${port}:8080`, `-p${SPACE_PLACEHOLDER}${port}:8080`,
`--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`, `--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`,
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`, ...(keycloakMajorVersionNumber >= 26
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`, ? [
`-e${SPACE_PLACEHOLDER}KC_BOOTSTRAP_ADMIN_USERNAME=admin`,
`-e${SPACE_PLACEHOLDER}KC_BOOTSTRAP_ADMIN_PASSWORD=admin`
]
: [
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`,
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`
]),
...(devServerPort === undefined ...(devServerPort === undefined
? [] ? []
: [ : [
@ -451,7 +413,7 @@ export async function command(params: {
...(realmJsonFilePath === undefined ...(realmJsonFilePath === undefined
? [] ? []
: [ : [
`-v${SPACE_PLACEHOLDER}"${realmJsonFilePath}":/opt/keycloak/data/import/myrealm-realm.json` `-v${SPACE_PLACEHOLDER}"${realmJsonFilePath}":/opt/keycloak/data/import/${realmName}-realm.json`
]), ]),
`-v${SPACE_PLACEHOLDER}"${jarFilePath_cacheDir}":/opt/keycloak/providers/keycloak-theme.jar`, `-v${SPACE_PLACEHOLDER}"${jarFilePath_cacheDir}":/opt/keycloak/providers/keycloak-theme.jar`,
...extensionJarFilePaths.map( ...extensionJarFilePaths.map(
@ -526,7 +488,14 @@ export async function command(params: {
{ shell: true } { shell: true }
); );
child.stdout.on("data", data => process.stdout.write(data)); child.stdout.on("data", async data => {
if (data.toString("utf8").includes("keycloakify-logging: REALM_CONFIG_CHANGED")) {
await onRealmConfigChange();
return;
}
process.stdout.write(data);
});
child.stderr.on("data", data => process.stderr.write(data)); child.stderr.on("data", data => process.stderr.write(data));
@ -573,9 +542,9 @@ export async function command(params: {
`${chalk.green("Your theme is accessible at:")}`, `${chalk.green("Your theme is accessible at:")}`,
`${chalk.green("➜")} ${chalk.cyan.bold( `${chalk.green("➜")} ${chalk.cyan.bold(
(() => { (() => {
const url = new URL("https://my-theme.keycloakify.dev"); const url = new URL(TEST_APP_URL);
if (port !== DEFAULT_PORT) { if (port !== 8080) {
url.searchParams.set("port", `${port}`); url.searchParams.set("port", `${port}`);
} }
if (kcHttpRelativePath !== undefined) { if (kcHttpRelativePath !== undefined) {
@ -584,13 +553,20 @@ export async function command(params: {
kcHttpRelativePath kcHttpRelativePath
); );
} }
if (realmName !== "myrealm") {
url.searchParams.set("realm", realmName);
}
if (clientName !== "myclient") {
url.searchParams.set("client", clientName);
}
return url.href; return url.href;
})() })()
)}`, )}`,
"", "",
"You can login with the following credentials:", "You can login with the following credentials:",
`- username: ${chalk.cyan.bold("testuser")}`, `- username: ${chalk.cyan.bold(username)}`,
`- password: ${chalk.cyan.bold("password123")}`, `- password: ${chalk.cyan.bold("password123")}`,
"", "",
`Watching for changes in ${chalk.bold( `Watching for changes in ${chalk.bold(

View File

@ -44,6 +44,7 @@ export function startViteDevServer(params: {
//Local: http://localhost:8083/ //Local: http://localhost:8083/
const match = data const match = data
.toString("utf8") .toString("utf8")
.replace(/\x1b[[0-9;]*m/g, "")
.match(/Local:\s*http:\/\/(?:localhost|127\.0\.0\.1):(\d+)\//); .match(/Local:\s*http:\/\/(?:localhost|127\.0\.0\.1):(\d+)\//);
if (match === null) { if (match === null) {