POST /api/token/refresh
Obtient un nouveau token d'accès en utilisant le refresh token.
Endpoint
POST /api/token/refresh
Headers
| Header | Valeur | Requis |
|---|---|---|
| Content-Type | application/json | Oui |
Corps de la requête
{
"refresh_token": "string"
}
| Champ | Type | Requis | Description |
|---|---|---|---|
| refresh_token | string | Oui | Token de rafraîchissement obtenu lors du login |
Réponse succès
Code: 200 OK
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3MDUzMTU5NDUsImV4cCI6MTcwNTMxOTU0NSwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJlbWFpbCI6ImFkbWluQHBjaC1zaWcuc24ifQ...",
"refresh_token": "e2f3a4b5c6d7e8f9g0h1i2j3k4l5m6n7o8p9q0r1"
}
| Champ | Type | Description |
|---|---|---|
| token | string | Nouveau token JWT d'accès |
| refresh_token | string | Nouveau refresh token (rotation) |
Réponses erreur
401 Unauthorized - Refresh token invalide
{
"code": 401,
"message": "Invalid refresh token"
}
401 Unauthorized - Refresh token expiré
{
"code": 401,
"message": "Refresh token has expired"
}
Exemples
cURL
curl -X POST https://sig.ucp-pch.org/api/token/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "d1f2a3b4c5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0"
}'
JavaScript
const refreshAccessToken = async () => {
const refreshToken = localStorage.getItem('refresh_token');
if (!refreshToken) {
throw new Error('No refresh token available');
}
const response = await fetch('https://sig.ucp-pch.org/api/token/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh_token: refreshToken
})
});
if (!response.ok) {
// Refresh token invalide, rediriger vers login
localStorage.removeItem('token');
localStorage.removeItem('refresh_token');
window.location.href = '/login';
throw new Error('Session expired');
}
const data = await response.json();
// Mettre à jour les tokens
localStorage.setItem('token', data.token);
localStorage.setItem('refresh_token', data.refresh_token);
return data.token;
};
JavaScript - Intercepteur Axios
import axios from 'axios';
const api = axios.create({
baseURL: 'https://sig.ucp-pch.org/api'
});
// Intercepteur pour rafraîchir automatiquement le token
api.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const newToken = await refreshAccessToken();
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
return api(originalRequest);
} catch (refreshError) {
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
Python
import requests
def refresh_token(current_refresh_token):
response = requests.post(
'https://sig.ucp-pch.org/api/token/refresh',
json={
'refresh_token': current_refresh_token
}
)
if response.status_code == 200:
data = response.json()
return {
'token': data['token'],
'refresh_token': data['refresh_token']
}
else:
raise Exception('Failed to refresh token')
# Utilisation
try:
tokens = refresh_token('d1f2a3b4c5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0')
print(f"Nouveau token: {tokens['token'][:50]}...")
except Exception as e:
print(f"Erreur: {e}")
Rotation des tokens
Le système utilise la rotation des refresh tokens :
- Chaque appel à
/api/token/refreshgénère un nouveau refresh token - L'ancien refresh token est invalidé
- Cela limite le risque en cas de vol du refresh token
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ │ Backend │ │ Redis │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ refresh_token_A │ │
│──────────────────▶│ │
│ │ Vérifier token_A │
│ │──────────────────▶│
│ │ OK │
│ │◀──────────────────│
│ │ Invalider token_A │
│ │──────────────────▶│
│ │ Créer token_B │
│ │──────────────────▶│
│ token + token_B │ │
│◀──────────────────│ │
Bonnes pratiques
Quand rafraîchir ?
- Proactivement : Quelques minutes avant l'expiration du token
- Réactivement : Après avoir reçu une erreur 401
Calcul du moment de rafraîchissement
const shouldRefreshToken = () => {
const token = localStorage.getItem('token');
if (!token) return false;
try {
const payload = JSON.parse(atob(token.split('.')[1]));
const expiresAt = payload.exp * 1000;
const now = Date.now();
// Rafraîchir 5 minutes avant expiration
return expiresAt - now < 5 * 60 * 1000;
} catch {
return false;
}
};
Notes
- Le refresh token expire après 7 jours
- Stockez le refresh token de manière sécurisée (httpOnly cookie si possible)
- En cas d'erreur de rafraîchissement, redirigez l'utilisateur vers la page de login