diff --git a/docusaurus/docs/cms/api/rest.md b/docusaurus/docs/cms/api/rest.md index fc09e4f419..af0941e238 100644 --- a/docusaurus/docs/cms/api/rest.md +++ b/docusaurus/docs/cms/api/rest.md @@ -16,7 +16,7 @@ tags: The REST API allows accessing the [content-types](/cms/backend-customization/models) through API endpoints. Strapi automatically creates [API endpoints](#endpoints) when a content-type is created. [API parameters](/cms/api/rest/parameters) can be used when querying API endpoints to refine the results. -This section of the documentation is for the REST API reference. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases. +This section of the documentation is for the REST API reference for content-types. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases. :::prerequisites All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions. See the [Quick Start Guide](/cms/quick-start#step-4-set-roles--permissions), the user guide for the [Users & Permissions feature](/cms/features/users-permissions#roles), and [API tokens configuration documentation](/cms/features/api-tokens) for more details. diff --git a/docusaurus/docs/cms/backend-customization/examples/authentication.md b/docusaurus/docs/cms/backend-customization/examples/authentication.md index baf1bfc7b4..a7b38c5d60 100644 --- a/docusaurus/docs/cms/backend-customization/examples/authentication.md +++ b/docusaurus/docs/cms/backend-customization/examples/authentication.md @@ -145,6 +145,120 @@ const Login = () => { export default Login; ``` +## Enhanced Authentication with Session Management + +The above example uses the traditional JWT approach. For enhanced security, you can enable session management mode in your Users & Permissions configuration, which provides shorter-lived access tokens and refresh token functionality. + +### Configuration + +First, enable session management in your `/config/plugins.js`: + +```js title="/config/plugins.js" +module.exports = ({ env }) => ({ + 'users-permissions': { + config: { + jwtManagement: 'refresh', + sessions: { + accessTokenLifespan: 604800, // 1 week (default) + maxRefreshTokenLifespan: 2592000, // 30 days + idleRefreshTokenLifespan: 604800, // 7 days + }, + }, + }, +}); +``` + +### Enhanced Login Component + +Here's an updated login component that handles both JWT and refresh tokens: + +```jsx title="/client/pages/auth/enhanced-login.js" +import React, { useState } from 'react'; +import { useFormik } from 'formik'; +import { Button, Input } from '@nextui-org/react'; +import Layout from '@/components/layout'; +import { getStrapiURL } from '@/utils'; + +const EnhancedLogin = () => { + const [isLoading, setIsLoading] = useState(false); + + const { handleSubmit, handleChange } = useFormik({ + initialValues: { + identifier: '', + password: '', + }, + onSubmit: async (values) => { + setIsLoading(true); + try { + const res = await fetch(getStrapiURL('/auth/local'), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(values), + }); + + const data = await res.json(); + + if (res.ok) { + // Store both tokens (session management mode) + if (data.refreshToken) { + localStorage.setItem('accessToken', data.jwt); + localStorage.setItem('refreshToken', data.refreshToken); + } else { + // Legacy mode - single JWT + localStorage.setItem('token', data.jwt); + } + + // Redirect to protected area + window.location.href = '/dashboard'; + } else { + console.error('Login failed:', data.error); + } + } catch (error) { + console.error('Login error:', error); + } finally { + setIsLoading(false); + } + }, + }); + + return ( + +
+
+

Enhanced Login

+ + + +
+
+
+ ); +}; + +export default EnhancedLogin; +``` +``` +
:::strapi What's next? diff --git a/docusaurus/docs/cms/configurations/admin-panel.md b/docusaurus/docs/cms/configurations/admin-panel.md index cd2b5ab324..04d6eaafb9 100644 --- a/docusaurus/docs/cms/configurations/admin-panel.md +++ b/docusaurus/docs/cms/configurations/admin-panel.md @@ -2,7 +2,7 @@ title: Admin panel configuration sidebar_label: Admin panel displayed_sidebar: cmsSidebar -toc_max_heading_level: 2 +toc_max_heading_level: 3 description: Strapi's admin panel offers a single entry point file for its configuration. tags: - admin panel @@ -57,7 +57,7 @@ export default { ::: -## Admin panel server +## Admin panel server By default, Strapi's admin panel is exposed via `http://localhost:1337/admin`. For security reasons, the host, port, and path can be updated. @@ -204,7 +204,11 @@ For Strapi Cloud customers, the `auditLogs.retentionDays` value stored in the li ## Authentication -The authentication system, including [SSO configuration](/cms/configurations/guides/configure-sso), can be configured with the following parameters: +The authentication system, including [SSO configuration](/cms/configurations/guides/configure-sso) and [session management](#session-management), can be configured with the following parameters: + +### Basic authentication + +To configure basic authentication, use the following parameters: | Parameter | Description | Type | Default | |-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------| @@ -218,6 +222,43 @@ The authentication system, including [SSO configuration](/cms/configurations/gui | `auth.events.onConnectionSuccess` | Function called when an admin user log in successfully to the administration panel | function | `undefined` | | `auth.events.onConnectionError` | Function called when an admin user fails to log in to the administration panel | function | `undefined` | +Additional configuration parameters are available for [session management](#session-management). + +### Session management + +Admin authentication uses session management by default for enhanced security. + +Session management provides enhanced security for authentication in Strapi applications by using short-lived access tokens paired with longer-lived refresh tokens. This approach reduces the risk of token theft and allows for more granular control over user sessions. + +Strapi's session management system supports both admin panel authentication and Content API authentication through the [Users & Permissions feature](/cms/features/users-permissions). The system provides: + +- Short-lived access tokens (typically 30 minutes) for API requests +- Refresh tokens for obtaining new access tokens +- Device-specific sessions for targeted logout +- Configurable token lifespans for different security requirements + +To configure session lifespans and behavior, use the following parameters: + +| Parameter | Description | Type | Default | +|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------| +| `auth.sessions` | Session management configuration | object | `{}` | +| `auth.sessions.accessTokenLifespan` | Access token lifespan in seconds | number | `1800` (30 minutes) | +| `auth.sessions.maxRefreshTokenLifespan` | Maximum refresh token lifespan in seconds | number | `2592000` (30 days, or legacy `expiresIn` value) | +| `auth.sessions.idleRefreshTokenLifespan` | Idle refresh token timeout in seconds | number | `604800` (7 days) | +| `auth.sessions.maxSessionLifespan` | Maximum session duration in seconds | number | `2592000` (30 days, or legacy `expiresIn` value) | +| `auth.sessions.idleSessionLifespan` | Session idle timeout in seconds | number | `3600` (1 hour) | + +### Cookie configuration + +To configure HTTP cookies for admin authentication, use the following parameters: + +| Parameter | Description | Type | Default | +|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------| +| `auth.cookie` | Cookie configuration for admin authentication | object | `{}` | +| `auth.cookie.domain` | Cookie domain (inherits from server if not set) | string | `undefined` | +| `auth.cookie.path` | Cookie path | string | `'/admin'` | +| `auth.cookie.sameSite` | | string | `'lax'` | + ## Feature flags The feature flags can be configured with the following parameters: @@ -365,6 +406,18 @@ module.exports = ({ env }) => ({ expiresIn: '7d', }, secret: env('ADMIN_JWT_SECRET', 'someSecretKey'), + sessions: { + accessTokenLifespan: 1800, // 30 minutes + maxRefreshTokenLifespan: 2592000, // 30 days + idleRefreshTokenLifespan: 604800, // 7 days + maxSessionLifespan: 604800, // 7 days + idleSessionLifespan: 3600, // 1 hour + }, + cookie: { + domain: env('ADMIN_COOKIE_DOMAIN'), + path: '/admin', + sameSite: 'lax', + }, }, url: env('PUBLIC_ADMIN_URL', '/dashboard'), autoOpen: false, @@ -423,6 +476,18 @@ export default ({ env }) => ({ expiresIn: '7d', }, secret: env('ADMIN_JWT_SECRET', 'someSecretKey'), + sessions: { + accessTokenLifespan: 1800, // 30 minutes + maxRefreshTokenLifespan: 2592000, // 30 days + idleRefreshTokenLifespan: 604800, // 7 days + maxSessionLifespan: 604800, // 7 days + idleSessionLifespan: 3600, // 1 hour + }, + cookie: { + domain: env('ADMIN_COOKIE_DOMAIN'), + path: '/admin', + sameSite: 'lax', + }, }, url: env('PUBLIC_ADMIN_URL', '/dashboard'), autoOpen: false, diff --git a/docusaurus/docs/cms/configurations/environment.md b/docusaurus/docs/cms/configurations/environment.md index 3b9ba70794..c83ba0acb1 100644 --- a/docusaurus/docs/cms/configurations/environment.md +++ b/docusaurus/docs/cms/configurations/environment.md @@ -56,6 +56,30 @@ Prefixing an environment variable name with `STRAPI_ADMIN_` exposes the variable +Set these environment variables for secure authentication with [sessions management](/cms/features/users-permissions#jwt-management-modes) configuration: + +```bash title=".env" +# Admin authentication +ADMIN_JWT_SECRET=your-admin-secret-key + +# Cookie domain (optional) +ADMIN_COOKIE_DOMAIN=yourdomain.com + +# Users & Permissions JWT secret +JWT_SECRET=your-content-api-secret-key + +# Users & Permissions session management +UP_JWT_MANAGEMENT=refresh # or 'legacy-support' +UP_SESSIONS_ACCESS_TTL=604800 # 1 week in seconds +UP_SESSIONS_MAX_REFRESH_TTL=2592000 # 30 days in seconds +UP_SESSIONS_IDLE_REFRESH_TTL=604800 # 7 days in seconds +UP_SESSIONS_HTTPONLY=false # true for HTTP-only cookies +UP_SESSIONS_COOKIE_NAME=strapi_up_refresh +UP_SESSIONS_COOKIE_SAMESITE=lax +UP_SESSIONS_COOKIE_PATH=/ +UP_SESSIONS_COOKIE_SECURE=false # true in production +``` + ## Environment configurations Configurations can be created with the following naming and structure conventions: `./config/env/{environment}/{filename}`. This is useful when you need specific static configurations for specific environments and using environment variables is not the best solution. diff --git a/docusaurus/docs/cms/features/users-permissions.md b/docusaurus/docs/cms/features/users-permissions.md index 46ab2b3ee9..21bdb14351 100644 --- a/docusaurus/docs/cms/features/users-permissions.md +++ b/docusaurus/docs/cms/features/users-permissions.md @@ -196,15 +196,47 @@ While most of the Users & Permissions settings are handled via the admin panel, ### JWT configuration -You can configure the JWT generation by using the [plugins configuration file](/cms/configurations/plugins). +You can configure the JSON Web Token (JWT) generation by using the [plugins configuration file](/cms/configurations/plugins). Strapi uses to generate the JWT. -Available options: +#### JWT management modes -- `jwtSecret`: random string used to create new JWTs, typically set using the `JWT_SECRET` [environment variable](/cms/configurations/environment#strapi). -- `jwt.expiresIn`: expressed in seconds or a string describing a time span.
+The Users & Permissions feature supports 2 JWT management modes. + +Defining which mode is used is done by setting the `jwtManagement` property of the `users-permissions.config` object in the [`/config/plugins` file](/cms/configurations/plugins). The property accepts either `legacy-support` or `refresh`: + +| Mode | Description | Use case | +|------|-------------|----------| +| `legacy-support` | (default) Issues long-lived JWTs using traditional configuration | Existing applications, simple authentication | +| `refresh` | Uses session management with short-lived access tokens and refresh tokens for enhanced security | New applications, enhanced security requirements
(additional information can be found in [admin panel configuration](/cms/configurations/admin-panel#session-management) documentation) | + +For backwards compatibility, the Users & Permission feature defaults to legacy mode: + +```js title="/config/plugins.js" +module.exports = ({ env }) => ({ + 'users-permissions': { + config: { + jwtManagement: 'legacy-support', + jwt: { + expiresIn: '7d', // Traditional JWT expiry + }, + }, + }, +}); +``` + +:::note Notes +- `jwtSecret` is a random string used to create new JWTs, typically set using the `JWT_SECRET` [environment variable](/cms/configurations/environment#strapi). +- `jwt.expiresIn` is (legacy-mode only) is 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 use a string be sure you provide the time units (minutes, hours, days, years, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms"). +::: + +:::warning +Setting JWT expiry for more than 30 days is not recommended due to security concerns. +::: + +When the `refresh` mode is used, the configuration file could look like as follows: @@ -213,11 +245,21 @@ Available options: ```js title="/config/plugins.js" module.exports = ({ env }) => ({ - // ... + // … 'users-permissions': { config: { - jwt: { - expiresIn: '7d', + jwtManagement: 'refresh', + sessions: { + accessTokenLifespan: 604800, // 1 week (default) + maxRefreshTokenLifespan: 2592000, // 30 days + idleRefreshTokenLifespan: 604800, // 7 days + httpOnly: false, // Set to true for HTTP-only cookies + cookie: { + name: 'strapi_up_refresh', + sameSite: 'lax', + path: '/', + secure: false, // true in production + }, }, }, }, @@ -232,11 +274,21 @@ module.exports = ({ env }) => ({ ```ts title="/config/plugins.ts" export default ({ env }) => ({ - // ... + // … 'users-permissions': { config: { - jwt: { - expiresIn: '7d', + jwtManagement: 'refresh', + sessions: { + accessTokenLifespan: 604800, // 1 week (default) + maxRefreshTokenLifespan: 2592000, // 30 days + idleRefreshTokenLifespan: 604800, // 7 days + httpOnly: false, // Set to true for HTTP-only cookies + cookie: { + name: 'strapi_up_refresh', + sameSite: 'lax', + path: '/', + secure: false, // true in production + }, }, }, }, @@ -248,10 +300,6 @@ export default ({ env }) => ({ -:::warning -Setting JWT expiry for more than 30 days is not recommended due to security concerns. -::: - ### Registration configuration If you have added any additional fields in your User **model** Models, also called content-types in Strapi, define a representation of the content structure.
Users are a special type of built-in content-type found in any new Strapi application. You can customize the Users model, adding more fields for instance, like any other models.
For more information, please refer to the [models](/cms/backend-customization/models) documentation.
that need to be accepted on registration, you need to added them to the list of allowed fields in the `config.register` object of [the `/config/plugins` file](/cms/configurations/plugins), otherwise they will not be accepted. @@ -448,15 +496,72 @@ 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. ::: +#### Basic 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 | + +#### 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 you could for instance 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" +``` + + + + #### Identifier -The `identifier` param can be an email or username, as in the following examples: +The `identifier` parameter sent with requests can be an email or username, as in the following examples: @@ -496,8 +601,9 @@ If you use **Postman**, set the **body** to **raw** and select **JSON** as your } ``` -If the request is successful you will receive the **user's JWT** in the `jwt` key: +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", @@ -509,6 +615,19 @@ If the request is successful you will receive the **user's JWT** in the `jwt` ke } ``` +**Session management mode response:** +```json +{ + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Short-lived access token + "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Long-lived refresh token + "user": { + "id": 1, + "username": "user", + ... + } +} +``` + diff --git a/docusaurus/static/llms-full.txt b/docusaurus/static/llms-full.txt index a59c4d7ef8..70d636406e 100644 --- a/docusaurus/static/llms-full.txt +++ b/docusaurus/static/llms-full.txt @@ -3709,7 +3709,7 @@ Source: https://docs.strapi.io/cms/api/rest The REST API allows accessing the [content-types](/cms/backend-customization/models) through API endpoints. Strapi automatically creates [API endpoints](#endpoints) when a content-type is created. [API parameters](/cms/api/rest/parameters) can be used when querying API endpoints to refine the results. -This section of the documentation is for the REST API reference. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases. +This section of the documentation is for the REST API reference for content-types. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases. :::prerequisites All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions. See the [Quick Start Guide](/cms/quick-start#step-4-set-roles--permissions), the user guide for the [Users & Permissions feature](/cms/features/users-permissions#roles), and [API tokens configuration documentation](/cms/features/api-tokens) for more details. @@ -8835,10 +8835,6 @@ Click the search button -:::warning -Setting JWT expiry for more than 30 days is not recommended due to security concerns. -::: - ### Registration configuration If you have added any additional fields in your User **model** that need to be accepted on registration, you need to added them to the list of allowed fields in the `config.register` object of [the `/config/plugins` file](/cms/configurations/plugins), otherwise they will not be accepted. @@ -8867,6 +8863,16 @@ By default you can set a `JWT_SECRET` environment variable and it will be used a By default, Strapi SSO only redirects to the redirect URL that is exactly equal to the url in the configuration: + + +To log out of all sessions, send the following request: + + + +#### Identifier + +The `identifier` parameter sent with requests can be an email or username, as in the following examples: + #### Token usage