From fb6218ed82746fa3fb6a49b1ae53241765c11118 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Fri, 14 Feb 2025 02:39:58 +0100 Subject: [PATCH] fix(saml): change SAML attribute default, verify that a NameID is defined Signed-off-by: Erik Michelson Signed-off-by: Philip Molares --- docs/content/configuration.md | 32 ++++++++++++++++---------------- lib/config/default.js | 4 ++-- lib/web/auth/saml/index.js | 9 +++++---- public/docs/release-notes.md | 10 ++++++++++ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/docs/content/configuration.md b/docs/content/configuration.md index b17a0a711..169c9036d 100644 --- a/docs/content/configuration.md +++ b/docs/content/configuration.md @@ -221,22 +221,22 @@ these are rarely used for various reasons. ### SAML Login -| config file | environment | **default** and example value | description | -| ----------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `saml` | | `{idpSsoUrl: ..., idpCert: ..., clientCert: ..., issuer: ..., identifierFormat: ..., disableRequestedAuthnContext: ..., groupAttribute: ..., externalGroups: [], requiredGroups: [], attribute: {id: ..., username: ..., email: ...}}` | An object detailing your SAML provider. Refer to the [OneLogin](guides/auth/saml-onelogin.md) and [SAML](guides/auth/saml.md) guides for more details! | -| | `CMD_SAML_IDPSSOURL` | **no default**, `https://idp.example.com/sso` | authentication endpoint of IdP. for details, see [guide](guides/auth/saml-onelogin.md). | -| | `CMD_SAML_IDPCERT` | **no default**, `/path/to/cert.pem` | certificate file path of IdP in PEM format | -| | `CMD_SAML_CLIENTCERT` | **no default**, `/path/to/privatecert.pem` | certificate file path for the client in PEM format (optional) | -| | `CMD_SAML_ISSUER` | **no default** | Issuer to supply to identity provider (optional, default: `serverURL` config)" | -| | `CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT` | **no default**, `true` or `false` | true to allow any authentication method, false restricts to password authentication (PasswordProtectedTransport) method (default: false) | -| | `CMD_SAML_IDENTIFIERFORMAT` | **`urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`** | name identifier format (optional, default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`) | -| | `CMD_SAML_GROUPATTRIBUTE` | **no default**, `memberOf` | attribute name for group list (optional) | -| | `CMD_SAML_REQUIREDGROUPS` | **no default**, `hedgedoc-users` | group names that allowed (use vertical bar to separate) (optional) | -| | `CMD_SAML_EXTERNALGROUPS` | **no default**, `Temporary-staff` | group names that not allowed (use vertical bar to separate) (optional) | -| | `CMD_SAML_ATTRIBUTE_ID` | **no default**, `sAMAccountName` | attribute map for `id` (optional, default: NameID of SAML response) | -| | `CMD_SAML_ATTRIBUTE_USERNAME` | **no default**, `mailNickname` | attribute map for `username` (optional, default: NameID of SAML response) | -| | `CMD_SAML_ATTRIBUTE_EMAIL` | **no default**, `mail` | attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) | -| | `CMD_SAML_PROVIDERNAME` | **no default**, `My institution` | Optional name to be displayed at login form indicating the SAML provider | +| config file | environment | **default** and example value | description | +|-------------|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `saml` | | `{idpSsoUrl: ..., idpCert: ..., clientCert: ..., issuer: ..., identifierFormat: ..., disableRequestedAuthnContext: ..., groupAttribute: ..., externalGroups: [], requiredGroups: [], attribute: {id: ..., username: ..., email: ...}}` | An object detailing your SAML provider. Refer to the [OneLogin](guides/auth/saml-onelogin.md) and [SAML](guides/auth/saml.md) guides for more details! | +| | `CMD_SAML_IDPSSOURL` | **no default**, `https://idp.example.com/sso` | authentication endpoint of IdP. for details, see [guide](guides/auth/saml-onelogin.md). | +| | `CMD_SAML_IDPCERT` | **no default**, `/path/to/cert.pem` | certificate file path of IdP in PEM format | +| | `CMD_SAML_CLIENTCERT` | **no default**, `/path/to/privatecert.pem` | certificate file path for the client in PEM format (optional) | +| | `CMD_SAML_ISSUER` | **no default** | Issuer to supply to identity provider (optional, default: `serverURL` config)" | +| | `CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT` | **no default**, `true` or `false` | true to allow any authentication method, false restricts to password authentication (PasswordProtectedTransport) method (default: false) | +| | `CMD_SAML_IDENTIFIERFORMAT` | **`urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`** | name identifier format (optional, if using `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`, ensure that the IdP returns an unique email address for each user) | +| | `CMD_SAML_GROUPATTRIBUTE` | **no default**, `http://schemas.xmlsoap.org/claims/Group` | attribute name for group list (optional) | +| | `CMD_SAML_REQUIREDGROUPS` | **no default**, `hedgedoc-users` | group names that allowed (use vertical bar to separate) (optional) | +| | `CMD_SAML_EXTERNALGROUPS` | **no default**, `Temporary-staff` | group names that not allowed (use vertical bar to separate) (optional) | +| | `CMD_SAML_ATTRIBUTE_ID` | *defaults to NameID as configured per requested NameID-Format*, `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn` | attribute map for `id` (optional, default: NameID of SAML response) | +| | `CMD_SAML_ATTRIBUTE_USERNAME` | **`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name`** | attribute map for `username` (optional) | +| | `CMD_SAML_ATTRIBUTE_EMAIL` | **`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`** | attribute map for `email` (optional) | +| | `CMD_SAML_PROVIDERNAME` | **no default**, `My institution` | Optional name to be displayed at login form indicating the SAML provider | ### Twitter Login diff --git a/lib/config/default.js b/lib/config/default.js index 6fffd20d9..02fe12f58 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -160,8 +160,8 @@ module.exports = { requiredGroups: [], attribute: { id: undefined, - username: undefined, - email: undefined + username: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', + email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' } }, email: true, diff --git a/lib/web/auth/saml/index.js b/lib/web/auth/saml/index.js index e2d506b23..c1444c4b2 100644 --- a/lib/web/auth/saml/index.js +++ b/lib/web/auth/saml/index.js @@ -56,14 +56,15 @@ passport.use( } // user creation const uuid = user[config.saml.attribute.id] || user.nameID + if (!uuid) { + logger.error('saml auth failed: id not found') + return done('Permission denied', null) + } const profile = { provider: 'saml', id: 'SAML-' + uuid, username: user[config.saml.attribute.username] || user.nameID, - emails: user[config.saml.attribute.email] ? [user[config.saml.attribute.email]] : [] - } - if (profile.emails.length === 0 && config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress') { - profile.emails.push(user.nameID) + emails: user[config.saml.attribute.email] ? [user[config.saml.attribute.email]] : config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' ? [user.nameID] : [] } const stringifiedProfile = JSON.stringify(profile) models.User.findOrCreate({ diff --git a/public/docs/release-notes.md b/public/docs/release-notes.md index 65052832f..f3378ec61 100644 --- a/public/docs/release-notes.md +++ b/public/docs/release-notes.md @@ -2,6 +2,16 @@ ## 1.x.x UNRELEASED +**PLEASE CHECK THIS IF YOU USE SAML AUTHENTICATION:** +This release had to set default values for the username and email address attribute mapping for SAML authentication for +security reasons. +If you use SAML authentication, please make sure to update your SAML configuration accordingly. +See: https://docs.hedgedoc.org/configuration/#saml-login `CMD_SAML_ATTRIBUTE_USERNAME` or `CMD_SAML_ATTRIBUTE_EMAIL` + +### Bugfixes +- Abort SAML login if NameID is undefined instead of logging in with a user named "undefined" +- Set default values for username and email attribute mapping in SAML configuration + ## 1.10.1 2024-02-02 This release fixes a security issue where brute-forcing local email/passwords is possible because of missing rate-limits.