Aller au contenu principal

POST /api/token/refresh

Obtient un nouveau token d'accès en utilisant le refresh token.

Endpoint

POST /api/token/refresh

Headers

HeaderValeurRequis
Content-Typeapplication/jsonOui

Corps de la requête

{
"refresh_token": "string"
}
ChampTypeRequisDescription
refresh_tokenstringOuiToken de rafraîchissement obtenu lors du login

Réponse succès

Code: 200 OK

{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3MDUzMTU5NDUsImV4cCI6MTcwNTMxOTU0NSwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJlbWFpbCI6ImFkbWluQHBjaC1zaWcuc24ifQ...",
"refresh_token": "e2f3a4b5c6d7e8f9g0h1i2j3k4l5m6n7o8p9q0r1"
}
ChampTypeDescription
tokenstringNouveau token JWT d'accès
refresh_tokenstringNouveau 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 :

  1. Chaque appel à /api/token/refresh génère un nouveau refresh token
  2. L'ancien refresh token est invalidé
  3. 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