diff --git a/docusaurus/docs/cms/backend-customization/examples/authentication.md b/docusaurus/docs/cms/backend-customization/examples/authentication.md index a7b38c5d60..d9652b72fd 100644 --- a/docusaurus/docs/cms/backend-customization/examples/authentication.md +++ b/docusaurus/docs/cms/backend-customization/examples/authentication.md @@ -99,7 +99,8 @@ const Login = () => { body: JSON.stringify(values), }); /** - * Gets the JWT from the server response + * Gets the JWT from the server response. + * The actual response is { jwt, user }, but we only need the JWT here. */ const { jwt } = await res.json(); /** @@ -159,9 +160,11 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) - maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + accessTokenLifespan: 600, // 10 minutes (default) + maxRefreshTokenLifespan: 2592000, // 30 days (default) + idleRefreshTokenLifespan: 1209600, // 14 days (default) + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) }, }, }, @@ -257,7 +260,6 @@ const EnhancedLogin = () => { export default EnhancedLogin; ``` -```
diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md index c899dd9a6b..99e5edd3e9 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md @@ -22,7 +22,7 @@ You have read the [Users & Permissions providers documentation](/cms/configurati ## Auth0 configuration :::note -AWS Cognito accepts the `localhost` urls.
+Auth0 accepts the `localhost` URLs.
The use of `ngrok` is not needed. ::: diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md index 041bcd0c46..0a29b071db 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md @@ -1,6 +1,6 @@ --- title: CAS provider setup for Users & Permissions -description: Learn how to setup the CAS provider for the Users & Permissions feature. +description: Learn how to set up the CAS provider for the Users & Permissions feature. displayed_sidebar: cmsSidebar tags: - users and permissions @@ -13,7 +13,7 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # CAS provider setup for Users & Permissions -The present page explains how to setup the Auth0 provider for the [Users & Permissions feature](/cms/features/users-permissions). +The present page explains how to set up the CAS provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites You have read the [Users & Permissions providers documentation](/cms/configurations/users-and-permissions-providers). @@ -58,7 +58,7 @@ The use of `ngrok` is not needed. ## Strapi configuration -1. Visit the User & Permissions provider settings page at +1. Visit the User & Permissions provider settings page at 2. Click on the **CAS** provider 3. Fill the information: - **Enable**: `ON` diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md index 034f6009a4..9e1ed55a1c 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md @@ -19,6 +19,10 @@ The present page explains how to setup the Instagram provider for the [Users & P You have read the [Users & Permissions providers documentation](/cms/configurations/users-and-permissions-providers). ::: +:::caution +The Instagram Basic Display API was deprecated and shut down by Meta on December 4, 2024. This provider may no longer work as documented below. +::: + ## Instagram configuration :::note diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md index 5bcf35057a..f8668f83e2 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md @@ -19,6 +19,10 @@ The present page explains how to setup the LinkedIn provider for the [Users & Pe You have read the [Users & Permissions providers documentation](/cms/configurations/users-and-permissions-providers). ::: +:::caution +LinkedIn has migrated from "Sign In with LinkedIn" to "Sign In with LinkedIn using OpenID Connect." The `r_liteprofile` and `r_emailaddress` scopes have been deprecated. The setup steps below may need adjustments to match the new OpenID Connect product. +::: + ## LinkedIn configuration :::note @@ -37,7 +41,7 @@ The use of `ngrok` is not needed. 6. Fill the information: - **Authorized redirect URL**: `http://localhost:1337/api/connect/linkedin/callback` 7. On the app page click on **Products** tab. -8. Select `Sign In with LinkedIn` from the product list to enable it. +8. Select `Sign In with LinkedIn using OpenID Connect` from the product list to enable it. ## Strapi configuration diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md index b21329e45e..88a93544cf 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md @@ -19,6 +19,10 @@ The present page explains how to setup the Twitter provider for the [Users & Per You have read the [Users & Permissions providers documentation](/cms/configurations/users-and-permissions-providers). ::: +:::caution +Twitter has rebranded to X. The developer portal has been significantly restructured, and free-tier API access is now limited. The setup steps and URLs below may be outdated. +::: + ## Twitter configuration :::note diff --git a/docusaurus/docs/cms/features/users-permissions.md b/docusaurus/docs/cms/features/users-permissions.md index 11fa3c7017..a87a23b725 100644 --- a/docusaurus/docs/cms/features/users-permissions.md +++ b/docusaurus/docs/cms/features/users-permissions.md @@ -2,7 +2,7 @@ title: Users & Permissions description: Learn to use the Users & Permissions feature to manage end-user accounts, authentication, and role-based access. displayed_sidebar: cmsSidebar -toc_max_heading_level: 5 +toc_max_heading_level: 4 tags: - admin panel - users & permissions @@ -95,7 +95,7 @@ When ticking an action or permission box, related bound routes of the API are di **Path:** *Users & Permissions plugin > Roles* -Although the 2 default end-user roles cannot be deleted, the other ones can, as long as no end user still has this role attributed to their account. +Although the Public role cannot be deleted, other roles can be deleted. Users currently assigned to a deleted role are automatically reassigned to the Public role. 1. Click on the delete button on the right side of the role's record. 2. In the deletion window, click on the **Confirm** button to confirm the deletion. @@ -138,7 +138,7 @@ Click the search button above the table :::note Username generation during provider registration When an end user registers via an authentication provider (such as Google or GitHub), Strapi automatically generates a username from the provider email address, using the part before the `@` symbol (e.g., `joe` from `joe@gmail.com`). -If the generated username is already taken, Strapi appends an incrementing number to make it unique (e.g., `joe1`, then `joe2`, and so on). The existing account's username is not affected. +If the generated username is already taken, Strapi appends a random number to make it unique (e.g., `joe1234`). The existing account's username is not affected. ::: ### Email templates @@ -226,7 +226,7 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'legacy-support', jwt: { - expiresIn: '7d', // Traditional JWT expiry + expiresIn: '30d', // Traditional JWT expiry }, }, }, @@ -257,9 +257,11 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) + accessTokenLifespan: 600, // 10 minutes (default) maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + idleRefreshTokenLifespan: 1209600, // 14 days + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) httpOnly: false, // Set to true for HTTP-only cookies cookie: { name: 'strapi_up_refresh', @@ -286,9 +288,11 @@ export default ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) + accessTokenLifespan: 600, // 10 minutes (default) maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + idleRefreshTokenLifespan: 1209600, // 14 days + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) httpOnly: false, // Set to true for HTTP-only cookies cookie: { name: 'strapi_up_refresh', @@ -364,8 +368,8 @@ The following options are available in [the `/config/plugins` file](/cms/configu | --------- | ----------- | ---- | ------- | | `ratelimit` | Settings to customize the rate limiting of the authentications and registration endpoints | object | `{}` | | `ratelimit.enabled` | Enable or disable the rate limiter | boolean | `true` | -| `ratelimit.interval` | Time window for requests to be considered as part of the same rate limiting bucket | object | `{ min: 5 }` | -| `ratelimit.max` | Maximum number of requests allowed in the time window | integer | `5` | +| `ratelimit.interval` | Time window for requests to be considered as part of the same rate limiting bucket (in milliseconds) | integer | `60000` (1 minute) | +| `ratelimit.max` | Maximum number of requests allowed in the time window | integer | `10` | | `ratelimit.prefixKey` | Prefix for the rate limiting key | string | `${userIdentifier}:${requestPath}:${ctx.request.ip}` | @@ -381,8 +385,8 @@ module.exports = ({ env }) => ({ config: { ratelimit: { enabled: true, - interval: { min: 5 }, - max: 5, + interval: 60000, // 1 minute + max: 10, }, }, }, @@ -402,8 +406,8 @@ export default ({ env }) => ({ config: { ratelimit: { enabled: true, - interval: { min: 5 }, - max: 5, + interval: 60000, // 1 minute + max: 10, }, }, }, @@ -452,11 +456,9 @@ The following variables can be used: ### 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 `/src/extensions/users-permissions/config/jwt.js`. +JWTs can be verified and trusted because the information is digitally signed. To sign a token, a _secret_ is required. By default, Strapi stores it as the `JWT_SECRET` environment variable in the `.env` file. -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. +If you want to use a different environment variable, you can update the configuration file. @@ -573,362 +575,22 @@ If end users can register themselves on your front-end application (see "Enable ### API usage - 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. :::note 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. ::: -#### Authentication endpoints {#authentication-endpoints} - -The Users & Permissions feature provides the following authentication endpoints for user management and [Content API](/cms/api/rest) access: - -| Method | URL | Description | -| ------ | --- | ----------- | -| `POST` | `/api/auth/local` | User login with email/username and password
(see [`identifier` parameter](#identifier)) | -| `POST` | `/api/auth/local/register` | [User registration](#user-registration) | -| `POST` | `/api/auth/forgot-password` | Request password reset | -| `POST` | `/api/auth/reset-password` | Reset password using token | -| `GET` | `/api/auth/email-confirmation` | Confirm user email address | -| `POST` | `/api/auth/send-email-confirmation` | Resend confirmation email | -| `POST` | `/api/auth/change-password` | Change password (requires authentication) | - -##### Session management endpoints - -When [session management](#jwt-management-modes) is enabled (`jwtManagement: 'refresh'`), additional endpoints are available: - -| Method | URL | Description | -| ------ | --- | ----------- | -| `POST` | `/api/auth/refresh` | Refresh access token using refresh token | -| `POST` | `/api/auth/logout` | Revoke user sessions (supports device-specific logout) | - -To refresh your authentication token, send the following request: - - - -``` -curl -X POST http://localhost:1337/api/auth/refresh \ - -H "Content-Type: application/json" \ - -d '{ - "refreshToken": "your-refresh-token" - }' -``` - - - -```json -{ - "jwt": "your-new-access-token" -} -``` - - - -To log out of all sessions, send the following request: - - - - -```bash -curl -X POST http://localhost:1337/api/auth/logout \ - -H "Authorization: Bearer your-access-token" -``` - - - - -#### User CRUD endpoints - -The Users & Permissions feature also exposes a set of endpoints for managing user records directly. These endpoints are separate from the authentication endpoints and allow you to create, read, update, and delete user entries: - -| Method | URL | Description | -| ------ | --- | ----------- | -| `GET` | `/api/users` | Find all users | -| `GET` | `/api/users/me` | Get the currently authenticated user | -| `GET` | `/api/users/:id` | Find a specific user by ID | -| `GET` | `/api/users/count` | Get the total number of users | -| `POST` | `/api/users` | Create a new user | -| `PUT` | `/api/users/:id` | Update a user by ID | -| `DELETE` | `/api/users/:id` | Delete a user by ID | - -:::note -These endpoints are protected by the role-based permission system. To access them, enable the corresponding action (e.g., `find`, `findOne`, `create`, `update`, `destroy`, `me`, `count`) for the desired role in *Users & Permissions plugin > Roles*. -::: - -##### Get the authenticated user - -The `GET /api/users/me` endpoint returns the user associated with the current JWT. The endpoint is useful for front-end applications that need to display user profile information after login. - - - - -```bash -curl -X GET http://localhost:1337/api/users/me \ - -H "Authorization: Bearer your-access-token" -``` - - - - - -```json -{ - "id": 1, - "documentId": "abc123", - "username": "kai", - "email": "kai@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-15T09:00:00.000Z", - "updatedAt": "2024-01-15T09:00:00.000Z", - "publishedAt": "2024-01-15T09:00:00.000Z" -} -``` - - - - -##### Find all users - -The `GET /api/users` endpoint returns a list of all users. [`populate` and `filters` parameters](/cms/api/rest/parameters) can be passed as query strings. - - - - -```bash -curl -X GET "http://localhost:1337/api/users?populate=role" \ - -H "Authorization: Bearer your-access-token" -``` - - - - - -```json -[ - { - "id": 1, - "documentId": "abc123", - "username": "kai", - "email": "kai@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "role": { - "id": 1, - "name": "Authenticated", - "description": "Default role given to authenticated user.", - "type": "authenticated", - "createdAt": "2024-01-01T00:00:00.000Z", - "updatedAt": "2024-01-01T00:00:00.000Z" - }, - "createdAt": "2024-01-15T09:00:00.000Z", - "updatedAt": "2024-01-15T09:00:00.000Z", - "publishedAt": "2024-01-15T09:00:00.000Z" - } -] -``` - - - - -##### Create a user - -The `POST /api/users` endpoint creates a new user. Unlike `/api/auth/local/register`, this endpoint requires `create` permission for the Users & Permissions plugin. - - - - -```bash -curl -X POST http://localhost:1337/api/users \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-access-token" \ - -d '{ - "username": "newuser", - "email": "newuser@strapi.io", - "password": "Password123", - "role": 1, - "confirmed": true - }' -``` - - - - - -```json -{ - "id": 2, - "documentId": "def456", - "username": "newuser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-16T10:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" -} -``` - - - - -##### Update a user - -The `PUT /api/users/:id` endpoint updates an existing user by ID. - - - - -```bash -curl -X PUT http://localhost:1337/api/users/2 \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-access-token" \ - -d '{ - "username": "updateduser" - }' -``` - - - - - -```json -{ - "id": 2, - "documentId": "def456", - "username": "updateduser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-17T11:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" -} -``` - - - - -##### Delete a user - -The `DELETE /api/users/:id` endpoint deletes a user by ID. +The Users & Permissions feature exposes authentication, user management, and role/permission endpoints through both the REST API and the GraphQL API. Full endpoint references with request and response examples are available on the dedicated sub-pages: - - - -```bash -curl -X DELETE http://localhost:1337/api/users/2 \ - -H "Authorization: Bearer your-access-token" -``` - - - - - -```json -{ - "id": 2, - "documentId": "def456", - "username": "updateduser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-17T11:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" -} -``` - - - - -#### Identifier - -The `identifier` parameter sent with requests can be an email or username, as in the following examples: - - - - - -```js -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: - -```json -{ - "identifier": "user@strapi.io", - "password": "strapiPassword" -} -``` - -If the request is successful you will receive the **user's JWT** in the `jwt` key: - -**Legacy mode response:** -```json -{ - "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU", - "user": { - "id": 1, - "username": "user", - ... - } -} -``` - -**Session management mode response:** -```json -{ - "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Short-lived access token - "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Long-lived refresh token - "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 panel. - -Authentication failures return a `401 (unauthorized)` error. - -The `token` variable is the `data.jwt` received when logging in or registering. +The `jwt` received when logging in or registering 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 request using the Bearer token pattern: ```js import axios from 'axios'; @@ -937,7 +599,7 @@ const token = 'YOUR_TOKEN_HERE'; // Request API. axios - .get('http://localhost:1337/posts', { + .get('http://localhost:1337/api/posts', { headers: { Authorization: `Bearer ${token}`, }, @@ -952,38 +614,13 @@ axios }); ``` -#### User registration - -Creating a new user in the database with a default role as 'authenticated' can be done as in the following example: - -```js -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); - }); -``` +Any request without a token will assume the `public` role permissions by default. Modify the permissions of each user's role in the admin panel. Authentication failures return a `401 (unauthorized)` error. #### User object in Strapi context The `user` object is available to successfully authenticated requests. -The authenticated `user` object is a property of `ctx.state`. +The authenticated `user` object is a property of `ctx.state`, as shown in the following example: ```js create: async ctx => { diff --git a/docusaurus/docs/cms/features/users-permissions/graphql-api.md b/docusaurus/docs/cms/features/users-permissions/graphql-api.md new file mode 100644 index 0000000000..f13409d034 --- /dev/null +++ b/docusaurus/docs/cms/features/users-permissions/graphql-api.md @@ -0,0 +1,336 @@ +--- +title: Users & Permissions GraphQL API +description: GraphQL queries and mutations for authentication, user management, and role-based access with the Users & Permissions plugin. +displayed_sidebar: cmsSidebar +tags: + - users & permissions + - GraphQL API + - authentication + - API +--- + +# Users & Permissions GraphQL API + +This page documents all GraphQL queries and mutations provided by the Users & Permissions plugin. The [GraphQL plugin](/cms/plugins/graphql) must be installed. For configuration details, see the main [Users & Permissions page](/cms/features/users-permissions). + +## Authentication + +Authentication mutations handle login, registration, and password management. Public mutations do not require an Authorization header. + +### Login + +The `login` mutation authenticates a user and returns a JWT token: + +```graphql +mutation { + login(input: { identifier: "user@example.com", password: "yourPassword" }) { + jwt + user { + id + documentId + username + email + confirmed + blocked + } + } +} +``` + +Input type `UsersPermissionsLoginInput`: + +- `identifier` (String!) -- email or username +- `password` (String!) +- `provider` (String, defaults to "local") + +Returns `UsersPermissionsLoginPayload`: `jwt` (String), `user` (UsersPermissionsMe) + +Auth: Public + +### Register + +The `register` mutation creates a new user account and returns a JWT token: + +```graphql +mutation { + register(input: { username: "newuser", email: "new@example.com", password: "Password123!" }) { + jwt + user { + id + documentId + username + email + } + } +} +``` + +Input type `UsersPermissionsRegisterInput`: + +- `username` (String!) +- `email` (String!) +- `password` (String!) + +Returns `UsersPermissionsLoginPayload` + +Auth: Public + +:::note +Only `username`, `email`, and `password` are accepted by default. Additional fields require `register.allowedFields` configuration. +::: + +### Forgot password + +The `forgotPassword` mutation sends a password reset email to the user: + +```graphql +mutation { + forgotPassword(email: "user@example.com") { + ok + } +} +``` + +Input: `email` (String!) -- direct argument, not wrapped in an input type. + +Returns `UsersPermissionsPasswordPayload`: `ok` (Boolean!) + +Auth: Public + +### Reset password + +The `resetPassword` mutation sets a new password using the token received by email: + +```graphql +mutation { + resetPassword(code: "resetTokenFromEmail", password: "NewPassword123!", passwordConfirmation: "NewPassword123!") { + jwt + user { + id + username + email + } + } +} +``` + +Input (direct arguments): + +- `code` (String!) -- reset token from email +- `password` (String!) +- `passwordConfirmation` (String!) + +Returns `UsersPermissionsLoginPayload` + +Auth: Public + +### Change password + +The `changePassword` mutation updates the password for the currently authenticated user: + +```graphql +mutation { + changePassword(currentPassword: "OldPassword123!", password: "NewPassword456!", passwordConfirmation: "NewPassword456!") { + jwt + user { + id + username + email + } + } +} +``` + +Requires an Authorization header with a Bearer token. + +Input (direct arguments): + +- `currentPassword` (String!) +- `password` (String!) +- `passwordConfirmation` (String!) + +Returns `UsersPermissionsLoginPayload` + +Auth: Authenticated + +### Email confirmation + +The `emailConfirmation` mutation confirms a user's email address using the token received by email: + +```graphql +mutation { + emailConfirmation(confirmation: "confirmationTokenFromEmail") { + jwt + user { + id + username + email + confirmed + } + } +} +``` + +Input: `confirmation` (String!) + +Returns `UsersPermissionsLoginPayload` + +Auth: Public + +:::note +Unlike the REST equivalent (which redirects), the GraphQL mutation returns a JWT and user object directly. +::: + +## User queries and mutations + +These operations retrieve and manage user records. They require the corresponding permission to be enabled for the requesting user's role. + +### Get authenticated user (me query) + +The `me` query returns the profile of the currently authenticated user: + +```graphql +query { + me { + id + documentId + username + email + confirmed + blocked + role { + id + name + description + type + } + } +} +``` + +Requires an Authorization header. Returns `UsersPermissionsMe` type. + +### Create a user + +The `createUsersPermissionsUser` mutation creates a new user record: + +```graphql +mutation { + createUsersPermissionsUser(data: { username: "newuser", email: "new@example.com", password: "Password123!" }) { + data { + documentId + username + email + } + } +} +``` + +Input: `UsersPermissionsUserInput` (auto-generated from User content-type schema, with `password` field added) + +Auth: Requires `plugin::users-permissions.user.create` permission + +### Update a user + +The `updateUsersPermissionsUser` mutation updates an existing user record: + +```graphql +mutation { + updateUsersPermissionsUser(id: "documentId123", data: { username: "updatedname" }) { + data { + documentId + username + email + } + } +} +``` + +Auth: Requires `plugin::users-permissions.user.update` permission + +### Delete a user + +The `deleteUsersPermissionsUser` mutation removes a user record: + +```graphql +mutation { + deleteUsersPermissionsUser(id: "documentId123") { + data { + documentId + username + } + } +} +``` + +Auth: Requires `plugin::users-permissions.user.destroy` permission + +## Role mutations + +Role mutations manage end-user roles. They return `{ ok: true }` on success (not the role data). + +### Create a role + +The `createUsersPermissionsRole` mutation creates a new role: + +```graphql +mutation { + createUsersPermissionsRole(data: { name: "Editor", description: "Can edit content" }) { + ok + } +} +``` + +Auth: Requires `plugin::users-permissions.role.createRole` permission + +### Update a role + +The `updateUsersPermissionsRole` mutation updates an existing role: + +```graphql +mutation { + updateUsersPermissionsRole(id: "1", data: { name: "Senior Editor", description: "Can edit and publish" }) { + ok + } +} +``` + +Auth: Requires `plugin::users-permissions.role.updateRole` permission + +### Delete a role + +The `deleteUsersPermissionsRole` mutation removes a role: + +```graphql +mutation { + deleteUsersPermissionsRole(id: "3") { + ok + } +} +``` + +Auth: Requires `plugin::users-permissions.role.deleteRole` permission + +:::note +The Public role cannot be deleted. +::: + +## Types reference + +This section lists the key GraphQL types used across Users & Permissions operations. + +### Input types + +| Type | Fields | Used by | +|------|--------|---------| +| `UsersPermissionsLoginInput` | `identifier` (String!), `password` (String!), `provider` (String) | `login` mutation | +| `UsersPermissionsRegisterInput` | `username` (String!), `email` (String!), `password` (String!) | `register` mutation | + +### Response types + +| Type | Fields | Used by | +|------|--------|---------| +| `UsersPermissionsLoginPayload` | `jwt` (String), `user` (UsersPermissionsMe!) | `login`, `register`, `resetPassword`, `changePassword`, `emailConfirmation` | +| `UsersPermissionsPasswordPayload` | `ok` (Boolean!) | `forgotPassword` | +| `UsersPermissionsMe` | `id` (ID!), `documentId` (ID!), `username` (String!), `email` (String), `confirmed` (Boolean), `blocked` (Boolean), `role` (UsersPermissionsMeRole) | `me` query, nested in login payload | +| `UsersPermissionsMeRole` | `id` (ID!), `name` (String!), `description` (String), `type` (String) | Nested in `UsersPermissionsMe` | diff --git a/docusaurus/docs/cms/features/users-permissions/rest-api.md b/docusaurus/docs/cms/features/users-permissions/rest-api.md new file mode 100644 index 0000000000..d75e970ed4 --- /dev/null +++ b/docusaurus/docs/cms/features/users-permissions/rest-api.md @@ -0,0 +1,680 @@ +--- +title: Users & Permissions REST API +description: REST API reference for authentication, user management, roles, and permissions with the Users & Permissions plugin. +displayed_sidebar: cmsSidebar +tags: + - users & permissions + - REST API + - authentication + - API +--- + +# Users & Permissions REST API + +The Users & Permissions plugin exposes a set of REST API endpoints for authentication, user management, and role/permission management. These endpoints are separate from the standard content-type CRUD endpoints and have their own response shapes. For a general overview of the plugin's features and configuration, see the [Users & Permissions introduction](/cms/features/users-permissions). + +All endpoints use the `/api` prefix. For example, if your Strapi server runs at `http://localhost:1337`, the login endpoint is `http://localhost:1337/api/auth/local`. + +## Authentication + +Authentication endpoints handle login, registration, and password management. Most of these endpoints are public by default and do not require a Bearer token. + +### Login + +`POST /api/auth/local` + +Authenticates a user with their identifier (email or username) and password, returning a JWT and the user object. + +Request body: + +```json +{ + "identifier": "user@example.com", + "password": "yourPassword" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/local \ + -H "Content-Type: application/json" \ + -d '{"identifier": "user@example.com", "password": "yourPassword"}' +``` + +Example response (200): + +```json +{ + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 1, + "documentId": "x74detpqybxw0bn6ormua5g2", + "username": "testuser1", + "email": "user@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" + } +} +``` + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 400 | `"Invalid identifier or password"` | Wrong credentials | +| 400 | `"Your account email is not confirmed"` | Email confirmation required but not completed | +| 400 | `"Your account has been blocked by an administrator"` | Account blocked | + +This endpoint is rate limited (default: 10 requests per 60 seconds). + +### Register + +`POST /api/auth/local/register` + +Creates a new user account and returns a JWT along with the user object. + +Request body: + +```json +{ + "username": "newuser", + "email": "newuser@example.com", + "password": "Password123!" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/local/register \ + -H "Content-Type: application/json" \ + -d '{"username": "newuser", "email": "newuser@example.com", "password": "Password123!"}' +``` + +Example response (200): + +```json +{ + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 2, + "documentId": "xjpaytstw1gm7wdfoc6c2k13", + "username": "newuser", + "email": "newuser@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" + } +} +``` + +:::note +Only `username`, `email`, and `password` are accepted in the request body by default. To allow additional fields (e.g., a `fullName` field you added to the User content-type), you must explicitly list them in the `register.allowedFields` configuration. See [Registration configuration](/cms/features/users-permissions#registration-configuration) for details. + +When email confirmation is enabled, the response contains only the user object without a JWT -- the user must confirm their email before they can log in. + +The newly registered user is assigned the default role (typically "Authenticated"). +::: + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 400 | `"Email or Username are already taken"` | Duplicate email or username | +| 400 | `"Invalid parameters: fieldName"` | Extra fields not listed in `allowedFields` | +| 400 | `"Register action is currently disabled"` | Registration disabled in admin settings | + +This endpoint is rate limited. + +### Forgot password + +`POST /api/auth/forgot-password` + +Sends a password reset email to the specified address. Requires an email provider to be configured. + +Request body: + +```json +{ + "email": "user@example.com" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/forgot-password \ + -H "Content-Type: application/json" \ + -d '{"email": "user@example.com"}' +``` + +Example response (200): + +```json +{ + "ok": true +} +``` + +:::note +This endpoint always returns `{ "ok": true }` regardless of whether the email address exists in the system. This is intentional to prevent user enumeration attacks. +::: + +This endpoint is rate limited. + +### Reset password + +`POST /api/auth/reset-password` + +Resets a user's password using a token received by email. All 3 fields are required. + +Request body: + +```json +{ + "code": "resetTokenFromEmail", + "password": "NewPassword123!", + "passwordConfirmation": "NewPassword123!" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/reset-password \ + -H "Content-Type: application/json" \ + -d '{"code": "resetTokenFromEmail", "password": "NewPassword123!", "passwordConfirmation": "NewPassword123!"}' +``` + +Example response (200): Same shape as the [login](#login) response (jwt + user). + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 400 | `"passwordConfirmation is a required field"` | Missing `passwordConfirmation` | +| 400 | `"Incorrect code provided"` | Invalid or expired reset token | + +This endpoint is rate limited. + +### Change password + +`POST /api/auth/change-password` + +Changes the password for the currently authenticated user. Requires a valid Bearer token. All 3 fields are required. + +Request body: + +```json +{ + "currentPassword": "OldPassword123!", + "password": "NewPassword456!", + "passwordConfirmation": "NewPassword456!" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/change-password \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"currentPassword": "OldPassword123!", "password": "NewPassword456!", "passwordConfirmation": "NewPassword456!"}' +``` + +Example response (200): Same shape as the [login](#login) response (jwt + user). + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 400 | `"passwordConfirmation is a required field"` | Missing `passwordConfirmation` | +| 400 | `"The provided current password is invalid"` | Wrong current password | +| 400 | New password must differ from current password | Same password reused | + +This endpoint is rate limited. + +### Email confirmation + +`GET /api/auth/email-confirmation` + +Confirms a user's email address using a token from the confirmation email. + +Query parameter: `confirmation` -- the token received in the confirmation email. + +Example request: + +```bash +curl -G http://localhost:1337/api/auth/email-confirmation \ + --data-urlencode "confirmation=confirmationTokenHere" +``` + +After confirming the email, Strapi redirects the user to the URL configured in the admin panel under Settings > Users & Permissions > Advanced Settings > "Redirection url". + +### Send email confirmation + +`POST /api/auth/send-email-confirmation` + +Resends the confirmation email to a user who has not yet confirmed their email address. + +Request body: + +```json +{ + "email": "user@example.com" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/send-email-confirmation \ + -H "Content-Type: application/json" \ + -d '{"email": "user@example.com"}' +``` + +Example response (200): + +```json +{ + "email": "user@example.com", + "sent": true +} +``` + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 400 | `"Already confirmed"` | User already confirmed their email | +| 400 | `"Your account has been blocked by an administrator"` | Account blocked | + +This endpoint is rate limited. + +### Provider authentication + +`GET /api/connect/:provider` + +Redirects the user to a third-party provider's login page (e.g., Google, GitHub, Discord). Replace `:provider` with the provider name. See [Setting up providers](/cms/configurations/users-and-permissions-providers) for configuration instructions. + +### Provider callback + +`GET /api/auth/:provider/callback` + +Handles the OAuth callback after the user authenticates with a third-party provider. On success, returns the same response shape as [login](#login) (jwt + user). + +If the username derived from the provider profile already exists, a unique username is generated automatically to avoid conflicts. + +## Session management endpoints + +When session management is enabled (`jwtManagement: 'refresh'` in the plugin configuration), these additional endpoints become available. They return 404 when the default legacy JWT mode is active. + +### Refresh token + +`POST /api/auth/refresh` + +Exchanges a refresh token for a new access token. The old refresh token is invalidated and a new one is returned (token rotation). + +Request body: + +```json +{ + "refreshToken": "yourRefreshToken" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/refresh \ + -H "Content-Type: application/json" \ + -d '{"refreshToken": "yourRefreshToken"}' +``` + +Example response (200): + +```json +{ + "jwt": "newAccessToken", + "refreshToken": "newRefreshToken" +} +``` + +:::note +When `httpOnly` is enabled in the session configuration, the new refresh token is set as an HTTP-only cookie instead of being included in the response body. In that case, the response only contains `{ "jwt": "newAccessToken" }`. +::: + +### Logout + +`POST /api/auth/logout` + +Revokes all sessions for the authenticated user. Requires a valid Bearer token. + +Example request: + +```bash +curl -X POST http://localhost:1337/api/auth/logout \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): + +```json +{ + "ok": true +} +``` + +## Users + +User management endpoints handle CRUD operations on end-user records. Each endpoint requires the corresponding permission to be enabled for the user's role in the admin panel (Settings > Users & Permissions > Roles). + +:::caution Response format +User endpoints return bare JSON objects (not wrapped in a `data` key), unlike standard Strapi content-type endpoints. +::: + +### Get current user + +`GET /api/users/me` + +Returns the user associated with the provided JWT. Requires authentication. + +Example request: + +```bash +curl http://localhost:1337/api/users/me \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): + +```json +{ + "id": 1, + "documentId": "x74detpqybxw0bn6ormua5g2", + "username": "testuser1", + "email": "user@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" +} +``` + +### List users + +`GET /api/users` + +Returns a list of users. Supports `filters`, `sort`, and `pagination` query parameters. + +Example request: + +```bash +curl http://localhost:1337/api/users \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): An array of user objects. + +### Get a user + +`GET /api/users/:id` + +Returns a single user by their integer `id`. + +Example request: + +```bash +curl http://localhost:1337/api/users/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): A user object. + +### Count users + +`GET /api/users/count` + +Returns the total number of users. Supports the `filters` query parameter. + +Example request: + +```bash +curl http://localhost:1337/api/users/count \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): A bare integer, for example: + +```json +42 +``` + +### Create a user + +`POST /api/users` + +Creates a new user. If `role` is omitted, the default role is assigned. + +Request body: + +```json +{ + "username": "newuser", + "email": "newuser@example.com", + "password": "Password123!", + "role": 1, + "confirmed": true +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/users \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"username": "newuser", "email": "newuser@example.com", "password": "Password123!", "role": 1, "confirmed": true}' +``` + +Example response (201): A user object with the populated role. + +### Update a user + +`PUT /api/users/:id` + +Updates an existing user. Only include the fields you want to change. + +Example request: + +```bash +curl -X PUT http://localhost:1337/api/users/1 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"username": "updateduser"}' +``` + +Example response (200): The updated user object. + +Possible errors: + +| Status | Message | Cause | +|--------|---------|-------| +| 404 | `"User not found"` | No user with the given `id` | +| 400 | `"Username already taken"` or `"Email already taken"` | Duplicate value | + +### Delete a user + +`DELETE /api/users/:id` + +Deletes a user by their integer `id`. + +Example request: + +```bash +curl -X DELETE http://localhost:1337/api/users/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): The deleted user object. + +## Roles + +Role endpoints manage end-user roles and their associated permissions. These endpoints use the `/api/users-permissions/` prefix, not the standard `/api/` prefix used by content-type endpoints. + +### List roles + +`GET /api/users-permissions/roles` + +Returns all available roles with user counts. + +Example request: + +```bash +curl http://localhost:1337/api/users-permissions/roles \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): + +```json +{ + "roles": [ + { + "id": 1, + "name": "Authenticated", + "description": "Default role given to authenticated user.", + "type": "authenticated", + "nb_users": 2 + }, + { + "id": 2, + "name": "Public", + "description": "Default role given to unauthenticated user.", + "type": "public", + "nb_users": 0 + } + ] +} +``` + +### Get a role + +`GET /api/users-permissions/roles/:id` + +Returns a single role by `id`, including its full permissions tree. + +Example request: + +```bash +curl http://localhost:1337/api/users-permissions/roles/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): A role object with a nested `permissions` structure mapping plugins to controllers to actions. + +### Create a role + +`POST /api/users-permissions/roles` + +Creates a new role. + +Request body: + +```json +{ + "name": "Editor", + "description": "Can edit content", + "type": "editor" +} +``` + +Example request: + +```bash +curl -X POST http://localhost:1337/api/users-permissions/roles \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"name": "Editor", "description": "Can edit content", "type": "editor"}' +``` + +Example response (200): + +```json +{ + "ok": true +} +``` + +### Update a role + +`PUT /api/users-permissions/roles/:id` + +Updates an existing role. + +Example request: + +```bash +curl -X PUT http://localhost:1337/api/users-permissions/roles/1 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"description": "Updated description"}' +``` + +Example response (200): + +```json +{ + "ok": true +} +``` + +### Delete a role + +`DELETE /api/users-permissions/roles/:id` + +Deletes a role by `id`. The Public role cannot be deleted. When a role is deleted, users assigned to it are reassigned to the Public role. + +Example request: + +```bash +curl -X DELETE http://localhost:1337/api/users-permissions/roles/3 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): + +```json +{ + "ok": true +} +``` + +## Permissions + +The permissions endpoint returns the complete permission tree, showing which actions are available across all plugins and content-types. + +### List permissions + +`GET /api/users-permissions/permissions` + +Returns a nested object mapping plugins to controllers to actions. + +Example request: + +```bash +curl http://localhost:1337/api/users-permissions/permissions \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Example response (200): A nested `permissions` object where keys are plugin names, sub-keys are controller names, and values contain the available actions with their `enabled` status and `policy` information. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md index 2cdb374070..e5d2ce1375 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md @@ -56,3 +56,23 @@ An undefined `allowedFields` is treated as an empty array, and no fields are acc ### Manual procedure A codemod should handle this migration. If not, please refer to the documentation on how to [register allowed fields for the Users & Permissions plugin](/cms/features/users-permissions#registration-configuration). + +#### How it works in Strapi 5 + +The fields `username`, `email`, and `password` are always accepted by the registration endpoint -- they are hardcoded as `alwaysAllowedKeys` in the Users & Permissions plugin source. Any other field on the User content-type must be explicitly listed in `allowedFields` or the request will be rejected with a `400` status and an error message like `"Invalid parameters: fieldName"`. + +To allow additional fields on registration, update your plugin configuration: + +```js title="config/plugins.js" +module.exports = { + 'users-permissions': { + config: { + register: { + allowedFields: ['firstName', 'lastName'], + }, + }, + }, +}; +``` + +If you relied on the Strapi v4 behavior (all fields accepted by default), list every extra field in `allowedFields`. Fields not listed will be silently dropped or rejected. diff --git a/docusaurus/sidebars.js b/docusaurus/sidebars.js index 431e089361..0016140e9e 100644 --- a/docusaurus/sidebars.js +++ b/docusaurus/sidebars.js @@ -121,9 +121,22 @@ const sidebars = { id: 'cms/features/sso', }, { - type: 'doc', + type: 'category', label: 'Users & Permissions', - id: 'cms/features/users-permissions', + link: { type: 'doc', id: 'cms/features/users-permissions' }, + collapsed: true, + items: [ + { + type: 'doc', + label: 'REST API', + id: 'cms/features/users-permissions/rest-api', + }, + { + type: 'doc', + label: 'GraphQL API', + id: 'cms/features/users-permissions/graphql-api', + }, + ], }, { type: 'category', diff --git a/docusaurus/static/llms-code.txt b/docusaurus/static/llms-code.txt index 53753d111c..616eb80651 100644 --- a/docusaurus/static/llms-code.txt +++ b/docusaurus/static/llms-code.txt @@ -11439,7 +11439,8 @@ const Login = () => { body: JSON.stringify(values), }); /** - * Gets the JWT from the server response + * Gets the JWT from the server response. + * The actual response is { jwt, user }, but we only need the JWT here. */ const { jwt } = await res.json(); /** @@ -11499,9 +11500,11 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) - maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + accessTokenLifespan: 600, // 10 minutes (default) + maxRefreshTokenLifespan: 2592000, // 30 days (default) + idleRefreshTokenLifespan: 1209600, // 14 days (default) + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) }, }, }, @@ -12519,7 +12522,7 @@ Language: JavaScript File path: /src/extensions/users-permissions/strapi-server.js ```js -module.exports = (plugin) => { +module.exports = (plugin, { strapi }) => { // Add a new controller action plugin.controllers.user.deactivate = async (ctx) => { const { id } = ctx.params; @@ -12552,7 +12555,7 @@ Language: TypeScript File path: /src/extensions/users-permissions/strapi-server.ts ```ts -export default (plugin) => { +export default (plugin, { strapi }) => { // Add a new controller action plugin.controllers.user.deactivate = async (ctx) => { const { id } = ctx.params; @@ -12737,7 +12740,7 @@ Language: JavaScript File path: /src/extensions/users-permissions/strapi-server.js ```js -module.exports = (plugin) => { +module.exports = (plugin, { strapi }) => { const routes = plugin.routes['content-api'].routes; // 1. Add 'is-own-user' policy to update and delete @@ -12796,7 +12799,7 @@ Language: TypeScript File path: /src/extensions/users-permissions/strapi-server.ts ```ts -export default (plugin) => { +export default (plugin, { strapi }) => { const routes = plugin.routes['content-api'].routes; // 1. Add 'is-own-user' policy to update and delete @@ -24015,9 +24018,11 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) + accessTokenLifespan: 600, // 10 minutes (default) maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + idleRefreshTokenLifespan: 1209600, // 14 days + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) httpOnly: false, // Set to true for HTTP-only cookies cookie: { name: 'strapi_up_refresh', @@ -24044,9 +24049,11 @@ export default ({ env }) => ({ config: { jwtManagement: 'refresh', sessions: { - accessTokenLifespan: 604800, // 1 week (default) + accessTokenLifespan: 600, // 10 minutes (default) maxRefreshTokenLifespan: 2592000, // 30 days - idleRefreshTokenLifespan: 604800, // 7 days + idleRefreshTokenLifespan: 1209600, // 14 days + maxSessionLifespan: 86400, // 1 day (default) + idleSessionLifespan: 7200, // 2 hours (default) httpOnly: false, // Set to true for HTTP-only cookies cookie: { name: 'strapi_up_refresh', @@ -24070,7 +24077,7 @@ module.exports = ({ env }) => ({ config: { jwtManagement: 'legacy-support', jwt: { - expiresIn: '7d', // Traditional JWT expiry + expiresIn: '30d', // Traditional JWT expiry }, }, }, @@ -24119,7 +24126,7 @@ export default ({ env }) => ({ ## Rate limiting configuration -Description: | ratelimit | Settings to customize the rate limiting of the authentications and registration endpoints | object | {} | | ratelimit.enabled | Enable or disable the rate limiter | boolean | true | | ratelimit.interval | Time window for requests to be considered as part of the same rate limiting bucket | object | { min: 5 } | | ratelimit.max | Maximum number of requests allowed in the time window | integer | 5 | | ratelimit.prefixKey | Prefix for the rate limiting key | string | ${userIdentifier}:${requestPath}:${ctx.request.ip} | +Description: | ratelimit | Settings to customize the rate limiting of the authentications and registration endpoints | object | {} | | ratelimit.enabled | Enable or disable the rate limiter | boolean | true | | ratelimit.interval | Time window for requests to be considered as part of the same rate limiting bucket (in milliseconds) | integer | 60000 (1 minute) | | ratelimit.max | Maximum number of requests allowed in the time window | integer | 10 | | ratelimit.prefixKey | Prefix for the rate limiting key | string | ${userIdentifier}:${requestPath}:${ctx.request.ip} | (Source: https://docs.strapi.io/cms/features/users-permissions#rate-limiting-configuration) Language: JavaScript @@ -24133,8 +24140,8 @@ module.exports = ({ env }) => ({ config: { ratelimit: { enabled: true, - interval: { min: 5 }, - max: 5, + interval: 60000, // 1 minute + max: 10, }, }, }, @@ -24154,8 +24161,8 @@ export default ({ env }) => ({ config: { ratelimit: { enabled: true, - interval: { min: 5 }, - max: 5, + interval: 60000, // 1 minute + max: 10, }, }, }, @@ -24165,7 +24172,7 @@ export default ({ env }) => ({ ## Security configuration -Description: By default you can set a JWT_SECRET environment variable and it will be used as secret. +Description: If you want to use a different environment variable, you can update the configuration file. (Source: https://docs.strapi.io/cms/features/users-permissions#security-configuration) Language: JavaScript @@ -24226,376 +24233,876 @@ File path: /config/plugins.js|ts ``` -## Session management endpoints -Description: Code example from "Session management endpoints" -(Source: https://docs.strapi.io/cms/features/users-permissions#session-management-endpoints) +## Token usage +Description: The jwt received when logging in or registering may then be used for making permission-restricted API requests. +(Source: https://docs.strapi.io/cms/features/users-permissions#token-usage) Language: JavaScript File path: N/A -``` -curl -X POST http://localhost:1337/api/auth/refresh \ - -H "Content-Type: application/json" \ - -d '{ - "refreshToken": "your-refresh-token" - }' -``` - ---- -Language: JSON -File path: N/A - -```json -{ - "jwt": "your-new-access-token" -} -``` +```js +import axios from 'axios'; ---- -Language: Bash -File path: N/A +const token = 'YOUR_TOKEN_HERE'; -```bash -curl -X POST http://localhost:1337/api/auth/logout \ - -H "Authorization: Bearer your-access-token" +// Request API. +axios + .get('http://localhost:1337/api/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); + }); ``` -## Get the authenticated user -Description: Code example from "Get the authenticated user" -(Source: https://docs.strapi.io/cms/features/users-permissions#get-the-authenticated-user) +## User object in Strapi context +Description: The authenticated user object is a property of ctx.state, as shown in the following example: +(Source: https://docs.strapi.io/cms/features/users-permissions#user-object-in-strapi-context) -Language: Bash +Language: JavaScript File path: N/A -```bash -curl -X GET http://localhost:1337/api/users/me \ - -H "Authorization: Bearer your-access-token" -``` +```js +create: async ctx => { + const { id } = ctx.state.user; ---- -Language: JSON -File path: N/A + const depositObj = { + ...ctx.request.body, + depositor: id, + }; -```json -{ - "id": 1, - "documentId": "abc123", - "username": "kai", - "email": "kai@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-15T09:00:00.000Z", - "updatedAt": "2024-01-15T09:00:00.000Z", - "publishedAt": "2024-01-15T09:00:00.000Z" -} + const data = await strapi.services.deposit.add(depositObj); + + // Send 201 `created` + ctx.created(data); +}; ``` -## Find all users -Description: Code example from "Find all users" -(Source: https://docs.strapi.io/cms/features/users-permissions#find-all-users) -Language: Bash -File path: N/A +# Users & Permissions GraphQL API +Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api -```bash -curl -X GET "http://localhost:1337/api/users?populate=role" \ - -H "Authorization: Bearer your-access-token" -``` +## Login +Description: The login mutation authenticates a user and returns a JWT token: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#login) ---- -Language: JSON +Language: DOCKERFILE File path: N/A -```json -[ - { - "id": 1, - "documentId": "abc123", - "username": "kai", - "email": "kai@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "role": { - "id": 1, - "name": "Authenticated", - "description": "Default role given to authenticated user.", - "type": "authenticated", - "createdAt": "2024-01-01T00:00:00.000Z", - "updatedAt": "2024-01-01T00:00:00.000Z" - }, - "createdAt": "2024-01-15T09:00:00.000Z", - "updatedAt": "2024-01-15T09:00:00.000Z", - "publishedAt": "2024-01-15T09:00:00.000Z" +```dockerfile +mutation { + login(input: { identifier: "user@example.com", password: "yourPassword" }) { + jwt + user { + id + documentId + username + email + confirmed + blocked + } } -] +} ``` -## Create a user -Description: Code example from "Create a user" -(Source: https://docs.strapi.io/cms/features/users-permissions#create-a-user) +## Register +Description: The register mutation creates a new user account and returns a JWT token: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#register) -Language: Bash +Language: DOCKERFILE File path: N/A -```bash -curl -X POST http://localhost:1337/api/users \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-access-token" \ - -d '{ - "username": "newuser", - "email": "newuser@strapi.io", - "password": "Password123", - "role": 1, - "confirmed": true - }' +```dockerfile +mutation { + register(input: { username: "newuser", email: "new@example.com", password: "Password123!" }) { + jwt + user { + id + documentId + username + email + } + } +} ``` ---- -Language: JSON + +## Forgot password +Description: The forgotPassword mutation sends a password reset email to the user: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#forgot-password) + +Language: GRAPHQL File path: N/A -```json -{ - "id": 2, - "documentId": "def456", - "username": "newuser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-16T10:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" +```graphql +mutation { + forgotPassword(email: "user@example.com") { + ok + } } ``` -## Update a user -Description: Code example from "Update a user" -(Source: https://docs.strapi.io/cms/features/users-permissions#update-a-user) +## Reset password +Description: The resetPassword mutation sets a new password using the token received by email: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#reset-password) -Language: Bash +Language: DOCKERFILE File path: N/A -```bash -curl -X PUT http://localhost:1337/api/users/2 \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-access-token" \ - -d '{ - "username": "updateduser" - }' +```dockerfile +mutation { + resetPassword(code: "resetTokenFromEmail", password: "NewPassword123!", passwordConfirmation: "NewPassword123!") { + jwt + user { + id + username + email + } + } +} ``` ---- -Language: JSON + +## Change password +Description: The changePassword mutation updates the password for the currently authenticated user: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#change-password) + +Language: DOCKERFILE File path: N/A -```json -{ - "id": 2, - "documentId": "def456", - "username": "updateduser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-17T11:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" +```dockerfile +mutation { + changePassword(currentPassword: "OldPassword123!", password: "NewPassword456!", passwordConfirmation: "NewPassword456!") { + jwt + user { + id + username + email + } + } } ``` -## Delete a user -Description: Code example from "Delete a user" -(Source: https://docs.strapi.io/cms/features/users-permissions#delete-a-user) +## Email confirmation +Description: The emailConfirmation mutation confirms a user's email address using the token received by email: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#email-confirmation) -Language: Bash +Language: DOCKERFILE File path: N/A -```bash -curl -X DELETE http://localhost:1337/api/users/2 \ - -H "Authorization: Bearer your-access-token" +```dockerfile +mutation { + emailConfirmation(confirmation: "confirmationTokenFromEmail") { + jwt + user { + id + username + email + confirmed + } + } +} ``` ---- -Language: JSON + +## Get authenticated user (me query) +Description: The me query returns the profile of the currently authenticated user: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#get-authenticated-user-me-query) + +Language: GRAPHQL File path: N/A -```json -{ - "id": 2, - "documentId": "def456", - "username": "updateduser", - "email": "newuser@strapi.io", - "provider": "local", - "confirmed": true, - "blocked": false, - "createdAt": "2024-01-16T10:00:00.000Z", - "updatedAt": "2024-01-17T11:00:00.000Z", - "publishedAt": "2024-01-16T10:00:00.000Z" +```graphql +query { + me { + id + documentId + username + email + confirmed + blocked + role { + id + name + description + type + } + } } ``` -## Identifier -Description: The identifier parameter sent with requests can be an email or username, as in the following examples: -(Source: https://docs.strapi.io/cms/features/users-permissions#identifier) +## Create a user +Description: The createUsersPermissionsUser mutation creates a new user record: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#create-a-user) -Language: JavaScript +Language: GRAPHQL File path: N/A -```js -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); - }); +```graphql +mutation { + createUsersPermissionsUser(data: { username: "newuser", email: "new@example.com", password: "Password123!" }) { + data { + documentId + username + email + } + } +} ``` ---- -Language: JSON -File path: N/A -```json -{ - "identifier": "user@strapi.io", - "password": "strapiPassword" -} -``` +## Update a user +Description: The updateUsersPermissionsUser mutation updates an existing user record: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#update-a-user) ---- -Language: JSON +Language: GRAPHQL File path: N/A -```json -{ - "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTc2OTM4MTUwLCJleHAiOjE1Nzk1MzAxNTB9.UgsjjXkAZ-anD257BF7y1hbjuY3ogNceKfTAQtzDEsU", - "user": { - "id": 1, - "username": "user", - ... +```graphql +mutation { + updateUsersPermissionsUser(id: "documentId123", data: { username: "updatedname" }) { + data { + documentId + username + email } + } } ``` ---- -Language: JSON + +## Delete a user +Description: The deleteUsersPermissionsUser mutation removes a user record: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#delete-a-user) + +Language: GRAPHQL File path: N/A -```json -{ - "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Short-lived access token - "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Long-lived refresh token - "user": { - "id": 1, - "username": "user", - ... +```graphql +mutation { + deleteUsersPermissionsUser(id: "documentId123") { + data { + documentId + username } + } } ``` -## Token usage -Description: The token variable is the data.jwt received when logging in or registering. -(Source: https://docs.strapi.io/cms/features/users-permissions#token-usage) +## Create a role +Description: The createUsersPermissionsRole mutation creates a new role: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#create-a-role) -Language: JavaScript +Language: GRAPHQL File path: N/A -```js -import axios from 'axios'; +```graphql +mutation { + createUsersPermissionsRole(data: { name: "Editor", description: "Can edit content" }) { + ok + } +} +``` -const token = 'YOUR_TOKEN_HERE'; -// Request API. -axios - .get('http://localhost:1337/posts', { - headers: { - Authorization: `Bearer ${token}`, +## Update a role +Description: The updateUsersPermissionsRole mutation updates an existing role: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#update-a-role) + +Language: GRAPHQL +File path: N/A + +```graphql +mutation { + updateUsersPermissionsRole(id: "1", data: { name: "Senior Editor", description: "Can edit and publish" }) { + ok + } +} +``` + + +## Delete a role +Description: The deleteUsersPermissionsRole mutation removes a role: +(Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api#delete-a-role) + +Language: GRAPHQL +File path: N/A + +```graphql +mutation { + deleteUsersPermissionsRole(id: "3") { + ok + } +} +``` + + + +# Users & Permissions REST API +Source: https://docs.strapi.io/cms/features/users-permissions/rest-api + +## Login +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#login) + +Language: JSON +File path: N/A + +```json +{ + "identifier": "user@example.com", + "password": "yourPassword" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/local \ + -H "Content-Type: application/json" \ + -d '{"identifier": "user@example.com", "password": "yourPassword"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 1, + "documentId": "x74detpqybxw0bn6ormua5g2", + "username": "testuser1", + "email": "user@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" + } +} +``` + + +## Register +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#register) + +Language: JSON +File path: N/A + +```json +{ + "username": "newuser", + "email": "newuser@example.com", + "password": "Password123!" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/local/register \ + -H "Content-Type: application/json" \ + -d '{"username": "newuser", "email": "newuser@example.com", "password": "Password123!"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 2, + "documentId": "xjpaytstw1gm7wdfoc6c2k13", + "username": "newuser", + "email": "newuser@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" + } +} +``` + + +## Forgot password +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#forgot-password) + +Language: JSON +File path: N/A + +```json +{ + "email": "user@example.com" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/forgot-password \ + -H "Content-Type: application/json" \ + -d '{"email": "user@example.com"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "ok": true +} +``` + + +## Reset password +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#reset-password) + +Language: JSON +File path: N/A + +```json +{ + "code": "resetTokenFromEmail", + "password": "NewPassword123!", + "passwordConfirmation": "NewPassword123!" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/reset-password \ + -H "Content-Type: application/json" \ + -d '{"code": "resetTokenFromEmail", "password": "NewPassword123!", "passwordConfirmation": "NewPassword123!"}' +``` + + +## Change password +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#change-password) + +Language: JSON +File path: N/A + +```json +{ + "currentPassword": "OldPassword123!", + "password": "NewPassword456!", + "passwordConfirmation": "NewPassword456!" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/change-password \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"currentPassword": "OldPassword123!", "password": "NewPassword456!", "passwordConfirmation": "NewPassword456!"}' +``` + + +## Email confirmation +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#email-confirmation) + +Language: Bash +File path: N/A + +```bash +curl -G http://localhost:1337/api/auth/email-confirmation \ + --data-urlencode "confirmation=confirmationTokenHere" +``` + + +## Send email confirmation +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#send-email-confirmation) + +Language: JSON +File path: N/A + +```json +{ + "email": "user@example.com" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/send-email-confirmation \ + -H "Content-Type: application/json" \ + -d '{"email": "user@example.com"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "email": "user@example.com", + "sent": true +} +``` + + +## Refresh token +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#refresh-token) + +Language: JSON +File path: N/A + +```json +{ + "refreshToken": "yourRefreshToken" +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/refresh \ + -H "Content-Type: application/json" \ + -d '{"refreshToken": "yourRefreshToken"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "jwt": "newAccessToken" +} +``` + + +## Logout +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#logout) + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/auth/logout \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Language: JSON +File path: N/A + +```json +{ + "ok": true +} +``` + + +## Get current user +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#get-current-user) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users/me \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Language: JSON +File path: N/A + +```json +{ + "id": 1, + "documentId": "x74detpqybxw0bn6ormua5g2", + "username": "testuser1", + "email": "user@example.com", + "provider": "local", + "confirmed": true, + "blocked": false, + "createdAt": "2024-03-15T10:00:00.000Z", + "updatedAt": "2024-03-15T10:00:00.000Z", + "publishedAt": "2024-03-15T10:00:00.000Z" +} +``` + + +## List users +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#list-users) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + + +## Get a user +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#get-a-user) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + + +## Count users +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#count-users) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users/count \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Language: JSON +File path: N/A + +```json +42 +``` + + +## Create a user +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#create-a-user) + +Language: JSON +File path: N/A + +```json +{ + "username": "newuser", + "email": "newuser@example.com", + "password": "Password123!", + "role": 1, + "confirmed": true +} +``` + +Language: Bash +File path: N/A + +```bash +curl -X POST http://localhost:1337/api/users \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"username": "newuser", "email": "newuser@example.com", "password": "Password123!", "role": 1, "confirmed": true}' +``` + + +## Update a user +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#update-a-user) + +Language: Bash +File path: N/A + +```bash +curl -X PUT http://localhost:1337/api/users/1 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"username": "updateduser"}' +``` + + +## Delete a user +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#delete-a-user) + +Language: Bash +File path: N/A + +```bash +curl -X DELETE http://localhost:1337/api/users/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + + +## List roles +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#list-roles) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users-permissions/roles \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Language: JSON +File path: N/A + +```json +{ + "roles": [ + { + "id": 1, + "name": "Authenticated", + "description": "Default role given to authenticated user.", + "type": "authenticated", + "nb_users": 2 }, - }) - .then(response => { - // Handle success. - console.log('Data: ', response.data); - }) - .catch(error => { - // Handle error. - console.log('An error occurred:', error.response); - }); + { + "id": 2, + "name": "Public", + "description": "Default role given to unauthenticated user.", + "type": "public", + "nb_users": 0 + } + ] +} ``` -## User registration -Description: Creating a new user in the database with a default role as 'authenticated' can be done as in the following example: -(Source: https://docs.strapi.io/cms/features/users-permissions#user-registration) +## Get a role +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#get-a-role) -Language: JavaScript +Language: Bash File path: N/A -```js -import axios from 'axios'; +```bash +curl http://localhost:1337/api/users-permissions/roles/1 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` -// 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); - }); + +## Create a role +Description: Request body: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#create-a-role) + +Language: JSON +File path: N/A + +```json +{ + "name": "Editor", + "description": "Can edit content", + "type": "editor" +} ``` +Language: Bash +File path: N/A -## User object in Strapi context -Description: The authenticated user object is a property of ctx.state. -(Source: https://docs.strapi.io/cms/features/users-permissions#user-object-in-strapi-context) +```bash +curl -X POST http://localhost:1337/api/users-permissions/roles \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"name": "Editor", "description": "Can edit content", "type": "editor"}' +``` -Language: JavaScript +Language: JSON File path: N/A -```js -create: async ctx => { - const { id } = ctx.state.user; +```json +{ + "ok": true +} +``` - const depositObj = { - ...ctx.request.body, - depositor: id, - }; - const data = await strapi.services.deposit.add(depositObj); +## Update a role +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#update-a-role) - // Send 201 `created` - ctx.created(data); -}; +Language: Bash +File path: N/A + +```bash +curl -X PUT http://localhost:1337/api/users-permissions/roles/1 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" \ + -d '{"description": "Updated description"}' +``` + +Language: JSON +File path: N/A + +```json +{ + "ok": true +} +``` + + +## Delete a role +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#delete-a-role) + +Language: Bash +File path: N/A + +```bash +curl -X DELETE http://localhost:1337/api/users-permissions/roles/3 \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" +``` + +Language: JSON +File path: N/A + +```json +{ + "ok": true +} +``` + + +## List permissions +Description: Example request: +(Source: https://docs.strapi.io/cms/features/users-permissions/rest-api#list-permissions) + +Language: Bash +File path: N/A + +```bash +curl http://localhost:1337/api/users-permissions/permissions \ + -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` @@ -27153,6 +27660,30 @@ File path: N/A +# The Users & Permissions plugin's register.allowedFields configuration option defaults to [] +Source: https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields + +## How it works in Strapi 5 +Description: To allow additional fields on registration, update your plugin configuration: +(Source: https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields#how-it-works-in-strapi-5) + +Language: JavaScript +File path: config/plugins.js + +```js +module.exports = { + 'users-permissions': { + config: { + register: { + allowedFields: ['firstName', 'lastName'], + }, + }, + }, +}; +``` + + + # Some env-only configuration options are handled by the server configuration Source: https://docs.strapi.io/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options diff --git a/docusaurus/static/llms-full.txt b/docusaurus/static/llms-full.txt index f2ce46c6ac..f16b70d2b1 100644 --- a/docusaurus/static/llms-full.txt +++ b/docusaurus/static/llms-full.txt @@ -9573,209 +9573,1005 @@ To access the admin panel using a specific provider instead of logging in with a -# Users & Permissions -Source: https://docs.strapi.io/cms/features/users-permissions +# Users & Permissions GraphQL API +Source: https://docs.strapi.io/cms/features/users-permissions/graphql-api -# Users & Permissions +# Users & Permissions GraphQL API -The Users & Permissions feature allows the management of the end-users of a Strapi project. It 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. +This page documents all GraphQL queries and mutations provided by the Users & Permissions plugin. The [GraphQL plugin](/cms/plugins/graphql) must be installed. For configuration details, see the main [Users & Permissions page](/cms/features/users-permissions). - +## Authentication -## Admin panel configuration +Authentication mutations handle login, registration, and password management. Public mutations do not require an Authorization header. -The Users & Permissions feature is configured from both the admin panel settings, and via the code base. +### Login -### Roles +The `login` mutation authenticates a user and returns a JWT token: -The Users & Permissions feature allows creating and managing roles for end users, to configure what they can have access to. +```graphql +mutation { + login(input: { identifier: "user@example.com", password: "yourPassword" }) { + jwt + user { + id + documentId + username + email + confirmed + blocked + } + } +} +``` -#### Creating a new role +Input type `UsersPermissionsLoginInput`: -**Path:** +- `identifier` (String!) -- email or username +- `password` (String!) +- `provider` (String, defaults to "local") -