diff --git a/.changeset/flat-suns-call.md b/.changeset/flat-suns-call.md new file mode 100644 index 0000000000..096a10ec30 --- /dev/null +++ b/.changeset/flat-suns-call.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Add support for the majority of the Core configurations for Passport-SAML. + +These configuration keys are supported: + +- entryPoint +- issuer +- cert +- privateKey +- decryptionPvk +- signatureAlgorithm +- digestAlgorithm + +As part of this change, there is also a fix to the redirection behaviour when doing load balancing and HTTPS termination - the application's baseUrl is used to generate the callback URL. For properly configured Backstage installations, no changes are necessary, and the baseUrl is respected. diff --git a/docs/auth/auth-backend-classes.md b/docs/auth/auth-backend-classes.md index 8dbae0daa7..424869196d 100644 --- a/docs/auth/auth-backend-classes.md +++ b/docs/auth/auth-backend-classes.md @@ -61,6 +61,19 @@ If your authentication provider is any of the above mentioned providers, you can configure them by setting the right variables in `app-config.yaml` under the `auth` section. +### SAML + +The SAML Provider is currently under development. Additional validation and +profile handling is still required before use in production. + +To configure the SAML Auth provider, look at the configuration parameters +supported by +[Passport-SAML](https://github.com/node-saml/passport-saml#config-parameter-details) +under the `auth.providers.saml` key + +For security reasons, validate that the response from the IdP is indeed signed +by also providing the `cert` configuration. + ### Configuration Each authentication provider (except SAML) needs five parameters: an OAuth @@ -96,6 +109,11 @@ auth: development: clientId: $env: + saml: + entryPoint: + $env: AUTH_SAML_ENTRY_POINT + issuer: + $env: AUTH_SAML_ISSUER ... ``` diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index c971528e14..f7e1da9b96 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -47,6 +47,11 @@ export interface Config { saml?: { entryPoint: string; issuer: string; + cert?: string; + privateKey?: string; + decryptionPvk?: string; + signatureAlgorithm?: 'sha1' | 'sha256' | 'sha512'; + digestAlgorithm?: string; }; okta?: { development: { [key: string]: string }; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 9891557134..a91ec04ad9 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -44,7 +44,7 @@ "fs-extra": "^9.0.0", "got": "^11.5.2", "helmet": "^4.0.0", - "jose": "^3.5.0", + "jose": "^1.27.1", "jwt-decode": "^3.1.0", "knex": "^0.21.6", "moment": "^2.26.0", @@ -58,7 +58,7 @@ "passport-oauth2": "^1.5.0", "passport-okta-oauth": "^0.0.1", "passport-onelogin-oauth": "^0.0.1", - "passport-saml": "^1.3.3", + "passport-saml": "^1.3.5, <1.4.0", "uuid": "^8.0.0", "winston": "^3.2.1", "yn": "^4.0.0" diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index 7b663a5528..4cdee1da0f 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -16,6 +16,7 @@ import express from 'express'; import { + SamlConfig, Strategy as SamlStrategy, Profile as SamlProfile, VerifyWithoutRequest, @@ -112,27 +113,31 @@ export class SamlAuthProvider implements AuthProviderRouteHandlers { } } -type SAMLProviderOptions = { - entryPoint: string; - issuer: string; - path: string; +type SAMLProviderOptions = SamlConfig & { tokenIssuer: TokenIssuer; appUrl: string; }; +type SignatureAlgorithm = 'sha1' | 'sha256' | 'sha512'; + export const createSamlProvider: AuthProviderFactory = ({ providerId, globalConfig, config, tokenIssuer, }) => { - const url = new URL(globalConfig.baseUrl); - const entryPoint = config.getString('entryPoint'); - const issuer = config.getString('issuer'); const opts = { - entryPoint, - issuer, - path: `${url.pathname}/${providerId}/handler/frame`, + callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`, + entryPoint: config.getString('entryPoint'), + issuer: config.getString('issuer'), + cert: config.getOptionalString('cert'), + privateCert: config.getOptionalString('privateKey'), + decryptionPvk: config.getOptionalString('decryptionPvk'), + signatureAlgorithm: config.getOptionalString('signatureAlgorithm') as + | SignatureAlgorithm + | undefined, + digestAlgorithm: config.getOptionalString('digestAlgorithm'), + tokenIssuer, appUrl: globalConfig.appUrl, }; diff --git a/yarn.lock b/yarn.lock index 9f3666d25c..3af2f2f713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15692,6 +15692,13 @@ jmespath@0.15.0: resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= +jose@^1.27.1: + version "1.27.1" + resolved "https://registry.npmjs.org/jose/-/jose-1.27.1.tgz#a1de2ecb5b3ae1ae28f0d9d0cc536349ada27ec8" + integrity sha512-VyHM6IJPw0TTGqHVNlPWg16/ASDPAmcChcLqSb3WNBvwWFoWPeFqlmAUCm8/oIG1GjZwAlUDuRKFfycowarcVA== + dependencies: + "@panva/asn1.js" "^1.0.0" + jose@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/jose/-/jose-2.0.2.tgz#fb22385b80c658cc7a0cae05b7086c04c6be49f4" @@ -15699,11 +15706,6 @@ jose@^2.0.2: dependencies: "@panva/asn1.js" "^1.0.0" -jose@^3.5.0: - version "3.5.0" - resolved "https://registry.npmjs.org/jose/-/jose-3.5.0.tgz#0a9b1cbedb53ec024d4fcbae779e719e7cf88916" - integrity sha512-pW9z+ny33gxX2wXLQl3SkPQWGaUvOMYLijuiMHIHUYIDsrZjdMqYYS5UTkusuMzZkqe5T8YImA4FOqqB1IWmRg== - joycon@^2.2.5: version "2.2.5" resolved "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" @@ -19095,16 +19097,16 @@ passport-onelogin-oauth@^0.0.1: pkginfo "0.2.x" uid2 "0.0.3" -passport-saml@^1.3.3: - version "1.3.3" - resolved "https://registry.npmjs.org/passport-saml/-/passport-saml-1.3.3.tgz#cbea1a2b21ff32b3bc4bfd84dc39c3a370df9935" - integrity sha512-54ecY/A6UEsyCehJws6a+J6THvwtYnGl9cnAUxx5DjsuKgZrDs0tSy58K4hCk1XG/LOcdQSF1TR3xlRXgTULhA== +"passport-saml@^1.3.5, <1.4.0": + version "1.3.5" + resolved "https://registry.npmjs.org/passport-saml/-/passport-saml-1.3.5.tgz#747f2c8bb8b9fed41e8cd14586df5aa83e8a8996" + integrity sha512-HFamiqgGiMRCbUBm3wx02WYWKb6ojke0WJHrg4QXI8tx35HrTmDiY8MksUXhouJtEkfcRwXjBL2cSEpRQ6+PgQ== dependencies: debug "^3.1.0" passport-strategy "*" q "^1.5.0" xml-crypto "^1.4.0" - xml-encryption "^1.0.0" + xml-encryption "1.2.1" xml2js "0.4.x" xmlbuilder "^11.0.0" xmldom "0.1.x" @@ -25294,7 +25296,7 @@ xml-crypto@^1.4.0: xmldom "0.1.27" xpath "0.0.27" -xml-encryption@^1.0.0: +xml-encryption@1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/xml-encryption/-/xml-encryption-1.2.1.tgz#e6d18817c4309fd07ca7793cca93c3fd06745baa" integrity sha512-hn5w3l5p2+nGjlmM0CAhMChDzVGhW+M37jH35Z+GJIipXbn9PUlAIRZ6I5Wm7ynlqZjFrMAr83d/CIp9VZJMTA==