From 637b773fd6884cfa4079beddb361dd2abb469899 Mon Sep 17 00:00:00 2001 From: Cameron Hutchison Date: Tue, 10 Dec 2024 16:06:56 -0600 Subject: [PATCH 1/6] Make the error message for when a user does not exist when attempting to login via OIDC more user-friendly. --- backend/internal/token.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/token.js b/backend/internal/token.js index f949f1b2..436669bc 100644 --- a/backend/internal/token.js +++ b/backend/internal/token.js @@ -102,7 +102,7 @@ module.exports = { .first() .then((user) => { if (!user) { - throw new error.AuthError('No relevant user found'); + throw new error.AuthError(`A user with the email ${data.identity} does not exist. Please contact your administrator.`); } // Create a moment of the expiry expression From e4b87d01f1ca2bc498d85a395ed4fd8802657b84 Mon Sep 17 00:00:00 2001 From: Cameron Hutchison Date: Tue, 10 Dec 2024 16:07:36 -0600 Subject: [PATCH 2/6] Add documentation for configuring SSO with OIDC --- docs/src/setup/index.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/src/setup/index.md b/docs/src/setup/index.md index ee8e9903..8af828b2 100644 --- a/docs/src/setup/index.md +++ b/docs/src/setup/index.md @@ -146,4 +146,38 @@ Immediately after logging in with this default user you will be asked to modify INITIAL_ADMIN_PASSWORD: mypassword1 ``` +## OpenID Connect - Single Sign-On (SSO) + +Nginx Proxy Manager supports single sign-on (SSO) with OpenID Connect. This feature allows you to use an external OpenID Connect provider log in. +*Note: This feature requires a user to have an existing account to have been created via the "Users" page in the admin interface.* + +### Provider Configuration +However, before you configure this feature, you need to have an OpenID Connect provider. +If you don't have one, you can use Authentik, which is an open-source OpenID Connect provider. Auth0 is another popular OpenID Connect provider that offers a free tier. + +Each provider is a little different, so you will need to refer to the provider's documentation to get the necessary information to configure a new application. +You will need the `Client ID`, `Client Secret`, and `Issuer URL` from the provider. When you create the application in the provider, you will also need to include the `Redirect URL` in the list of allowed redirect URLs for the application. +Nginx Proxy Manager uses the `/api/oidc/callback` endpoint for the redirect URL. +The scopes requested by Nginx Proxy Manager are `openid`, `email`, and `profile` - make sure your auth provider supports these scopes. + +We have confirmed that the following providers work with Nginx Proxy Manager. If you have success with another provider, make a pull request to add it to the list! +- Authentik +- Authelia +- Auth0 + +### Nginx Proxy Manager Configuration +To enable SSO, log into the management interface as an Administrator and navigate to the "Settings" page. +The setting to configure OpenID Connect is named "OpenID Connect Configuration". +Click the 3 dots on the far right side of the table and then click "Edit". +In the modal that appears, you will see a form with the following fields: + +| Field | Description | Example Value | Notes | +|---------------|-----------------------------------------------------------|---------------------------------------------|---------------------------------------------------------------------| +| Name | The name of the OpenID Connect provider | Authentik | This will be shown on the login page (eg: "Sign in with Authentik") | +| Client ID | The client ID provided by the OpenID Connect provider | `xyz...456` | | +| Client Secret | The client secret provided by the OpenID Connect provider | `abc...123` | +| Issuer URL | The issuer URL provided by the OpenID Connect provider | `https://authentik.example.com` | This is the URL that the provider uses to identify itself | +| Redirect URL | The redirect URL to use for the OpenID Connect provider | `https://npm.example.com/api/oidc/callback` | | + +After filling in the fields, click "Save" to save the settings. You can now use the "Sign in with Authentik" button on the login page to sign in with your OpenID Connect provider. From 81aa8a4fe6b8ff66b63eeb758131c2fa93edf07e Mon Sep 17 00:00:00 2001 From: Cameron Hutchison Date: Tue, 10 Dec 2024 16:23:19 -0600 Subject: [PATCH 3/6] Make 'Redirect URL' match the name of the field. --- frontend/js/i18n/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json index 3a3ec055..e9a02f69 100644 --- a/frontend/js/i18n/messages.json +++ b/frontend/js/i18n/messages.json @@ -296,7 +296,7 @@ "oidc-config-description": "Sign in to Nginx Proxy Manager with an external Identity Provider", "oidc-not-configured": "Not configured", "oidc-config-hint-1": "Provide configuration for an IdP that supports Open ID Connect Discovery.", - "oidc-config-hint-2": "The 'RedirectURL' must be set to '[base URL]/api/oidc/callback', the IdP must send the 'email' claim and a user with matching email address must exist in Nginx Proxy Manager." + "oidc-config-hint-2": "The 'Redirect URL' must be set to '[base URL]/api/oidc/callback', the IdP must send the 'email' claim and a user with matching email address must exist in Nginx Proxy Manager." } } -} \ No newline at end of file +} From 1ed15b3dd9d5fe5fc046fc0bb6d253b1f3b49039 Mon Sep 17 00:00:00 2001 From: Cameron Hutchison Date: Tue, 10 Dec 2024 17:03:40 -0600 Subject: [PATCH 4/6] Add Cypress tests for updating the OIDC configuration --- test/cypress/e2e/api/Settings.cy.js | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/cypress/e2e/api/Settings.cy.js b/test/cypress/e2e/api/Settings.cy.js index 6942760c..bca5e365 100644 --- a/test/cypress/e2e/api/Settings.cy.js +++ b/test/cypress/e2e/api/Settings.cy.js @@ -19,6 +19,51 @@ describe('Settings endpoints', () => { }); }); + it('Get oidc-config setting', function() { + cy.task('backendApiGet', { + token: token, + path: '/api/settings/oidc-config', + }).then((data) => { + cy.validateSwaggerSchema('get', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('oidc-config'); + }); + }); + + it('OIDC settings can be updated', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/oidc-config', + data: { + meta: { + name: 'Some OIDC Provider', + clientID: 'clientID', + clientSecret: 'clientSecret', + issuerURL: 'https://oidc.example.com', + redirectURL: 'https://redirect.example.com/api/oidc/callback', + enabled: true, + } + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('oidc-config'); + expect(data).to.have.property('meta'); + expect(data.meta).to.have.property('name'); + expect(data.meta.name).to.be.equal('Some OIDC Provider'); + expect(data.meta).to.have.property('clientID'); + expect(data.meta.clientID).to.be.equal('clientID'); + expect(data.meta).to.have.property('clientSecret'); + expect(data.meta.clientSecret).to.be.equal('clientSecret'); + expect(data.meta).to.have.property('issuerURL'); + expect(data.meta.issuerURL).to.be.equal('https://oidc.example.com'); + expect(data.meta).to.have.property('redirectURL'); + expect(data.meta.redirectURL).to.be.equal('https://redirect.example.com/api/oidc/callback'); + expect(data.meta).to.have.property('enabled'); + expect(data.meta.enabled).to.be.true; + }); + }); + it('Get default-site setting', function() { cy.task('backendApiGet', { token: token, From 529c84f0fdb2e41b95bd6c2395241cffd059a9f1 Mon Sep 17 00:00:00 2001 From: Cameron Hutchison Date: Wed, 11 Dec 2024 13:23:31 -0600 Subject: [PATCH 5/6] Add UI E2E tests for the login page for OIDC being enabled and when it is disabled --- frontend/js/app/dashboard/main.ejs | 2 +- frontend/js/login/ui/login.ejs | 10 +- test/cypress/e2e/ui/Login.cy.js | 185 +++++++++++++++++++++++++++++ test/cypress/support/commands.js | 116 +++++++++++++++++- test/cypress/support/constants.js | 16 +++ 5 files changed, 321 insertions(+), 8 deletions(-) create mode 100644 test/cypress/e2e/ui/Login.cy.js create mode 100644 test/cypress/support/constants.js diff --git a/frontend/js/app/dashboard/main.ejs b/frontend/js/app/dashboard/main.ejs index c00aa6d0..94718a92 100644 --- a/frontend/js/app/dashboard/main.ejs +++ b/frontend/js/app/dashboard/main.ejs @@ -1,5 +1,5 @@ <% if (columns) { %> diff --git a/frontend/js/login/ui/login.ejs b/frontend/js/login/ui/login.ejs index 84aa90a0..3cde0a6f 100644 --- a/frontend/js/login/ui/login.ejs +++ b/frontend/js/login/ui/login.ejs @@ -17,19 +17,19 @@
<%- i18n('login', 'title') %>
- +
- -
+ +