diff --git a/src/apps.js b/src/apps.js index 2ef0bd6ff..6f356bb93 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1359,7 +1359,7 @@ async function install(data, auditSource) { let sso = 'sso' in data ? data.sso : null; if ('sso' in data && !('optionalSso' in manifest)) throw new BoxError(BoxError.BAD_FIELD, 'sso can only be specified for apps with optionalSso'); // if sso was unspecified, enable it by default if possible - if (sso === null) sso = !!manifest.addons?.ldap || !!manifest.addons?.proxyAuth; + if (sso === null) sso = !!manifest.addons?.ldap || !!manifest.addons?.proxyAuth || !!manifest.addons?.oidc; error = validateEnv(env); if (error) throw error; diff --git a/src/oidc.js b/src/oidc.js index 975bc612d..71a277d6b 100644 --- a/src/oidc.js +++ b/src/oidc.js @@ -14,6 +14,7 @@ exports = module.exports = { }; const assert = require('assert'), + apps = require('./apps.js'), BoxError = require('./boxerror.js'), blobs = require('./blobs.js'), constants = require('./constants.js'), @@ -30,6 +31,7 @@ const assert = require('assert'), jose = require('jose'), safe = require('safetydance'), settings = require('./settings.js'), + url = require('url'), users = require('./users.js'), util = require('util'); @@ -246,15 +248,29 @@ class CloudronAdapter { debug(`[${this.name}] find id:${id}`, client); - const tmp = { - client_id: id, - client_secret: client.secret, - application_type: 'native', // default is web but we want more flexible redirectUris and this is only used in https://github.com/panva/node-oidc-provider/blob/03c9bc513860e68ee7be84f99bfc9dc930b224e8/lib/helpers/client_schema.js#L536 - redirect_uris: client.loginRedirectUri.split(',').map(s => s.trim()), - id_token_signed_response_alg: client.tokenSignatureAlgorithm || 'RS256' - }; + const tmp = {}; + tmp.application_type = 'native'; // default is web but we want more flexible redirectUris and this is only used in https://github.com/panva/node-oidc-provider/blob/03c9bc513860e68ee7be84f99bfc9dc930b224e8/lib/helpers/client_schema.js#L53 + tmp.client_id = id; + tmp.client_secret = client.secret; + tmp.id_token_signed_response_alg = client.tokenSignatureAlgorithm || 'RS256'; - if (client.logoutRedirectUri) tmp.post_logout_redirect_uris = [ client.logoutRedirectUri ]; + if (client.appId) { + const [error, app] = await safe(apps.get(client.appId)); + if (error || !app) { + console.error(`oidc: Unkown app for client with appId ${client.appId}`); + return null; + } + + // prefix login and logout redirect uris with app.fqdn if it is just a path without a schema + // native callbacks for apps have custom schema like app.immich:/ + tmp.redirect_uris = client.loginRedirectUri.split(',').map(s => s.trim()).map(s => url.parse(s).protocol ? s : `https://${app.fqdn}${s}`); + + if (client.logoutRedirectUri) tmp.post_logout_redirect_uris = [ url.parse(client.logoutRedirectUri).protocol ? client.logoutRedirectUri : `https://${app.fqdn}${client.logoutRedirectUri}` ]; + } else { + tmp.redirect_uris = client.loginRedirectUri.split(',').map(s => s.trim()); + + if (client.logoutRedirectUri) tmp.post_logout_redirect_uris = [ client.logoutRedirectUri ]; + } return tmp; } else { diff --git a/src/services.js b/src/services.js index 690a6c018..62d9baceb 100644 --- a/src/services.js +++ b/src/services.js @@ -804,8 +804,9 @@ async function getEnvironment(app) { if (app.manifest.addons['docker']) env['CLOUDRON_DOCKER_HOST'] = `tcp://172.18.0.1:${constants.DOCKER_PROXY_PORT}`; - if (app.manifest.addons['oidc']) { + if (app.sso && app.manifest.addons['oidc']) { env['CLOUDRON_OIDC_DISCOVERY_URL'] = `https://${settings.dashboardFqdn()}/.well-known/openid-configuration`; + env['CLOUDRON_OIDC_ISSUER'] = `https://${settings.dashboardFqdn()}/openid`; env['CLOUDRON_OIDC_AUTH_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/auth`; env['CLOUDRON_OIDC_TOKEN_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/token`; env['CLOUDRON_OIDC_KEYS_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/jwks`; @@ -1941,6 +1942,7 @@ async function setupOidc(app, options) { secret: hat(4 * 128), loginRedirectUri: options.loginRedirectUri, logoutRedirectUri: options.logoutRedirectUri || '', + tokenSignatureAlgorithm: options.tokenSignatureAlgorithm || 'RS256', name: '', appId: app.id };