Users & Permissions plugin
The Users & Permissions plugin provides a full authentication process based on JSON Web Tokens (JWT) to protect your API, and an access-control list (ACL) strategy that enables you to manage permissions between groups of users. The Users & Permissions plugin is installed by default.
The user guide describes how to use the Users & Permissions plugin from the admin panel. The present page is more about the developer-related aspects of using the Users & Permissions plugin.
Concept
The Users & Permissions plugin adds an access layer to your application.
The plugin uses JWTs
to authenticate users. Your JWT contains your user ID, which is matched to the group your user is in and used to determine whether to allow access to the route.
Each time an API request is sent the server checks if an Authorization
header is present and verifies if the user making the request has access to the resource.
Manage role permissions
Public role
This is the default role used when the server receives a request without an Authorization
header. Any permissions (i.e. accessible endpoints) granted to this role will be accessible by anyone.
It is common practice to select find
/ findOne
endpoints when you want your front-end application to access all the content without requiring user authentication and authorization.
Authenticated role
This is the default role that is given to every new user at creation if no role is provided. In this role you define routes that a user can access.
Permissions management
By clicking on the Role name, you can see all functions available in your application (with these functions related to the specific route displayed).
If you check a function name, it makes this route accessible by the current role you are editing. On the right sidebar you can see the URL related to this function.
Update the default role
When you create a user without a role, or if you use the /api/auth/local/register
route, the authenticated
role is given to the user.
To change the default role, go to the Advanced settings
tab and update the Default role for authenticated users
option.
Authentication
Login
Submit the user's identifier and password credentials for authentication. On successful authentication the response data will have the user's information along with an authentication token.
Local
The identifier
param can be an email or username.
- Axios
- Postman
import axios from 'axios';
// Request API.
axios
.post('http://localhost:1337/api/auth/local', {
identifier: 'user@strapi.io',
password: 'strapiPassword',
})
.then(response => {
// Handle success.
console.log('Well done!');
console.log('User profile', response.data.user);
console.log('User token', response.data.jwt);
})
.catch(error => {
// Handle error.
console.log('An error occurred:', error.response);
});
If you use Postman, set the body to raw and select JSON as your data format:
{
"identifier": "user@strapi.io",
"password": "strapiPassword"
}
If the request is successful you will receive the user's JWT in the jwt
key:
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU",
"user": {
"id": 1,
"username": "user",
...
}
}
Token usage
The jwt
may then be used for making permission-restricted API requests. To make an API request as a user place the JWT into an Authorization
header of the GET
request.
Any request without a token will assume the public
role permissions by default. Modify the permissions of each user's role in the admin dashboard.
Authentication failures return a 401 (unauthorized)
error.
Usage
The token
variable is the data.jwt
received when logging in or registering.
import axios from 'axios';
const token = 'YOUR_TOKEN_HERE';
// Request API.
axios
.get('http://localhost:1337/posts', {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then(response => {
// Handle success.
console.log('Data: ', response.data);
})
.catch(error => {
// Handle error.
console.log('An error occurred:', error.response);
});
JWT configuration
You can configure the JWT generation by using the plugins configuration file.
Strapi uses jsonwebtoken to generate the JWT.
Available options:
jwtSecret
: random string used to create new JWTs, typically set using theJWT_SECRET
environment variable.jwt.expiresIn
: expressed in seconds or a string describing a time span.
Eg: 60, "45m", "10h", "2 days", "7d", "2y". A numeric value is interpreted as a seconds count. If you need more advanced examples please see the ms package.
- JavaScript
- TypeScript
module.exports = ({ env }) => ({
// ...
'users-permissions': {
config: {
jwt: {
expiresIn: '7d',
},
},
},
// ...
});
export default ({ env }) => ({
// ...
'users-permissions': {
config: {
jwt: {
expiresIn: '7d',
},
},
},
// ...
});
Setting JWT expiry for more than 30 days is not recommended due to security concerns.
Registration
Configuration
If you have added any additional fields to your user model that need to be accepted on registration, they need to be added to the list of allowed fields in the register
configuration option, otherwise they will not be accepted.
For example, if you have added a field called "nickname" that you wish to accept from the API on user registration:
- JavaScript
- TypeScript
module.exports = ({ env }) => ({
// ...
"users-permissions": {
config: {
register: {
allowedFields: ["nickname"],
},
},
},
// ...
});
export default ({ env }) => ({
// ...
"users-permissions": {
config: {
register: {
allowedFields: ["nickname"],
},
},
},
// ...
});
Usage
Creates a new user in the database with a default role as 'registered'.
import axios from 'axios';
// Request API.
// Add your own code here to customize or restrict how the public can register new users.
axios
.post('http://localhost:1337/api/auth/local/register', {
username: 'Strapi user',
email: 'user@strapi.io',
password: 'strapiPassword',
})
.then(response => {
// Handle success.
console.log('Well done!');
console.log('User profile', response.data.user);
console.log('User token', response.data.jwt);
})
.catch(error => {
// Handle error.
console.log('An error occurred:', error.response);
});
Providers
Grant and Purest allow you to use OAuth and OAuth2 providers to enable authentication in your application.
For a better understanding, review the following description of the login flow. The example uses github
as the provider but it works the same for other providers.
Understanding the login flow
Let's say that:
- Strapi's backend is located at:
strapi.website.com
, and - Your app frontend is located at:
website.com
- The user goes on your frontend app (
https://website.com
) and clicks on your buttonconnect with Github
. - The frontend redirects the tab to the backend URL:
https://strapi.website.com/api/connect/github
. - The backend redirects the tab to the GitHub login page where the user logs in.
- Once done, Github redirects the tab to the backend URL:
https://strapi.website.com/api/connect/github/callback?code=abcdef
. - The backend uses the given
code
to get anaccess_token
from Github that can be used for a period of time to make authorized requests to Github to get the user info. - Then, the backend redirects the tab to the url of your choice with the param
access_token
(example:http://website.com/connect/github/redirect?access_token=eyfvg
). - The frontend (
http://website.com/connect/github/redirect
) calls the backend withhttps://strapi.website.com/api/auth/github/callback?access_token=eyfvg
that returns the Strapi user profile with itsjwt
.
(Under the hood, the backend asks Github for the user's profile and a match is done on Github user's email address and Strapi user's email address). - The frontend now possesses the user's
jwt
, which means the user is connected and the frontend can make authenticated requests to the backend!
An example of a frontend app that handles this flow can be found here: react login example app.
Setting up the server url
Before setting up a provider you must specify the absolute url of your backend in server.js
.
example - config/server.js
- JavaScript
- TypeScript
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
url: env('', 'http://localhost:1337'),
});
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
url: env('', 'http://localhost:1337'),
});
Later you will give this url to your provider.
For development, some providers accept the use of localhost urls but many don't. In this case we recommend to use ngrok (ngrok http 1337
) that will make a proxy tunnel from a url it created to your localhost url (ex: url: env('', 'https://5299e8514242.ngrok.io'),
).
Setting up the provider - examples
Instead of a generic explanation we decided to show an example for each provider. You can also create your own custom provider.
In the following examples, the frontend app will be the react login example app.
It (the frontend app) will be running on http://localhost:3000
.
Strapi (the backend) will be running on http://localhost:1337
.
- GitHub
- AWS Cognito
- Discord
- Twitch
- VK
- CAS
- Auth0
- Patreon
- Keycloak
Using ngrok
Github doesn't accept localhost
urls.
Use ngrok
to serve the backend app.
ngrok http 1337
Don't forget to update the server url in the backend config file config/server.js
and the server url in your frontend app (environment variable REACT_APP_BACKEND_URL
if you use react login example app) with the generated ngrok url.
Github configuration
- Visit the OAuth Apps list page https://github.com/settings/developers
- Click on New OAuth App button
- Fill the information (replace with your own ngrok url):
- Application name: Strapi GitHub auth
- Homepage URL:
https://65e60559.ngrok.io
- Application description: Strapi provider auth description
- Authorization callback URL:
https://65e60559.ngrok.io/api/connect/github/callback
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the GitHub provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: 53de5258f8472c140917
- Client Secret: fb9d0fe1d345d9ac7f83d7a1e646b37c554dae8b
- The redirect URL to your front-end app:
http://localhost:3000/connect/github/redirect
- Enable:
Using ngrok
Facebook doesn't accept localhost
urls.
Use ngrok
to serve the backend app.
ngrok http 1337
Don't forget to update the server url in the backend config file config/server.js
and the server url in your frontend app (environment variable REACT_APP_BACKEND_URL
if you use react login example app) with the generated ngrok url.
Facebook configuration
- Visit the Developer Apps list page
https://developers.facebook.com/apps/ - Click on Add a New App button
- Fill the Display Name in the modal and create the app
- Setup a Facebook Login product
- Click on the PRODUCTS > Facebook login > Settings link in the left menu
- Fill the information and save (replace with your own ngrok url):
- Valid OAuth Redirect URIs:
https://65e60559.ngrok.io/api/connect/facebook/callback
- Valid OAuth Redirect URIs:
- Then, click on Settings in the left menu
- Then on Basic link
- You should see your Application ID and secret, save them for later
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Facebook provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: 2408954435875229
- Client Secret: 4fe04b740b69f31ea410b9391ff3b5b0
- The redirect URL to your front-end app:
http://localhost:3000/connect/facebook/redirect
- Enable:
Using ngrok
Google accepts the localhost
urls.
The use of ngrok
is not needed.
Google configuration
- Visit the Google Developer Console
https://console.developers.google.com/ - Click on the Select a project dropdown in the top menu
- Then click NEW PROJECT button
- Fill the Project name input and create
Wait a few seconds while the application is created.
- On the project dropdown, select your new project
- Click on Go to APIs overview under the APIs card
- Then click on the Credentials link in the left menu
- Click on OAuth consent screen button
- Choose External and click on create
- Fill the Application name and save
- Then click on Create credentials button
- Choose OAuth client ID option
- Fill the information:
- Name:
Strapi Auth
- Authorized redirect URIs:
http://localhost:1337/api/connect/google/callback
- Name:
- Click on OAuth 2.0 Client IDs name of the client you just created
- You should see your Application ID and secret, save them for later
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Google provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: 226437944084-o2mojv5i4lfnng9q8kq3jkf5v03avemk.apps.googleusercontent.com
- Client Secret: aiTbMoiuJQflSBy6uQrfgsni
- The redirect URL to your front-end app:
http://localhost:3000/connect/google/redirect
- Enable:
Using ngrok
AWS Cognito accepts the localhost
urls.
The use of ngrok
is not needed.
AWS Cognito configuration
- Visit the AWS Management Console
https://aws.amazon.com/console/ - If needed, select your Region in the top right corner next to the Support dropdown
- Select the Services dropdown in the top left corner
- Click on Cognito in the
Security, Identity & Compliance
section - Then click on the Manage User Pools button
- If applicable either create or use an existing user pool. You will find hereafter a tutorial to create a User Pool
https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html - Go to the App clients section in your cognito user pool and create a new client with the name
Strapi Auth
and set all the parameters and then click on Create app client - You should now have an App client id and by clicking on the button Show Details you will be able to see the App client secret. Do copy those two values App client id and App client secret somewhere for later use when configuring the AWS Cognito provider in Strapi.
- Go to the App integration section and click on App client settings
- Look for your app client named
Strapi Auth
and enable Cognito User Pool by checking it in the Enabled Identity Providers section of your newly created App client - Fill in your callback URL and Sign out URL with the value
http://localhost:1337/api/connect/cognito/callback
or the one provided by your AWS Cognito provider in Strapi - In the Oauth 2.0 section select
Authorization code grant
andImplicit grant
for the Allowed OAuth Flows and selectemail
,openid
andprofile
for the Allowed OAuth Scopes - You can now click on Save changes and if you have already configured your domain name then you should be able to see a link to the Launch Hosted UI. You can click on it in order to display the AWS Cognito login page. In case you haven't yet configured your domain name, use the link Choose domain name at the bottom right of the page in order to configure your domain name. On that page you will have an
Amazon Cognito Domain
section where aDomain prefix
is already setup. Type a domain prefix to use for the sign-up and sign-in pages that are hosted by Amazon Cognito, this domain prefix together with the.auth.YOUR_REGION.amazoncognito.com
will be the Host URI (Subdomain) value for your strapi configuration later on.
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Cognito provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: fill in the App client id (
5bd7a786qdupjmi0b3s10vegdt
) - Client Secret: fill in the App client secret (
19c5c78dsfsdfssfsdfhpdb4nkpb145vesdfdsfsffgh7vwd6g45jlipbpb
) - Host URI (Subdomain): fill in the URL value that you copied earlier (
myapp67b50345-67b50b17-local.auth.eu-central-1.amazoncognito.com
) - The redirect URL to your front-end app: if you are using strapi react-login https://github.com/strapi/strapi-examples/tree/master/examples/login-react/ use
http://localhost:3000/connect/cognito/redirect
but if you do not yet have a front-end app to test your Cognito configuration you can then use the following URLhttp://localhost:1337/api/auth/cognito/callback
- Enable:
Using ngrok
Twitter doesn't accept localhost
urls.
Use ngrok
to serve the backend app.
ngrok http 1337
Don't forget to update the server url in the backend config file config/server.js
and the server url in your frontend app (environment variable REACT_APP_BACKEND_URL
if you use react login example app) with the generated ngrok url.
Twitter configuration
- Visit the Apps list page
https://developer.twitter.com/en/apps - Click on Create an app button
- Fill the information (replace with your own ngrok url):
- App name: Strapi Twitter auth
- Application description: This is a demo app for Strapi auth
- Tell us how this app will be used: - here write a message enough long -
- At the end of the process you should see your Application ID and secret, save them for later
- Go to you app setting and click on edit Authentication settings
- Enable 3rd party authentication AND Request email address from users
- Fill the information (replace with your own ngrok url):
- Callback URLs:
https://65e60559.ngrok.io/api/connect/twitter/callback
- Website URL:
https://65e60559.ngrok.io
- Privacy policy:
https://d73e70e88872.ngrok.io
- Terms of service:
https://d73e70e88872.ngrok.io
- Callback URLs:
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Twitter provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- API Key: yfN4ycGGmKXiS1njtIYxuN5IH
- Api Secret: Nag1en8S4VwqurBvlW5OaFyKlzqrXFeyWhph6CZlpGA2V3VR3T
- The redirect URL to your front-end app:
http://localhost:3000/connect/twitter/redirect
- Enable:
Using ngrok
Discord accepts the localhost
urls.
The use of ngrok
is not needed.
Discord configuration
- Visit the Apps list page on the developer portal
https://discordapp.com/developers/applications/ - Click on New application button
- Fill the name and create
- Click on OAuth2 in the left menu
- And click on Add redirect button
- Fill the Redirect input with
http://localhost:1337/api/connect/discord/callback
URL and save - Click on General information in the left menu
- You should see your Application ID and secret, save them for later
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Discord provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: 665118465148846081
- Client Secret: iJbr7mkyqyut-J2hGvvSDch_5Dw5U77J
- The redirect URL to your front-end app:
http://localhost:3000/connect/discord/redirect
- Enable:
Using ngrok
Twitch accepts the localhost
urls.
The use of ngrok
is not needed.
Twitch configuration
- Visit the Apps list page on the developer console
https://dev.twitch.tv/console/apps - Click on Register Your Application button
- Fill the information:
- Name: Strapi auth
- OAuth Redirect URLs:
http://localhost:1337/api/connect/twitch/callback
- Category: Choose a category
- Click on Manage button of your new app
- Generate a new Client Secret with the New Secret button
- You should see your Application ID and secret, save them for later
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Twitch provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: amuy279g8wt68qlht3u4gek4oykh5j
- Client Secret: dapssh10uo97gg2l25qufr8wen3yr6
- The redirect URL to your front-end app:
http://localhost:3000/connect/twitch/redirect
- Enable:
Using ngrok
Facebook doesn't accept localhost
urls.
Use ngrok
to serve the backend app.
ngrok http 1337
Don't forget to update the server url in the backend config file config/server.js
and the server url in your frontend app (environment variable REACT_APP_BACKEND_URL
if you use react login example app) with the generated ngrok url.
Instagram configuration
- Visit the Developer Apps list page
https://developers.facebook.com/apps/ - Click on Add a New App button
- Fill the Display Name in the modal and create the app
- Setup an Instagram product
- Click on the PRODUCTS > Instagram > Basic Display link in the left menu
- Then click on the Create new application button (and valid the modal)
- Fill the information (replace with your own ngrok url):
- Valid OAuth Redirect URIs:
https://65e60559.ngrok.io/api/connect/instagram/callback
- Deauthorize:
https://65e60559.ngrok.io
- Data Deletion Requests:
https://65e60559.ngrok.io
- Valid OAuth Redirect URIs:
- On the App Review for Instagram Basic Display click on Add to submission for instagram_graph_user_profile.
- You should see your Application ID and secret, save them for later
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Instagram provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: 563883201184965
- Client Secret: f5ba10a7dd78c2410ab6b8a35ab28226
- The redirect URL to your front-end app:
http://localhost:3000/connect/instagram/redirect
- Enable:
Using ngrok
VK accepts the localhost
urls.
The use of ngrok
is not needed.
VK configuration
- Visit the Apps list page
https://vk.com/apps?act=manage - Click on Create app button
- Fill the information:
- Title: Strapi auth
- Platform: Choose Website option
- Website address:
http://localhost:1337
- Base domain:
localhost
- Click on the Settings link in the left menu
- Click on the Open API link to enable this option
- Fill the information:
- Authorized redirect URL:
http://localhost:1337/api/connect/vk/callback
- Authorized redirect URL:
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the VK provider
- Fill the information:
- Enable:
ON
- Client ID: 7276416
- Client Secret: cFBUSghLXGuxqnCyw1N3
- The redirect URL to your front-end app:
http://localhost:3000/connect/vk/redirect
- Enable:
Using ngrok
LinkedIn accepts the localhost
urls.
The use of ngrok
is not needed.
LinkedIn configuration
- Visit the Apps list page
https://www.linkedin.com/developers/apps - Click on Create app button
- Fill the information:
- App name: Strapi auth
- LinkedIn Page: Enter a LinkedIn page name to associate with the app or click Create a new LinkedIn Page to create a new one
- App Logo: Upload a square image that is at least 100x100 pixels.
- Click on the Create app to create the app
- On the app page click on Auth tab
- Fill the information:
- Authorized redirect URL:
http://localhost:1337/api/connect/linkedin/callback
- Authorized redirect URL:
- On the app page click on Products tab.
- Select
Sign In with LinkedIn
from the product list to enable it.
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the LinkedIn provider
- Fill the information:
- Enable:
ON
- Client ID: 84witsxk641rlv
- Client Secret: HdXO7a7mkrU5a6WN
- The redirect URL to your front-end app:
http://localhost:3000/connect/linkedin/redirect
- Enable:
Using ngrok
A remote CAS server can be configured to accept localhost
URLs or you can run your own CAS server locally that accepts them.
The use of ngrok
is not needed.
CAS configuration
- CAS is an SSO server that supports many different methods of verifying a users identity, retrieving attributes out the user and communicating that information to applications via protocols such as SAML, OIDC, and the CAS protocol. Strapi can use a CAS server for authentication if CAS is deployed with support for OIDC.
- CAS could already be used by your company or organization or you can setup a local CAS server by cloning the CAS Overlay project or using the newer CAS Initializr to create an overlay project.
- The CAS server must be configured so it can act as an OpenID Connect Provider
- CAS version 6.3.x and higher is known to work with Strapi but older versions that support OIDC may work.
- Define a CAS OIDC service for Strapi and store it in whichever CAS service registry is being used.
- The CAS service definition might look something like this for a local strapi deployment:
{
"@class": "org.apereo.cas.services.OidcRegisteredService",
"clientId": "thestrapiclientid",
"clientSecret": "thestrapiclientsecret",
"bypassApprovalPrompt": true,
"serviceId": "^http(|s)://localhost:1337/.*",
"name": "Local Strapi",
"id": 20201103,
"evaluationOrder": 50,
"attributeReleasePolicy": {
"@class": "org.apereo.cas.services.ReturnMappedAttributeReleasePolicy",
"allowedAttributes": {
"@class": "java.util.TreeMap",
"strapiemail": "groovy { return attributes['mail'].get(0) }",
"strapiusername": "groovy { return attributes['username'].get(0) }"
}
}
}
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/plugins/users-permissions/providers - Click on the Cas provider
- Fill the information:
- Enable:
ON
- Client ID: thestrapiclientid
- Client Secret: thestrapiclientsecret
- The redirect URL to your front-end app:
http://localhost:1337/api/connect/cas/redirect
- The Provider Subdomain such that the following URLs are correct for the CAS deployment you are targeting:
For example, if running CAS locally with a login URL of:authorize_url: https://[subdomain]/oidc/authorize
access_url: https://[subdomain]/oidc/token
profile_url: https://[subdomain]/oidc/profilehttps://localhost:8443/cas/login
, the value for the provider subdomain would belocalhost:8443/cas
. - Enable:
Using ngrok
Reddit accepts the localhost
urls.
The use of ngrok
is not needed.
Reddit configuration
- Visit the Reddit authorized applications preferences page
https://www.reddit.com/prefs/apps - Click on the create another app... button near the bottom
- Select web app for the type
- Fill the name and redirect uri input in
- Click the create app button
- Note that the Client ID is located under the app type (web app)
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Reddit provider
- Fill the information (replace with your own client ID and secret):
- Enable:
ON
- Client ID: hmxSBOit0SCjSQ
- Client Secret: gwR9hCjK_PMYVYNGeDLS4WLB8g7xqg
- The redirect URL to your front-end app:
http://localhost:3000/connect/reddit/redirect
- Enable:
Using ngrok
Auth0 accepts the localhost
urls.
The use of ngrok
is not needed.
Auth0 configuration
- Visit your Auth0 tenant dashboard
- In API section, create a new API
- In application, create a
machine-to-machine
application and select the API that you have just created - In settings of this app set these values:
- Allowed Callback URLs:
http://localhost:1337/api/connect/auth0/callback
- Allowed Logout URLs:
http://localhost:3000
- Allowed Web Origins:
http://localhost:3000
- Allowed Callback URLs:
- At the bottom of settings, show "Advanced Settings" and go to the "Grant Types". Ensure that these grants are checked/enabled:
- Implicit
- Authorization Code
- Refresh Token
- Client Credentials
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Auth0 provider
- Fill the information:
- Enable:
ON
- Client ID:
<Your Auth0 Client ID>
- Client Secret:
<Your Auth0 Client Secret>
- Subdomain:
<Your Auth0 tenant url>
, example it is the part in bold in the following url: https://my-tenant.eu.auth0.com/ - The redirect URL to your front-end app:
http://localhost:3000/connect/auth0
- Enable:
Using ngrok
Patreon does not accept localhost
urls.
Use ngrok
to serve the backend app.
ngrok http 1337
Don't forget to update the server url in the Strapi config file ./config/server.js
and the server URL in your frontend app (environment variable REACT_APP_BACKEND_URL
if you use react login example app) with the generated ngrok URL.
Patreon configuration
- You must be a Patreon Creator in order to register an Oauth client.
- Go to the Patreon developer portal
- Click on Clients & API Keys
- Click on "Create Client"
- Enter the details of your organization and website.
- There is a drop-down for "App Category" but no explanation of what the different categories mean. "Community" seems to work fine.
- You can choose either version 1 or version 2 of the API - neither are actively developed. Version 2 is probably the best choice. See their developer docs for more detail.
- Under "Redirect URI's" enter
https://your-site.com/api/connect/patreon/callback
- Save the client details and you will then see the Client ID and Client Secret.
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Patreon provider
- Fill the information:
- Enable:
ON
- Client ID:
<Your Patreon Client ID>
- as above - Client Secret:
<Your Patreon Client Secret>
- as above
- Enable:
Using ngrok
Keycloak accepts the localhost
urls.
The use of ngrok
is not needed.
Keycloak configuration
- Visit your Keycloak admin dashboard
- If you don't already have a realm, you'll want to create one
- In the Clients section of your realm, create a new client
- Under the capability config, ensure you set
Client Authentication
to on to ensure you can create a private key - Under the access settings, ensure you set the following values:
- Valid redirect URIs:
http://localhost:1337/api/connect/keycloak/callback
andhttp://localhost:1337/api/connect/keycloak
- Allowed Web Origins:
http://localhost:3000
andhttp://localhost:1337
- Valid redirect URIs:
- In the Client Scopes section, ensure you have the
email
andprofile
scopes set to default - In the Client Scopes section, ensure you have the
openid
scope set to default, if you don't have this you will need to manually create it in the global Client Scopes
Strapi configuration
- Visit the User Permissions provider settings page
http://localhost:1337/admin/settings/users-permissions/providers - Click on the Keycloak provider
- Fill the information:
- Enable:
ON
- Client ID:
<Your Keycloak Client ID>
- Client Secret:
<Your Keycloak Client Secret>
- Subdomain:
<Your Keycloak realm url>
, example is eitherkeycloak.example.com/realms/strapitest
orkeycloak.example.com/auth/realms/strapitest
without the protocol before it - The redirect URL to your front-end app:
http://localhost:3000/connect/keycloak/redirect
- (Optional) Set the JWKS URL if you have a custom JWKS URL, example is like
https://keycloak.example.com/auth/realms/strapitest/protocol/openid-connect/certs
- Enable:
Your configuration is done.
Launch the backend and the react login example app, go to http://localhost:3000
and try to connect to the provider your configured.
Creating a custom provider
You can also use the register
lifecycle function to create your own custom provider in the src/index.js|ts
file of your Strapi application. Use the following code example adjusted to your needs:
module.exports = {
register({ strapi }) {
strapi
.plugin("users-permissions")
.service("providers-registry")
.add("example-provider-name", {
icon: "",
enabled: true,
grantConfig: {
key: "",
secret: "",
callback: `${strapi.config.server.url}/auth/example-provider-name/callback`,
scope: ["email"],
authorize_url: "https://awesome.com/authorize",
access_url: "https://awesome.com/token",
oauth: 2,
},
async authCallback({ accessToken, providers, purest }) {
// use whatever you want here to get the user info
return {
username: "test",
email: "test",
};
},
});
},
};
For additional information on parameters passed to grantConfig
, please refer to the grant
documentation. For additional information about purest
please refer to purest
documentation.
Setup the frontend
Once you have configured strapi and the provider, in your frontend app you have to :
- Create a button that links to
GET STRAPI_BACKEND_URL/api/connect/${provider}
(ex:https://strapi.mywebsite/api/connect/github
). - Create a frontend route like
FRONTEND_URL/connect/${provider}/redirect
that have to handle theaccess_token
param and that have to requestSTRAPI_BACKEND_URL/api/auth/${provider}/callback
with theaccess_token
parameter.
The JSON request response will be{ "jwt": "...", "user": {...} }
.
Now you can make authenticated requests. More info here: token usage.
- Error 429: It's most likely because your login flow fell into a loop. To make new requests to the backend, you need to wait a few minutes or restart the backend.
- Grant: missing session or misconfigured provider: It may be due to many things.
- The redirect url can't be built: Make sure you have set the backend url in
config/server.js
: Setting up the server url - A session/cookie/cache problem: You can try again in a private tab.
- The incorrect use of a domain with ngrok: Check your urls and make sure that you use the ngrok url instead of
http://localhost:1337
. Don't forget to check the backend url set in the example app atsrc/config.js
.
- The redirect url can't be built: Make sure you have set the backend url in
- You can't access your admin panel: It's most likely because you built it with the backend url set with a ngrok url and you stopped/restarted ngrok. You need to replace the backend url with the new ngrok url and run
yarn build
ornpm run build
again.
Reset password
Can only be used for users registered using the email provider.
- Forgot & Reset flow
- Change the password flow
The assumed general flow:
- The user goes to your forgotten password page.
- The user enters their email address.
- Your forgotten password page sends a request to the backend to send an email with the reset password link to the user.
- The user receives the email and clicks on the special link.
- The link redirects the user to your reset password page.
- The user enters their new password.
- The reset password page sends a request to the backend with the new password.
- If the request contains the code contained in the link at step 3, the password is updated.
- The user can log in with the new password.
The following section details steps 3 and 7.
Forgotten password: ask for the reset password link
This action sends an email to a user with the link to your reset password page. The link will be enriched with the url param code
that is needed for the reset password at step 7.
First, you must specify the following:
- In the admin panel: Settings > USERS & PERMISSIONS PLUGIN > Advanced Settings > Reset Password page, the
url
to your reset password page. - In the admin panel: Settings > USERS & PERMISSIONS PLUGIN > Email Template page, the Shipper email.
Then, your forgotten password page has to make the following request to your backend:
import axios from 'axios';
// Request API.
axios
.post('http://localhost:1337/api/auth/forgot-password', {
email: 'user@strapi.io', // user's email
})
.then(response => {
console.log('Your user received an email');
})
.catch(error => {
console.log('An error occurred:', error.response);
});
Reset Password: send the new password
This action will update the user password.
This also works with the GraphQL Plugin, with the resetPassword
mutation.
Your reset password page has to make the following request to your backend:
import axios from 'axios';
// Request API.
axios
.post('http://localhost:1337/api/auth/reset-password', {
code: 'privateCode', // code contained in the reset link of step 3.
password: 'userNewPassword',
passwordConfirmation: 'userNewPassword',
})
.then(response => {
console.log("Your user's password has been reset.");
})
.catch(error => {
console.log('An error occurred:', error.response);
});
You can also update an authenticated user password through the /change-password
API endpoint:
import axios from 'axios';
// Request API.
axios.post(
'http://localhost:1337/api/auth/change-password',
{
currentPassword: 'currentPassword',
password: 'userNewPassword',
passwordConfirmation: 'userNewPassword',
},
{
headers: {
Authorization: 'Bearer <user jwt>',
},
}
);
Email validation
In production, make sure the url
config property is set. Otherwise the validation link will redirect to localhost
. More info on the config here.
After registering, if you have set Enable email confirmation to ON, the user will receive a confirmation link by email. The user has to click on it to validate their registration.
Example of the confirmation link: https://yourwebsite.com/api/auth/email-confirmation?confirmation=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaWF0IjoxNTk0OTgxMTE3LCJleHAiOjE1OTc1NzMxMTd9.0WeB-mvuguMyr4eY8CypTZDkunR--vZYzZH6h6sChFg
If needed you can re-send the confirmation email by making the following request:
import axios from 'axios';
// Request API.
axios
.post(`http://localhost:1337/api/auth/send-email-confirmation`, {
email: 'user@strapi.io', // user's email
})
.then(response => {
console.log('Your user received an email');
})
.catch(error => {
console.error('An error occurred:', error.response);
});
User object in Strapi context
The user
object is available to successfully authenticated requests.
The authenticated user
object is a property of ctx.state
.
create: async ctx => {
const { id } = ctx.state.user;
const depositObj = {
...ctx.request.body,
depositor: id,
};
const data = await strapi.services.deposit.add(depositObj);
// Send 201 `created`
ctx.created(data);
};
Templating emails
By default this plugin comes with two templates: reset password and email address confirmation. The templates use Lodash's template()
method to populate the variables.
You can update these templates under Plugins > Roles & Permissions > Email Templates tab in the admin panel.
Reset Password
USER
(object)username
email
TOKEN
corresponds to the token generated to be able to reset the password.URL
is the link where the user will be redirected after clicking on it in the email.SERVER_URL
is the absolute server url (configured in server configuration).
Email address confirmation
USER
(object)username
email
CODE
corresponds to the CODE generated to be able confirm the user email.URL
is the Strapi backend URL that confirms the code (by default/auth/email-confirmation
).SERVER_URL
is the absolute server url (configured in server configuration).
Security configuration
JWTs can be verified and trusted because the information is digitally signed. To sign a token a secret is required. By default Strapi generates and stores it in ./extensions/users-permissions/config/jwt.js
.
This is useful during development but for security reasons it is recommended to set a custom token via an environment variable JWT_SECRET
when deploying to production.
By default you can set a JWT_SECRET
environment variable and it will be used as secret. If you want to use another variable you can update the configuration file.
- JavaScript
- TypeScript
module.exports = {
jwtSecret: process.env.SOME_ENV_VAR,
};
export default {
jwtSecret: process.env.SOME_ENV_VAR,
};
You can learn more about configuration here.
Creating a custom callback validator
By default, Strapi SSO only redirects to the redirect URL that is exactly equal to the url in the configuration:
If you need to configure a custom handler to accept other URLs, you can create a callback validate
function in your plugins.js for the users-permissions
plugin.
// ... other plugins configuration ...
// Users & Permissions configuration
'users-permissions': {
enabled: true,
config: {
callback: {
validate: (cbUrl, options) => {
// cbUrl is where Strapi is being asked to redirect the auth info
// that was received from the provider to
// in this case, we will only validate that the
// if using a base url, you should always include the trailing slash
// although in real-world usage you should also include the full paths
if (cbUrl.startsWith('https://myproxy.mysite.com/') ||
cbUrl.startsWith('https://mysite.com/')) {
return;
}
// Note that you MUST throw an error to fail validation
// return values are not checked
throw new Error('Invalid callback url');
},
},
},
},
Creating a custom password validation
To add password validation at the API level, you can create a custom function passed to validationRules
in the configuration of the Users & Permissions plugin, as in the following example:
// ... other plugins configuration ...
// Users & Permissions configuration
'users-permissions': {
config: {
validationRules: {
validatePassword(value) {
if (value.length < 8) {
// custom error message
throw new Error('password should be more than 8 letters');
}
if (value.length > 24) {
// throws default error message
return false;
}
return true; // Validation passed
},
},
},
},