POST /api/token/refresh
Obtem um novo token de acesso utilizando o refresh token.
Endpoint
POST /api/token/refresh
Headers
| Header | Valor | Obrigatorio |
|---|---|---|
| Content-Type | application/json | Sim |
Corpo da requisicao
{
"refresh_token": "string"
}
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
| refresh_token | string | Sim | Token de atualizacao obtido no login |
Resposta de sucesso
Codigo: 200 OK
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3MDUzMTU5NDUsImV4cCI6MTcwNTMxOTU0NSwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJlbWFpbCI6ImFkbWluQHBjaC1zaWcuc24ifQ...",
"refresh_token": "e2f3a4b5c6d7e8f9g0h1i2j3k4l5m6n7o8p9q0r1"
}
| Campo | Tipo | Descricao |
|---|---|---|
| token | string | Novo token JWT de acesso |
| refresh_token | string | Novo refresh token (rotacao) |
Respostas de erro
401 Unauthorized - Refresh token invalido
{
"code": 401,
"message": "Invalid refresh token"
}
401 Unauthorized - Refresh token expirado
{
"code": 401,
"message": "Refresh token has expired"
}
Exemplos
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 invalido, redirecionar para login
localStorage.removeItem('token');
localStorage.removeItem('refresh_token');
window.location.href = '/login';
throw new Error('Session expired');
}
const data = await response.json();
// Atualizar os tokens
localStorage.setItem('token', data.token);
localStorage.setItem('refresh_token', data.refresh_token);
return data.token;
};
JavaScript - Interceptor Axios
import axios from 'axios';
const api = axios.create({
baseURL: 'https://sig.ucp-pch.org/api'
});
// Interceptor para atualizar automaticamente o 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')
# Utilizacao
try:
tokens = refresh_token('d1f2a3b4c5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0')
print(f"Novo token: {tokens['token'][:50]}...")
except Exception as e:
print(f"Erro: {e}")
Rotacao dos tokens
O sistema utiliza a rotacao dos refresh tokens:
- Cada chamada a
/api/token/refreshgera um novo refresh token - O antigo refresh token e invalidado
- Isto limita o risco em caso de roubo do refresh token
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Cliente │ │ Backend │ │ Redis │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ refresh_token_A │ │
│──────────────────▶│ │
│ │ Verificar token_A │
│ │──────────────────▶│
│ │ OK │
│ │◀──────────────────│
│ │ Invalidar token_A │
│ │──────────────────▶│
│ │ Criar token_B │
│ │──────────────────▶│
│ token + token_B │ │
│◀──────────────────│ │
Boas praticas
Quando atualizar?
- Proativamente: Alguns minutos antes da expiracao do token
- Reativamente: Apos receber um erro 401
Calculo do momento de atualizacao
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();
// Atualizar 5 minutos antes da expiracao
return expiresAt - now < 5 * 60 * 1000;
} catch {
return false;
}
};
Notas
- O refresh token expira apos 7 dias
- Armazene o refresh token de forma segura (httpOnly cookie se possivel)
- Em caso de erro de atualizacao, redirecione o utilizador para a pagina de login