From 866d31e4c0f3b16786e4a0af4644a403dc0f77ef Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 18 Jan 2021 14:25:21 +0100 Subject: [PATCH 1/8] Add SSO technical documentation page --- developer-docs/latest/concepts/sso.md | 293 ++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 developer-docs/latest/concepts/sso.md diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md new file mode 100644 index 0000000000..cbd67b8734 --- /dev/null +++ b/developer-docs/latest/concepts/sso.md @@ -0,0 +1,293 @@ +# Single Sign On + +Single-Sign-On on Strapi allows you to configure additional sign-in and sign-up methods for your administration panel. + +## Prerequisites + +- A Strapi application running on version 3.5.0 or higher is required. +- To configure SSO on your application, you will need an **EE license**. +- If needed, **make sure Strapi is part of the applications you can access with you provider**. + + For example, with Microsoft (Azure) Active Directory, you must first ask someone with the right permissions to add Strapi to the list of allowed applications. + + Please refer to your provider(s) documentation to learn more about that. + +## Usage + +SSO configuration lives in the server configuration (found within `/config/server.js`). + +### Accessing the configuration + +The providers' configuration should be written within the `admin.auth.providers` path of the server configuration. + +`admin.auth.providers` is an array of [provider configuration](#provider-configuration). + +```javascript +module.exports = ({ env }) => ({ + // ... + admin: { + // ... + auth: { + providers: [], // The providers' configuration lives there + }, + }, +}); +``` + +### Provider Configuration + +A provider's configuration is a simple Javascript object built with the following properties: + +| Name | Required | Type | Description | +|----------------- |----------|----------|--------------------------------------------------------------------------------| +| `uid` | true | string | The UID of the strategy. It must match the strategy's name | +| `displayName` | true | string | The name that will be used on the login page to reference the provider | +| `icon` | false | string | An image URL. If specified, it will replace the displayName on the login page | +| `createStrategy` | true | function | A factory that will build and return a new passport strategy for your provider. Takes the strapi instance as parameter | + +::: tip +The `uid` property is the unique identifier of each strategy and is generally found in the strategy's package. + +If you are not sure of what it refers to, please contact the maintainer of the strategy. +::: + +#### The `createStrategy` Factory + +A passport strategy is usually built by instantiating it using two parameters: + +##### Configuration Object + +The configuration object depends on the strategy needs, but often ask for a callback url to be redirected to once the connection has been made on the provider side. + +You can generate a specific callback url for your provider using the `getProviderCallbackUrl` method. + +::: tip +`strapi.admin.services.passport.getProviderCallbackUrl` is a Strapi util you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL as a string. +::: + +If needed, this is also where you will put your client ID and secret key for your OAuth2 application. + +##### Verify Function + +The verify function is used here as a middleware allowing the user to transform and make extra processing on the data returned from the provider API. + +This function always takes a `done` method as last parameter which is used to transfer needed data to the Strapi layer of SSO. + +Its signature is the following: `void done(error: any, data: object);` and it follows the following rules: + +- If `error` is not set to `null`, then the data sent is ignored, and the controller will throw an error. +- If the SSO's auto-registration feature is disabled, then the `data` object only need to be composed of an `email` property. +- If the SSO's auto-registration feature is enabled, then you will need to define (in addition to the `email`) either a `username` property or both `firstname` and `lastname` within the `data` oject. + +### Adding a provider + +Adding a new provider means adding a new way for your administrators to log-in. + +To achieve a great flexibility and a large choice of provider, we use [Passport.js](http://www.passportjs.org/) under the hood. It means that any valid passport strategy that doesn't need additional custom data should also work with Strapi. + +::: warning +Strategies such as [ldapauth](https://github.com/vesse/passport-ldapauth) don't work out of the box since they require extra data to be sent from the admin panel. +If you want to add an LDAP provider to your application, you will need to write a [custom strategy](http://www.passportjs.org/packages/passport-custom/). +You can also use services such as Okta and Auth0 as bridge services. +::: + +### Configuring the provider + +Configuring a new provider is straight-forward: + +1. First, make sure to import your strategy in your server configuration file. (from an installed package or a local file) +2. Next, you'll need to add a new item to the `admin.auth.providers` array in your server configuration that will match the [format given above](#provider-configuration) +3. Finally, restart your application, the provider should appear on your admin login page. + +## Examples + +:::: tabs + +::: tab Google + +Using: [passport-google-oauth2](https://github.com/mstade/passport-google-oauth2) + +```bash +yarn add passport-google-oauth2 +``` + +`/config/server.js` + +```jsx +'use strict'; + +const GoogleStrategy = require('passport-google-oauth2'); + +module.exports = ({ env }) => ({ + // ... + admin: { + // ... + auth: { + /// ... + providers: [ + { + uid: 'google', + displayName: 'Google', + icon: 'https://cdn2.iconfinder.com/data/icons/social-icons-33/128/Google-512.png' , + createStrategy: strapi => new GoogleStrategy({ + clientID: env('GOOGLE_CLIENT_ID'), + clientSecret: env('GOOGLE_CLIENT_SECRET'), + scope: [ + 'https://www.googleapis.com/auth/userinfo.email', + 'https://www.googleapis.com/auth/userinfo.profile' + ], + callbackURL: strapi.admin.services.passport.getProviderCallbackUrl('google') + }, (request, accessToken, refreshToken, profile, done) => { + done(null, { + email: profile.email, + firstname: profile.given_name, + lastname: profile.family_name, + }); + } + ), + }, + ], + }, + }, +}); +``` + +::: + +::: tab Github + +Using: [passport-github](https://github.com/cfsghost/passport-github) + +```bash +yarn add passport-github2 +``` + +`/config/server.js` + +```jsx +'use strict'; + +const GithubStrategy = require('passport-github2'); + +module.exports = ({ env }) => ({ + // ... + admin: { + // ... + auth: { + // ... + providers: [ + { + uid: 'github', + displayName: 'Github', + icon: 'https://cdn1.iconfinder.com/data/icons/logotypes/32/github-512.png', + createStrategy: strapi => new GithubStrategy({ + clientID: env('GITHUB_CLIENT_ID'), + clientSecret: env('GITHUB_CLIENT_SECRET'), + scope: ['user:email'], + callbackURL: strapi.admin.services.passport.getProviderCallbackUrl('github'), + }, (accessToken, refreshToken, profile, done) => { + done(null, { + email: profile.emails[0].value, + username: profile.username, + }); + }), + }, + ], + }, + }, +}); +``` +::: + +::: tab Discord + +Using: [passport-discord](https://github.com/nicholastay/passport-discord#readme) + +```bash +yarn add passport-discord +``` + +`/config/server.js` + +```jsx +"use strict"; + +const DiscordStrategy = require("passport-discord"); + +module.exports = ({ env }) => ({ + // ... + admin: { + // ... + auth: { + // ... + providers: [ + { + uid: 'discord', + displayName: 'Discord', + icon: 'https://cdn0.iconfinder.com/data/icons/free-social-media-set/24/discord-512.png', + createStrategy: strapi => + new DiscordStrategy( + { + clientID: env('DISCORD_CLIENT_ID'), + clientSecret: env('DISCORD_SECRET'), + callbackURL: strapi.admin.services.passport.getProviderCallbackUrl( + 'discord' + ), + scope: ['identify', 'email'], + }, + (accessToken, refreshToken, profile, done) => { + done(null, { + email: profile.email, + username: `${profile.username}#${profile.discriminator}`, + }); + } + ), + }, + ], + }, + }, +}); +``` +::: +:::: + +## Advanced Customization + +### Admin Panel URL + +If your administration panel lives on a different host/port than your Strapi server, you will need to specify the values in the admin config. +To do so, heads to your `/config/admin.js` configuration file (create it if it doesn't exist) and tweaks the host and port fields. + +For example, if your admin application has been started on `http://localhost:4000`, your admin configuration will look like the following: + +```javascript +module.exports = { + host: 'http://localhost', + port: 4000 +}; +``` + +### Custom Logic + +In some scenarios, you will want to write additional logic for your connection workflow such as: +- Restricting connection and registration for a specific domain +- Triggering actions on connection attempt +- Analytics + +The easiest way to do so is to plug into the verify function of your strategy and write some code. + +For example, if you want to allow only people with an official strapi.io email address, you can instantiate your strategy like this: + +```javascript +const strategyInstance = new Strategy( + configuration, + (email, done) => { + if (!email.endsWith('@strapi.io')) { + done(new Error('Forbidden email address')); + return; + } + + done(null, { email }); + }, +); +``` From f9dfafdcc471ce5f0113f29e35b6ef6d87fc4568 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 18 Jan 2021 14:36:23 +0100 Subject: [PATCH 2/8] Add SSO to the sidebar --- developer-docs/.vuepress/config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/developer-docs/.vuepress/config.js b/developer-docs/.vuepress/config.js index ae3f389c17..79ee899840 100644 --- a/developer-docs/.vuepress/config.js +++ b/developer-docs/.vuepress/config.js @@ -292,6 +292,7 @@ module.exports = { '/latest/concepts/requests-responses', '/latest/concepts/routing', '/latest/concepts/services', + '/latest/concepts/sso', '/latest/concepts/templates', '/latest/concepts/webhooks', ], From e079385b701ab8eb557d339516f233b008a229af Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 29 Jan 2021 16:31:43 +0100 Subject: [PATCH 3/8] Update the pr with the review & new features --- .../latest/concepts/configurations.md | 13 ++- developer-docs/latest/concepts/sso.md | 87 ++++++++++++------- 2 files changed, 69 insertions(+), 31 deletions(-) diff --git a/developer-docs/latest/concepts/configurations.md b/developer-docs/latest/concepts/configurations.md index 16695e4ac5..3a1f7ae550 100644 --- a/developer-docs/latest/concepts/configurations.md +++ b/developer-docs/latest/concepts/configurations.md @@ -213,7 +213,7 @@ This is an example of a full configuration, typically certain keys do not need t **Path —** `./config/server.js`. -```js +```javascript module.exports = ({ env }) => ({ host: env('HOST', '0.0.0.0'), port: env.int('PORT', 1337), @@ -226,6 +226,14 @@ module.exports = ({ env }) => ({ }, admin: { auth: { + events: { + onConnectionSuccess(e) { + console.log(e.user, e.provider); + }, + onConnectionError(e) { + console.error(e.error, e.provider); + }, + }, secret: env('ADMIN_JWT_SECRET', 'someSecretKey'), }, url: env('PUBLIC_ADMIN_URL', '/dashboard'), @@ -264,6 +272,9 @@ module.exports = ({ env }) => ({ | `admin` | Admin panel configuration | Object | | | `admin.auth` | Authentication configuration | Object | | | `admin.auth.secret`| Secret used to encode JWT tokens | string| `undefined` | +| `admin.auth.events`| Record of all the events subscribers registered for the authentication | object| `{}` | +| `admin.auth.events.onConnectionSuccess`| Function called when an admin user log in successfully to the administration panel | function | `undefined` | +| `admin.auth.events.onConnectionError`| Function called when an admin user fails to log in to the administration panel | function| `undefined` | | `admin.url` | Url of your admin panel. Default value: `/admin`. Note: If the url is relative, it will be concatenated with `url`. | string | `/admin` | | `admin.autoOpen` | Enable or disabled administration opening on start. | boolean | `true` | | `admin.watchIgnoreFiles` | Add custom files that should not be watched during development. See more [here](https://github.com/paulmillr/chokidar#path-filtering) (property `ignored`). | Array(string) | `[]` | diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index cbd67b8734..1a676073b1 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -5,16 +5,12 @@ Single-Sign-On on Strapi allows you to configure additional sign-in and sign-up ## Prerequisites - A Strapi application running on version 3.5.0 or higher is required. -- To configure SSO on your application, you will need an **EE license**. -- If needed, **make sure Strapi is part of the applications you can access with you provider**. - - For example, with Microsoft (Azure) Active Directory, you must first ask someone with the right permissions to add Strapi to the list of allowed applications. - - Please refer to your provider(s) documentation to learn more about that. +- To configure SSO on your application, you will need an EE license with a Gold plan. +- Make sure Strapi is part of the applications you can access with your provider. For example, with Microsoft (Azure) Active Directory, you must first ask someone with the right permissions to add Strapi to the list of allowed applications. Please refer to your provider(s) documentation to learn more about that. ## Usage -SSO configuration lives in the server configuration (found within `/config/server.js`). +SSO configuration lives in the server configuration of your application found within `/config/server.js`. ### Accessing the configuration @@ -36,7 +32,7 @@ module.exports = ({ env }) => ({ ### Provider Configuration -A provider's configuration is a simple Javascript object built with the following properties: +A provider's configuration is a Javascript object built with the following properties: | Name | Required | Type | Description | |----------------- |----------|----------|--------------------------------------------------------------------------------| @@ -46,23 +42,21 @@ A provider's configuration is a simple Javascript object built with the followin | `createStrategy` | true | function | A factory that will build and return a new passport strategy for your provider. Takes the strapi instance as parameter | ::: tip -The `uid` property is the unique identifier of each strategy and is generally found in the strategy's package. - -If you are not sure of what it refers to, please contact the maintainer of the strategy. +The `uid` property is the unique identifier of each strategy and is generally found in the strategy's package. If you are not sure of what it refers to, please contact the maintainer of the strategy. ::: #### The `createStrategy` Factory -A passport strategy is usually built by instantiating it using two parameters: +A passport strategy is usually built by instantiating it using 2 parameters: the configuration object, and the verify function. ##### Configuration Object -The configuration object depends on the strategy needs, but often ask for a callback url to be redirected to once the connection has been made on the provider side. +The configuration object depends on the strategy needs, but often asks for a callback URL to be redirected to once the connection has been made on the provider side. -You can generate a specific callback url for your provider using the `getProviderCallbackUrl` method. +You can generate a specific callback URL for your provider using the `getStrategyCallbackURL` method. ::: tip -`strapi.admin.services.passport.getProviderCallbackUrl` is a Strapi util you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL as a string. +`strapi.admin.services.passport.getStrategyCallbackURL` is a Strapi helper you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL as a string. ::: If needed, this is also where you will put your client ID and secret key for your OAuth2 application. @@ -83,7 +77,7 @@ Its signature is the following: `void done(error: any, data: object);` and it fo Adding a new provider means adding a new way for your administrators to log-in. -To achieve a great flexibility and a large choice of provider, we use [Passport.js](http://www.passportjs.org/) under the hood. It means that any valid passport strategy that doesn't need additional custom data should also work with Strapi. +To achieve a great flexibility and a large choice of provider, Strapi uses [Passport.js](http://www.passportjs.org/). Any valid passport strategy that doesn't need additional custom data should therefore work with Strapi. ::: warning Strategies such as [ldapauth](https://github.com/vesse/passport-ldapauth) don't work out of the box since they require extra data to be sent from the admin panel. @@ -93,11 +87,11 @@ You can also use services such as Okta and Auth0 as bridge services. ### Configuring the provider -Configuring a new provider is straight-forward: +To configure a provider, follow the procedure below: -1. First, make sure to import your strategy in your server configuration file. (from an installed package or a local file) -2. Next, you'll need to add a new item to the `admin.auth.providers` array in your server configuration that will match the [format given above](#provider-configuration) -3. Finally, restart your application, the provider should appear on your admin login page. +1. Make sure to import your strategy in your server configuration file, either from an installed package or a local file. +2. You'll need to add a new item to the `admin.auth.providers` array in your server configuration that will match the [format given above](#provider-configuration) +3. Restart your application, the provider should appear on your admin login page. ## Examples @@ -136,7 +130,7 @@ module.exports = ({ env }) => ({ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile' ], - callbackURL: strapi.admin.services.passport.getProviderCallbackUrl('google') + callbackURL: strapi.admin.services.passport.getStrategyCallbackURL('google') }, (request, accessToken, refreshToken, profile, done) => { done(null, { email: profile.email, @@ -184,7 +178,7 @@ module.exports = ({ env }) => ({ clientID: env('GITHUB_CLIENT_ID'), clientSecret: env('GITHUB_CLIENT_SECRET'), scope: ['user:email'], - callbackURL: strapi.admin.services.passport.getProviderCallbackUrl('github'), + callbackURL: strapi.admin.services.passport.getStrategyCallbackURL('github'), }, (accessToken, refreshToken, profile, done) => { done(null, { email: profile.emails[0].value, @@ -230,7 +224,7 @@ module.exports = ({ env }) => ({ { clientID: env('DISCORD_CLIENT_ID'), clientSecret: env('DISCORD_SECRET'), - callbackURL: strapi.admin.services.passport.getProviderCallbackUrl( + callbackURL: strapi.admin.services.passport.getStrategyCallbackURL( 'discord' ), scope: ['identify', 'email'], @@ -255,16 +249,19 @@ module.exports = ({ env }) => ({ ### Admin Panel URL -If your administration panel lives on a different host/port than your Strapi server, you will need to specify the values in the admin config. -To do so, heads to your `/config/admin.js` configuration file (create it if it doesn't exist) and tweaks the host and port fields. +If your administration panel lives on a different host/port than your Strapi server, you will need to modify the admin URL. +To do so, head to your `/config/server.js` configuration file and tweak the `admin.url` field. -For example, if your admin application has been started on `http://localhost:4000`, your admin configuration will look like the following: +For example, if your admin application has been started on `localhost:4000`, your configuration will look like the following: ```javascript -module.exports = { - host: 'http://localhost', - port: 4000 -}; +{ + ... + admin: { + url: 'http://localhost:4000/admin', + ... + } +} ``` ### Custom Logic @@ -291,3 +288,33 @@ const strategyInstance = new Strategy( }, ); ``` + +### Authentication Events + +The SSO feature adds a new [authentication event](configurations.html#available-options): `onSSOAutoRegistration`. + +This event is triggered whenever a user is created using the auto-register feature added by SSO. +It contains the created user (`event.user`), and the provider used to make the registration (`event.provider`). + +Example: + +```javascript +module.exports = () => ({ + admin: { + auth: { + events: { + onConnectionSuccess(e) {}, + onConnectionError(e) {}, + // ... + onSSOAutoRegistration(e) { + const { user, provider } = e; + + console.log( + `A new user (${user.id}) has been automatically registered using ${provider}` + ); + }, + }, + }, + }, +}); +``` From 30b14a1bf8bdfff4df37f67ec1857b448e8ceeda Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 4 Feb 2021 10:17:59 +0100 Subject: [PATCH 4/8] Add gold badge for sso --- developer-docs/latest/concepts/sso.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index 1a676073b1..11b4298ad2 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -1,4 +1,4 @@ -# Single Sign On +# Single Sign On [](https://strapi.io/pricing) Single-Sign-On on Strapi allows you to configure additional sign-in and sign-up methods for your administration panel. From aa8ad24b909fe78c016f4cb407fa364dadc03fc2 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 15 Feb 2021 15:15:35 +0100 Subject: [PATCH 5/8] Add npm/yarn tabs for strategies installation --- developer-docs/latest/concepts/sso.md | 62 +++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index 11b4298ad2..ecbfcba55f 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -95,16 +95,30 @@ To configure a provider, follow the procedure below: ## Examples -:::: tabs +:::::: tabs -::: tab Google +::::: tab Google Using: [passport-google-oauth2](https://github.com/mstade/passport-google-oauth2) +:::: tabs + +::: tab yarn + ```bash yarn add passport-google-oauth2 ``` +::: + +::: tab npm + +```bash +npm install --save passport-google-oauth2 +``` + +:::: + `/config/server.js` ```jsx @@ -146,16 +160,32 @@ module.exports = ({ env }) => ({ }); ``` -::: +::::: -::: tab Github +::::: tab Github Using: [passport-github](https://github.com/cfsghost/passport-github) +:::: tabs + +::: tab yarn + ```bash yarn add passport-github2 ``` +::: + +::: tab npm + +```bash +npm install --save passport-github2 +``` + +::: + +:::: + `/config/server.js` ```jsx @@ -191,16 +221,32 @@ module.exports = ({ env }) => ({ }, }); ``` -::: +::::: -::: tab Discord +::::: tab Discord Using: [passport-discord](https://github.com/nicholastay/passport-discord#readme) +:::: tabs + +::: tab yarn + ```bash yarn add passport-discord ``` +::: + +::: tab npm + +```bash +npm install --save passport-discord +``` + +::: + +:::: + `/config/server.js` ```jsx @@ -242,8 +288,8 @@ module.exports = ({ env }) => ({ }, }); ``` -::: -:::: +::::: +:::::: ## Advanced Customization From b0e41f9a146ebbc7725732796d85706e3d6786bd Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 15 Feb 2021 15:31:11 +0100 Subject: [PATCH 6/8] Use better wording for admin.url option --- developer-docs/latest/concepts/sso.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index ecbfcba55f..25b01fa135 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -298,13 +298,13 @@ module.exports = ({ env }) => ({ If your administration panel lives on a different host/port than your Strapi server, you will need to modify the admin URL. To do so, head to your `/config/server.js` configuration file and tweak the `admin.url` field. -For example, if your admin application has been started on `localhost:4000`, your configuration will look like the following: +For example, if your admin application has been started on `https://api.example.com`, your configuration will look like the following: ```javascript { ... admin: { - url: 'http://localhost:4000/admin', + url: 'https://api.example.com/admin', ... } } From 1b44f9c0a8ed5b666f7654868a79b6c19977d497 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 15 Feb 2021 15:35:45 +0100 Subject: [PATCH 7/8] Add comments & filenames for code examples help the user understand what's what --- developer-docs/latest/concepts/sso.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index 25b01fa135..207a502443 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -300,14 +300,16 @@ To do so, head to your `/config/server.js` configuration file and tweak the `adm For example, if your admin application has been started on `https://api.example.com`, your configuration will look like the following: +`/config/server.js` + ```javascript -{ - ... +module.exports = () => ({ + // ... admin: { + // ... url: 'https://api.example.com/admin', - ... - } -} + }, +}); ``` ### Custom Logic @@ -344,10 +346,14 @@ It contains the created user (`event.user`), and the provider used to make the r Example: +`/config/server.js` ```javascript module.exports = () => ({ + // ... admin: { + // ... auth: { + // ... events: { onConnectionSuccess(e) {}, onConnectionError(e) {}, From b798a2c627261eec2498707cc414d905f52e4ddd Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 15 Feb 2021 15:55:27 +0100 Subject: [PATCH 8/8] Add information about the callback URL + add comments for the custom logic --- developer-docs/latest/concepts/sso.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/developer-docs/latest/concepts/sso.md b/developer-docs/latest/concepts/sso.md index 207a502443..d7b503c9b7 100644 --- a/developer-docs/latest/concepts/sso.md +++ b/developer-docs/latest/concepts/sso.md @@ -53,10 +53,12 @@ A passport strategy is usually built by instantiating it using 2 parameters: the The configuration object depends on the strategy needs, but often asks for a callback URL to be redirected to once the connection has been made on the provider side. -You can generate a specific callback URL for your provider using the `getStrategyCallbackURL` method. +You can generate a specific callback URL for your provider using the `getStrategyCallbackURL` method. This URL also needs to be written on the provider side in order to allow redirection from it. + +The format of the callback URL is the following: `/admin/connect/`. ::: tip -`strapi.admin.services.passport.getStrategyCallbackURL` is a Strapi helper you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL as a string. +`strapi.admin.services.passport.getStrategyCallbackURL` is a Strapi helper you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL. ::: If needed, this is also where you will put your client ID and secret key for your OAuth2 application. @@ -326,13 +328,15 @@ For example, if you want to allow only people with an official strapi.io email a ```javascript const strategyInstance = new Strategy( configuration, - (email, done) => { - if (!email.endsWith('@strapi.io')) { - done(new Error('Forbidden email address')); - return; + ({ email, username }, done) => { + // If the email ends with @strapi.io + if (email.endsWith('@strapi.io')) { + // Then we continue with the data given by the provider + return done(null, { email, username }); } - done(null, { email }); + // Otherwise, we continue by sending an error to the done function + done(new Error('Forbidden email address')); }, ); ```