diff --git a/client/pages/config/authentication.vue b/client/pages/config/authentication.vue index a85433c5..4d698857 100644 --- a/client/pages/config/authentication.vue +++ b/client/pages/config/authentication.vue @@ -58,6 +58,9 @@ + + +

@@ -138,6 +141,7 @@ export default { enableOpenIDAuth: false, showCustomLoginMessage: false, savingSettings: false, + openIdSigningAlgorithmsSupportedByIssuer: [], newAuthSettings: {} } }, @@ -178,6 +182,22 @@ export default { this.newAuthSettings.authOpenIDIssuerURL = this.newAuthSettings.authOpenIDIssuerURL.replace('/.well-known/openid-configuration', '') } + const setSupportedSigningAlgorithms = (algorithms) => { + if (!algorithms?.length || !Array.isArray(algorithms)) { + console.warn('Invalid id_token_signing_alg_values_supported from openid-configuration', algorithms) + this.openIdSigningAlgorithmsSupportedByIssuer = [] + return + } + this.openIdSigningAlgorithmsSupportedByIssuer = algorithms + + // If a signing algorithm is already selected, then keep it, when it is still supported. + // But if it is not supported, then select one of the supported ones. + let currentAlgorithm = this.newAuthSettings.authOpenIDTokenSigningAlgorithm + if (!algorithms.includes(currentAlgorithm)) { + this.newAuthSettings.authOpenIDTokenSigningAlgorithm = algorithms[0] + } + } + this.$axios .$get(`/auth/openid/config?issuer=${issuerUrl}`) .then((data) => { @@ -187,6 +207,7 @@ export default { if (data.userinfo_endpoint) this.newAuthSettings.authOpenIDUserInfoURL = data.userinfo_endpoint if (data.end_session_endpoint) this.newAuthSettings.authOpenIDLogoutURL = data.end_session_endpoint if (data.jwks_uri) this.newAuthSettings.authOpenIDJwksURL = data.jwks_uri + if (data.id_token_signing_alg_values_supported) setSupportedSigningAlgorithms(data.id_token_signing_alg_values_supported) }) .catch((error) => { console.error('Failed to receive data', error) @@ -224,6 +245,10 @@ export default { this.$toast.error('Client Secret required') isValid = false } + if (!this.newAuthSettings.authOpenIDTokenSigningAlgorithm) { + this.$toast.error('Signing Algorithm required') + isValid = false + } function isValidRedirectURI(uri) { // Check for somestring://someother/string diff --git a/server/Auth.js b/server/Auth.js index 8ba87509..827870b0 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -89,7 +89,8 @@ class Auth { }).Client const openIdClient = new openIdIssuerClient({ client_id: global.ServerSettings.authOpenIDClientID, - client_secret: global.ServerSettings.authOpenIDClientSecret + client_secret: global.ServerSettings.authOpenIDClientSecret, + id_token_signed_response_alg: global.ServerSettings.authOpenIDTokenSigningAlgorithm }) passport.use('openid-client', new OpenIDClient.Strategy({ client: openIdClient, @@ -650,7 +651,8 @@ class Auth { token_endpoint: data.token_endpoint, userinfo_endpoint: data.userinfo_endpoint, end_session_endpoint: data.end_session_endpoint, - jwks_uri: data.jwks_uri + jwks_uri: data.jwks_uri, + id_token_signing_alg_values_supported: data.id_token_signing_alg_values_supported }) }).catch((error) => { Logger.error(`[Auth] Failed to get openid configuration at "${configUrl}"`, error) diff --git a/server/objects/settings/ServerSettings.js b/server/objects/settings/ServerSettings.js index 5c2da381..f107d707 100644 --- a/server/objects/settings/ServerSettings.js +++ b/server/objects/settings/ServerSettings.js @@ -68,13 +68,14 @@ class ServerSettings { this.authOpenIDLogoutURL = null this.authOpenIDClientID = null this.authOpenIDClientSecret = null + this.authOpenIDTokenSigningAlgorithm = 'RS256' this.authOpenIDButtonText = 'Login with OpenId' this.authOpenIDAutoLaunch = false this.authOpenIDAutoRegister = false this.authOpenIDMatchExistingBy = null this.authOpenIDMobileRedirectURIs = ['audiobookshelf://oauth'] this.authOpenIDGroupClaim = '' - this.authOpenIDAdvancedPermsClaim = '' + this.authOpenIDAdvancedPermsClaim = '' if (settings) { this.construct(settings) @@ -127,6 +128,7 @@ class ServerSettings { this.authOpenIDLogoutURL = settings.authOpenIDLogoutURL || null this.authOpenIDClientID = settings.authOpenIDClientID || null this.authOpenIDClientSecret = settings.authOpenIDClientSecret || null + this.authOpenIDTokenSigningAlgorithm = settings.authOpenIDTokenSigningAlgorithm || 'RS256' this.authOpenIDButtonText = settings.authOpenIDButtonText || 'Login with OpenId' this.authOpenIDAutoLaunch = !!settings.authOpenIDAutoLaunch this.authOpenIDAutoRegister = !!settings.authOpenIDAutoRegister @@ -217,6 +219,7 @@ class ServerSettings { authOpenIDLogoutURL: this.authOpenIDLogoutURL, authOpenIDClientID: this.authOpenIDClientID, // Do not return to client authOpenIDClientSecret: this.authOpenIDClientSecret, // Do not return to client + authOpenIDTokenSigningAlgorithm: this.authOpenIDTokenSigningAlgorithm, authOpenIDButtonText: this.authOpenIDButtonText, authOpenIDAutoLaunch: this.authOpenIDAutoLaunch, authOpenIDAutoRegister: this.authOpenIDAutoRegister, @@ -252,7 +255,8 @@ class ServerSettings { this.authOpenIDUserInfoURL && this.authOpenIDJwksURL && this.authOpenIDClientID && - this.authOpenIDClientSecret + this.authOpenIDClientSecret && + this.authOpenIDTokenSigningAlgorithm } get authenticationSettings() { @@ -267,6 +271,7 @@ class ServerSettings { authOpenIDLogoutURL: this.authOpenIDLogoutURL, authOpenIDClientID: this.authOpenIDClientID, // Do not return to client authOpenIDClientSecret: this.authOpenIDClientSecret, // Do not return to client + authOpenIDTokenSigningAlgorithm: this.authOpenIDTokenSigningAlgorithm, authOpenIDButtonText: this.authOpenIDButtonText, authOpenIDAutoLaunch: this.authOpenIDAutoLaunch, authOpenIDAutoRegister: this.authOpenIDAutoRegister,