feat: give client_credentials tokens a one-hour lifetime

This commit is contained in:
2026-09-22 16:56:06 +02:00
parent ab7d00b35d
commit 79709e3a3e
3 changed files with 9 additions and 3 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ league_oauth2_server:
private_key_passphrase: null private_key_passphrase: null
encryption_key: '%env(resolve:OAUTH_ENCRYPTION_KEY)%' encryption_key: '%env(resolve:OAUTH_ENCRYPTION_KEY)%'
require_code_challenge_for_public_clients: true require_code_challenge_for_public_clients: true
enable_client_credentials_grant: true enable_client_credentials_grant: false
enable_auth_code_grant: true enable_auth_code_grant: true
enable_refresh_token_grant: true enable_refresh_token_grant: true
enable_password_grant: false enable_password_grant: false
+5
View File
@@ -382,3 +382,8 @@ services:
whitelisted_ips: '%env(csv:MAINTENANCE_MODE_IP_WHITELIST)%' whitelisted_ips: '%env(csv:MAINTENANCE_MODE_IP_WHITELIST)%'
whitelisted_routes: '%env(csv:MAINTENANCE_MODE_ROUTE_WHITELIST)%' whitelisted_routes: '%env(csv:MAINTENANCE_MODE_ROUTE_WHITELIST)%'
whitelisted_paths: '%env(csv:MAINTENANCE_MODE_PATH_WHITELIST)%' whitelisted_paths: '%env(csv:MAINTENANCE_MODE_PATH_WHITELIST)%'
league.oauth2_server.grant.client_credentials:
class: League\OAuth2\Server\Grant\ClientCredentialsGrant
tags:
- { name: league.oauth2_server.authorization_server.grant, accessTokenTTL: 'PT1H' }
+3 -2
View File
@@ -10,7 +10,8 @@ A Symfony application exposing a read-mostly JSON API under the `/api` prefix. A
- Token endpoint: `POST /token` (unauthenticated). - Token endpoint: `POST /token` (unauthenticated).
- Enabled grants: **client_credentials**, **authorization_code** (PKCE required for public clients), **refresh_token**. Password and implicit grants are disabled. - Enabled grants: **client_credentials**, **authorization_code** (PKCE required for public clients), **refresh_token**. Password and implicit grants are disabled.
- Access token TTL: **10 minutes** clients must refresh/re-request frequently. - Access token TTL depends on the grant: **1 hour** for client_credentials, **10 minutes** for authorization_code.
Do not hardcode either value — read `expires_in` from the token response, it is authoritative and may be tuned.
- Available scopes: `email`, `id`, `profile`, `roles`, `api`. Default scope if none requested: `email`. - Available scopes: `email`, `id`, `profile`, `roles`, `api`. Default scope if none requested: `email`.
- Each granted scope maps to a role `ROLE_OAUTH2_<SCOPE_UPPERCASE>` (e.g. scope `api``ROLE_OAUTH2_API`). - Each granted scope maps to a role `ROLE_OAUTH2_<SCOPE_UPPERCASE>` (e.g. scope `api``ROLE_OAUTH2_API`).
- Send the token as `Authorization: Bearer <access_token>`. - Send the token as `Authorization: Bearer <access_token>`.
@@ -427,7 +428,7 @@ CRM selection attributes/segments for the authenticated user. `400 {"message": "
## Client implementation notes ## Client implementation notes
1. **Token lifetime is 10 minutes** — implement refresh/re-fetch with a safety margin and retry once on 401. 1. **Token lifetime comes from `expires_in`** (currently 1 hour for client_credentials, 10 minutes for authorization_code) — cache the token for that long, refresh with a safety margin, and retry once on 401.
2. **Check for an `error` key even on 200 responses** for `/api/products` and the travel availability endpoint. 2. **Check for an `error` key even on 200 responses** for `/api/products` and the travel availability endpoint.
3. **Money units are inconsistent across endpoints**: contingent endpoints return decimal major units; accommodation-booking fields return integer cents. Normalize at the client boundary. 3. **Money units are inconsistent across endpoints**: contingent endpoints return decimal major units; accommodation-booking fields return integer cents. Normalize at the client boundary.
4. **Dates**: `Y-m-d` everywhere except `acceptedAt` (ISO-8601 datetime) and pickup planning (`Y-m-d H:i`). Contingent `dateFrom`/`dateTo` are inclusive night boundaries. 4. **Dates**: `Y-m-d` everywhere except `acceptedAt` (ISO-8601 datetime) and pickup planning (`Y-m-d H:i`). Contingent `dateFrom`/`dateTo` are inclusive night boundaries.