-
+
+
+
+
+
+
+ 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