From 6c9a81147249f195709c951c9203a99d851c6663 Mon Sep 17 00:00:00 2001 From: basti Date: Wed, 3 Apr 2024 16:18:13 +0200 Subject: [PATCH 1/4] Add ui and settings for OpenID Signing Algorithm --- client/pages/config/authentication.vue | 8 ++++++++ server/Auth.js | 6 ++++-- server/objects/settings/ServerSettings.js | 9 +++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/client/pages/config/authentication.vue b/client/pages/config/authentication.vue index a85433c5..260093b5 100644 --- a/client/pages/config/authentication.vue +++ b/client/pages/config/authentication.vue @@ -58,6 +58,8 @@ + +

@@ -187,6 +189,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_algorithm) this.newAuthSettings.authOpenIDTokenSigningAlgorithm = data.id_token_signing_algorithm }) .catch((error) => { console.error('Failed to receive data', error) @@ -225,6 +228,11 @@ export default { isValid = false } + if (!this.newAuthSettings.authOpenIDTokenSigningAlgorithm) { + this.$toast.error('Signing Algorithm required') + isValid = false + } + function isValidRedirectURI(uri) { // Check for somestring://someother/string const pattern = new RegExp('^\\w+://[\\w\\.-]+(/[\\w\\./-]*)*$', 'i') diff --git a/server/Auth.js b/server/Auth.js index 8ba87509..f9fe6e5c 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -85,7 +85,8 @@ class Auth { token_endpoint: global.ServerSettings.authOpenIDTokenURL, userinfo_endpoint: global.ServerSettings.authOpenIDUserInfoURL, jwks_uri: global.ServerSettings.authOpenIDJwksURL, - end_session_endpoint: global.ServerSettings.authOpenIDLogoutURL + end_session_endpoint: global.ServerSettings.authOpenIDLogoutURL, + id_token_signed_response_alg: global.ServerSettings.authOpenIDTokenSigningAlgorithm }).Client const openIdClient = new openIdIssuerClient({ client_id: global.ServerSettings.authOpenIDClientID, @@ -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_algorithm: data.id_token_signing_alg_values_supported?.[0] }) }).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, From 304d0f6d43684b43f1db169856ba75b253267d7f Mon Sep 17 00:00:00 2001 From: basti Date: Wed, 3 Apr 2024 22:52:49 +0200 Subject: [PATCH 2/4] id_token_signed_respo... should be in new Client --- server/Auth.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/Auth.js b/server/Auth.js index f9fe6e5c..5d376fd6 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -85,12 +85,12 @@ class Auth { token_endpoint: global.ServerSettings.authOpenIDTokenURL, userinfo_endpoint: global.ServerSettings.authOpenIDUserInfoURL, jwks_uri: global.ServerSettings.authOpenIDJwksURL, - end_session_endpoint: global.ServerSettings.authOpenIDLogoutURL, - id_token_signed_response_alg: global.ServerSettings.authOpenIDTokenSigningAlgorithm + end_session_endpoint: global.ServerSettings.authOpenIDLogoutURL }).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, From f75f0b8cc8e681a7491038c4c9f83e86e69f0e6b Mon Sep 17 00:00:00 2001 From: apocer Date: Tue, 9 Apr 2024 22:29:06 +0200 Subject: [PATCH 3/4] show dropdown if issuer has list of algorithms --- client/pages/config/authentication.vue | 22 ++++++++++++++++++++-- server/Auth.js | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/client/pages/config/authentication.vue b/client/pages/config/authentication.vue index 260093b5..5159c039 100644 --- a/client/pages/config/authentication.vue +++ b/client/pages/config/authentication.vue @@ -58,7 +58,8 @@ - + +

@@ -140,6 +141,7 @@ export default { enableOpenIDAuth: false, showCustomLoginMessage: false, savingSettings: false, + openIdSigningAlgorithmsSupportedByIssuer: [], newAuthSettings: {} } }, @@ -162,6 +164,9 @@ export default { value: 'username' } ] + }, + hasSupportedSigningAlgorithms() { + return this.openIdSigningAlgorithmsSupportedByIssuer.length > 0 } }, methods: { @@ -180,6 +185,19 @@ export default { this.newAuthSettings.authOpenIDIssuerURL = this.newAuthSettings.authOpenIDIssuerURL.replace('/.well-known/openid-configuration', '') } + const setSupportedSigningAlgorithms = (algorithms) => { + this.openIdSigningAlgorithmsSupportedByIssuer = algorithms + + if(!algorithms || algorithms.length === 0) return + + // 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) => { @@ -189,7 +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_algorithm) this.newAuthSettings.authOpenIDTokenSigningAlgorithm = data.id_token_signing_algorithm + 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) diff --git a/server/Auth.js b/server/Auth.js index 5d376fd6..827870b0 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -652,7 +652,7 @@ class Auth { userinfo_endpoint: data.userinfo_endpoint, end_session_endpoint: data.end_session_endpoint, jwks_uri: data.jwks_uri, - id_token_signing_algorithm: data.id_token_signing_alg_values_supported?.[0] + 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) From a8af6db3d608d64711e7e600bf21a748025fde9b Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 21 Apr 2024 16:05:41 -0500 Subject: [PATCH 4/4] Format update of authentication page for supported algorithms --- client/pages/config/authentication.vue | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/client/pages/config/authentication.vue b/client/pages/config/authentication.vue index 5159c039..4d698857 100644 --- a/client/pages/config/authentication.vue +++ b/client/pages/config/authentication.vue @@ -58,7 +58,7 @@ - + @@ -164,9 +164,6 @@ export default { value: 'username' } ] - }, - hasSupportedSigningAlgorithms() { - return this.openIdSigningAlgorithmsSupportedByIssuer.length > 0 } }, methods: { @@ -186,14 +183,17 @@ export default { } 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(!algorithms || algorithms.length === 0) return - // 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)) { + if (!algorithms.includes(currentAlgorithm)) { this.newAuthSettings.authOpenIDTokenSigningAlgorithm = algorithms[0] } } @@ -245,7 +245,6 @@ export default { this.$toast.error('Client Secret required') isValid = false } - if (!this.newAuthSettings.authOpenIDTokenSigningAlgorithm) { this.$toast.error('Signing Algorithm required') isValid = false