From 491d63ceee192bba318f8d5acbad86ad8f9b0216 Mon Sep 17 00:00:00 2001 From: Jason Minard Date: Thu, 10 Aug 2023 16:45:06 -0500 Subject: [PATCH] fix(auth): keycloak authentication post logout redirect for Keycloak 18+ (#5878) --- server/models/users.js | 2 +- .../authentication/keycloak/authentication.js | 18 +++++++++++++++--- .../authentication/keycloak/definition.yml | 5 +++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/server/models/users.js b/server/models/users.js index facb158a..33f6b24f 100644 --- a/server/models/users.js +++ b/server/models/users.js @@ -866,7 +866,7 @@ module.exports = class User extends Model { } const usr = await WIKI.models.users.query().findById(context.req.user.id).select('providerKey') const provider = _.find(WIKI.auth.strategies, ['key', usr.providerKey]) - return provider.logout ? provider.logout(provider.config) : '/' + return provider.logout ? provider.logout(provider.config, context) : '/' } static async getGuestUser () { diff --git a/server/modules/authentication/keycloak/authentication.js b/server/modules/authentication/keycloak/authentication.js index ce9a00c5..34ceb5ea 100644 --- a/server/modules/authentication/keycloak/authentication.js +++ b/server/modules/authentication/keycloak/authentication.js @@ -21,7 +21,7 @@ module.exports = { clientSecret: conf.clientSecret, callbackURL: conf.callbackURL, passReqToCallback: true - }, async (req, accessToken, refreshToken, profile, cb) => { + }, async (req, accessToken, refreshToken, results, profile, cb) => { let displayName = profile.username if (_.isString(profile.fullName) && profile.fullName.length > 0) { displayName = profile.fullName @@ -36,6 +36,7 @@ module.exports = { picture: '' } }) + req.session.keycloak_id_token = results.id_token cb(null, user) } catch (err) { cb(err, null) @@ -43,11 +44,22 @@ module.exports = { }) ) }, - logout (conf) { + logout (conf, context) { if (!conf.logoutUpstream) { return '/' } else if (conf.logoutURL && conf.logoutURL.length > 5) { - return `${conf.logoutURL}?redirect_uri=${encodeURIComponent(WIKI.config.host)}` + const idToken = context.req.session.keycloak_id_token + const redirURL = encodeURIComponent(WIKI.config.host) + if (conf.logoutUpstreamRedirectLegacy) { + // keycloak < 18 + return `${conf.logoutURL}?redirect_uri=${redirURL}` + } else if (idToken) { + // keycloak 18+ + return `${conf.logoutURL}?post_logout_redirect_uri=${redirURL}&id_token_hint=${idToken}` + } else { + // fall back to no redirect if keycloak_id_token isn't available + return conf.logoutURL + } } else { WIKI.logger.warn('Keycloak logout URL is not configured!') return '/' diff --git a/server/modules/authentication/keycloak/definition.yml b/server/modules/authentication/keycloak/definition.yml index d4ab044c..97453b84 100644 --- a/server/modules/authentication/keycloak/definition.yml +++ b/server/modules/authentication/keycloak/definition.yml @@ -57,4 +57,9 @@ props: title: Logout Endpoint URL hint: e.g. https://KEYCLOAK-HOST/auth/realms/YOUR-REALM/protocol/openid-connect/logout order: 9 + logoutUpstreamRedirectLegacy: + type: Boolean + title: Legacy Logout Redirect + hint: Pass the legacy 'redirect_uri' parameter to the logout endpoint. Leave disabled for Keycloak 18 and above. + order: 10