From f840aa80f8989a5d64b0a8e5935866906132a316 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 5 Nov 2023 14:11:37 -0600 Subject: [PATCH] Add button to populate openid URLs using the issuer URL --- client/pages/config/authentication.vue | 43 +++++++++++++++++++++++++- server/Auth.js | 27 ++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/client/pages/config/authentication.vue b/client/pages/config/authentication.vue index 13867ef3..7cedfd25 100644 --- a/client/pages/config/authentication.vue +++ b/client/pages/config/authentication.vue @@ -15,7 +15,17 @@
- +
+
+ +
+
+ + auto_fix_high + Auto-populate +
+
@@ -83,6 +93,37 @@ export default { } }, methods: { + autoPopulateOIDCClick() { + if (!this.newAuthSettings.authOpenIDIssuerURL) { + this.$toast.error('Issuer URL required') + return + } + // Remove trailing slash + let issuerUrl = this.newAuthSettings.authOpenIDIssuerURL + if (issuerUrl.endsWith('/')) issuerUrl = issuerUrl.slice(0, -1) + + // If the full config path is on the issuer url then remove it + if (issuerUrl.endsWith('/.well-known/openid-configuration')) { + issuerUrl = issuerUrl.replace('/.well-known/openid-configuration', '') + this.newAuthSettings.authOpenIDIssuerURL = this.newAuthSettings.authOpenIDIssuerURL.replace('/.well-known/openid-configuration', '') + } + + this.$axios + .$get(`/auth/openid/config?issuer=${issuerUrl}`) + .then((data) => { + if (data.issuer) this.newAuthSettings.authOpenIDIssuerURL = data.issuer + if (data.authorization_endpoint) this.newAuthSettings.authOpenIDAuthorizationURL = data.authorization_endpoint + if (data.token_endpoint) this.newAuthSettings.authOpenIDTokenURL = data.token_endpoint + 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 + }) + .catch((error) => { + console.error('Failed to receive data', error) + const errorMsg = error.response?.data || 'Unknown error' + this.$toast.error(errorMsg) + }) + }, validateOpenID() { let isValid = true if (!this.newAuthSettings.authOpenIDIssuerURL) { diff --git a/server/Auth.js b/server/Auth.js index a04f9ac4..361380f8 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -1,3 +1,4 @@ +const axios = require('axios') const passport = require('passport') const bcrypt = require('./libs/bcryptjs') const jwt = require('./libs/jsonwebtoken') @@ -309,6 +310,32 @@ class Auth { // on a successfull login: read the cookies and react like the client requested (callback or json) this.handleLoginSuccessBasedOnCookie.bind(this)) + /** + * Used to auto-populate the openid URLs in config/authentication + */ + router.get('/auth/openid/config', async (req, res) => { + if (!req.query.issuer) { + return res.status(400).send('Invalid request. Query param \'issuer\' is required') + } + let issuerUrl = req.query.issuer + if (issuerUrl.endsWith('/')) issuerUrl = issuerUrl.slice(0, -1) + + const configUrl = `${issuerUrl}/.well-known/openid-configuration` + axios.get(configUrl).then(({ data }) => { + res.json({ + issuer: data.issuer, + authorization_endpoint: data.authorization_endpoint, + token_endpoint: data.token_endpoint, + userinfo_endpoint: data.userinfo_endpoint, + end_session_endpoint: data.end_session_endpoint, + jwks_uri: data.jwks_uri + }) + }).catch((error) => { + Logger.error(`[Auth] Failed to get openid configuration at "${configUrl}"`, error) + res.status(error.statusCode || 400).send(`${error.code || 'UNKNOWN'}: Failed to get openid configuration`) + }) + }) + // Logout route router.post('/logout', (req, res) => { // TODO: invalidate possible JWTs