Enable PKCE by default for Keycloak JS (#26412)
Closes #26411 Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
cc7d6a9b79
commit
5bf2d4b6ec
7 changed files with 28 additions and 23 deletions
|
@ -6,9 +6,15 @@ image::images/new-welcome-screen.png["A screenshot of the new welcome page, show
|
||||||
|
|
||||||
If you are using a custom theme, you may need to update it to support the new welcome page. For more details consult the link:{upgradingguide_link}[{upgradingguide_name}].
|
If you are using a custom theme, you may need to update it to support the new welcome page. For more details consult the link:{upgradingguide_link}[{upgradingguide_name}].
|
||||||
|
|
||||||
= Keycloak JS using `exports` field
|
= Keycloak JS
|
||||||
|
|
||||||
The Keycloak JS adapter now uses the https://webpack.js.org/guides/package-exports/[`exports` field] in `package.json`. This change improves support for more modern bundlers like Webpack 5 and Vite, but comes with some unavoidable breaking changes. Consult the link:{upgradingguide_link}[{upgradingguide_name}] for more details.
|
== Using `exports` field in `package.json`
|
||||||
|
|
||||||
|
The Keycloak JS adapter now uses the https://webpack.js.org/guides/package-exports/[`exports` field] in its `package.json`. This change improves support for more modern bundlers like Webpack 5 and Vite, but comes with some unavoidable breaking changes. Consult the link:{upgradingguide_link}[{upgradingguide_name}] for more details.
|
||||||
|
|
||||||
|
== PKCE enabled by default
|
||||||
|
|
||||||
|
The Keycloak JS adapter now sets the `pkceMethod` option to `S256` by default. This enables Proof Key Code Exchange (https://datatracker.ietf.org/doc/html/rfc7636[PKCE]) for all applications using the adapter. If you are using the adapter on a system that doesn't support PKCE, you can set the `pkceMethod` option to `false` to disable it.
|
||||||
|
|
||||||
= Truststore Improvements
|
= Truststore Improvements
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,8 @@ to {project_name} will contain the scope parameter `scope=openid address phone`.
|
||||||
* flow - Set the OpenID Connect flow. Valid values are `standard`, `implicit` or `hybrid`.
|
* flow - Set the OpenID Connect flow. Valid values are `standard`, `implicit` or `hybrid`.
|
||||||
* enableLogging - Enables logging messages from Keycloak to the console (default is `false`).
|
* enableLogging - Enables logging messages from Keycloak to the console (default is `false`).
|
||||||
* pkceMethod - The method for Proof Key Code Exchange (https://datatracker.ietf.org/doc/html/rfc7636[PKCE]) to use. Configuring this value enables the PKCE mechanism. Available options:
|
* pkceMethod - The method for Proof Key Code Exchange (https://datatracker.ietf.org/doc/html/rfc7636[PKCE]) to use. Configuring this value enables the PKCE mechanism. Available options:
|
||||||
- "S256" - The SHA256 based PKCE method
|
- "S256" - The SHA256 based PKCE method (default)
|
||||||
|
- false - PKCE is disabled.
|
||||||
* acrValues - Generates the `acr_values` parameter which refers to authentication context class reference and allows clients to declare the required assurance level requirements, e.g. authentication mechanisms. See https://openid.net/specs/openid-connect-modrna-authentication-1_0.html#acr_values[Section 4. acr_values request values and level of assurance in OpenID Connect MODRNA Authentication Profile 1.0].
|
* acrValues - Generates the `acr_values` parameter which refers to authentication context class reference and allows clients to declare the required assurance level requirements, e.g. authentication mechanisms. See https://openid.net/specs/openid-connect-modrna-authentication-1_0.html#acr_values[Section 4. acr_values request values and level of assurance in OpenID Connect MODRNA Authentication Profile 1.0].
|
||||||
* messageReceiveTimeout - Set a timeout in milliseconds for waiting for message responses from the Keycloak server. This is used, for example, when waiting for a message during 3rd party cookies check. The default value is 10000.
|
* messageReceiveTimeout - Set a timeout in milliseconds for waiting for message responses from the Keycloak server. This is used, for example, when waiting for a message during 3rd party cookies check. The default value is 10000.
|
||||||
* locale - When onLoad is 'login-required', sets the 'ui_locales' query param in compliance with https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest[section 3.1.2.1 of the OIDC 1.0 specification].
|
* locale - When onLoad is 'login-required', sets the 'ui_locales' query param in compliance with https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest[section 3.1.2.1 of the OIDC 1.0 specification].
|
||||||
|
|
|
@ -13,7 +13,6 @@ import { routes } from "./routes";
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
keycloak.init({
|
keycloak.init({
|
||||||
onLoad: "check-sso",
|
onLoad: "check-sso",
|
||||||
pkceMethod: "S256",
|
|
||||||
}),
|
}),
|
||||||
i18n.init(),
|
i18n.init(),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -11,7 +11,6 @@ export const keycloak = new Keycloak({
|
||||||
export async function initKeycloak() {
|
export async function initKeycloak() {
|
||||||
const authenticated = await keycloak.init({
|
const authenticated = await keycloak.init({
|
||||||
onLoad: "check-sso",
|
onLoad: "check-sso",
|
||||||
pkceMethod: "S256",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Force the user to login if not authenticated.
|
// Force the user to login if not authenticated.
|
||||||
|
|
7
js/libs/keycloak-js/dist/keycloak.d.ts
vendored
7
js/libs/keycloak-js/dist/keycloak.d.ts
vendored
|
@ -22,7 +22,7 @@ export type KeycloakOnLoad = 'login-required'|'check-sso';
|
||||||
export type KeycloakResponseMode = 'query'|'fragment';
|
export type KeycloakResponseMode = 'query'|'fragment';
|
||||||
export type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
|
export type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
|
||||||
export type KeycloakFlow = 'standard'|'implicit'|'hybrid';
|
export type KeycloakFlow = 'standard'|'implicit'|'hybrid';
|
||||||
export type KeycloakPkceMethod = 'S256';
|
export type KeycloakPkceMethod = 'S256' | false;
|
||||||
|
|
||||||
export interface KeycloakConfig {
|
export interface KeycloakConfig {
|
||||||
/**
|
/**
|
||||||
|
@ -169,9 +169,8 @@ export interface KeycloakInitOptions {
|
||||||
flow?: KeycloakFlow;
|
flow?: KeycloakFlow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the Proof Key for Code Exchange (PKCE) method to use.
|
* Configures the Proof Key for Code Exchange (PKCE) method to use. This will default to 'S256'.
|
||||||
* The currently allowed method is 'S256'.
|
* Can be disabled by passing `false`.
|
||||||
* If not configured, PKCE will not be used.
|
|
||||||
*/
|
*/
|
||||||
pkceMethod?: KeycloakPkceMethod;
|
pkceMethod?: KeycloakPkceMethod;
|
||||||
|
|
||||||
|
|
|
@ -134,9 +134,11 @@ function Keycloak (config) {
|
||||||
|
|
||||||
if (initOptions.pkceMethod) {
|
if (initOptions.pkceMethod) {
|
||||||
if (initOptions.pkceMethod !== "S256") {
|
if (initOptions.pkceMethod !== "S256") {
|
||||||
throw 'Invalid value for pkceMethod';
|
throw new TypeError(`Invalid value for 'pkceMethod', expected 'S256' but got '${initOptions.pkceMethod}'.`);
|
||||||
}
|
}
|
||||||
kc.pkceMethod = initOptions.pkceMethod;
|
kc.pkceMethod = initOptions.pkceMethod;
|
||||||
|
} else {
|
||||||
|
kc.pkceMethod = "S256";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof initOptions.enableLogging === 'boolean') {
|
if (typeof initOptions.enableLogging === 'boolean') {
|
||||||
|
@ -374,19 +376,18 @@ function Keycloak (config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function generatePkceChallenge(pkceMethod, codeVerifier) {
|
function generatePkceChallenge(pkceMethod, codeVerifier) {
|
||||||
switch (pkceMethod) {
|
if (pkceMethod !== "S256") {
|
||||||
// The use of the "plain" method is considered insecure and therefore not supported.
|
throw new TypeError(`Invalid value for 'pkceMethod', expected 'S256' but got '${pkceMethod}'.`);
|
||||||
case "S256":
|
|
||||||
// hash codeVerifier, then encode as url-safe base64 without padding
|
|
||||||
var hashBytes = new Uint8Array(sha256.arrayBuffer(codeVerifier));
|
|
||||||
var encodedHash = bytesToBase64(hashBytes)
|
|
||||||
.replace(/\+/g, '-')
|
|
||||||
.replace(/\//g, '_')
|
|
||||||
.replace(/\=/g, '');
|
|
||||||
return encodedHash;
|
|
||||||
default:
|
|
||||||
throw 'Invalid value for pkceMethod';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hash codeVerifier, then encode as url-safe base64 without padding
|
||||||
|
const hashBytes = new Uint8Array(sha256.arrayBuffer(codeVerifier));
|
||||||
|
const encodedHash = bytesToBase64(hashBytes)
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/\=/g, '');
|
||||||
|
|
||||||
|
return encodedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildClaimsParameter(requestedAcr){
|
function buildClaimsParameter(requestedAcr){
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
realm: realm,
|
realm: realm,
|
||||||
clientId: 'account-console'
|
clientId: 'account-console'
|
||||||
});
|
});
|
||||||
keycloak.init({onLoad: 'check-sso', pkceMethod: 'S256', promiseType: 'native'}).then((authenticated) => {
|
keycloak.init({onLoad: 'check-sso'}).then((authenticated) => {
|
||||||
isReactLoading = true;
|
isReactLoading = true;
|
||||||
toggleReact();
|
toggleReact();
|
||||||
if (!keycloak.authenticated) {
|
if (!keycloak.authenticated) {
|
||||||
|
|
Loading…
Reference in a new issue