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 (
+
+
+
+
+
+ );
+};
+
+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