curl -X POST "https://api.chronos.app/auth/refresh" \
-H "Accept: application/json" \
-b "__Host-refresh=eyJhbG..."
{
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "[email protected]",
"name": "Jane Doe",
"avatar_url": "https://lh3.googleusercontent.com/a/...",
"created_at": "2026-03-04T10:30:00.000Z"
},
"expires_at": 1709556600
}
Refreshes an expired session using the refresh token cookie, returning a new access token and updated user data.
curl -X POST "https://api.chronos.app/auth/refresh" \
-H "Accept: application/json" \
-b "__Host-refresh=eyJhbG..."
{
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "[email protected]",
"name": "Jane Doe",
"avatar_url": "https://lh3.googleusercontent.com/a/...",
"created_at": "2026-03-04T10:30:00.000Z"
},
"expires_at": 1709556600
}
curl -X POST "https://api.chronos.app/auth/refresh" \
-H "Accept: application/json" \
-b "__Host-refresh=eyJhbG..."
{
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "[email protected]",
"name": "Jane Doe",
"avatar_url": "https://lh3.googleusercontent.com/a/...",
"created_at": "2026-03-04T10:30:00.000Z"
},
"expires_at": 1709556600
}
RATE_LIMIT_AUTH configuration. The rate limiter uses the client’s IP address as the key.
revoked_tokens tablerefresh)// Check if session is expiring soon (e.g., within 5 minutes)
function shouldRefreshSession(expiresAt) {
const now = Math.floor(Date.now() / 1000);
const fiveMinutes = 5 * 60;
return expiresAt - now < fiveMinutes;
}
// Refresh session before it expires
async function ensureValidSession(expiresAt) {
if (shouldRefreshSession(expiresAt)) {
const response = await fetch('/auth/refresh', {
method: 'POST',
credentials: 'include'
});
if (response.ok) {
const data = await response.json();
return data.expires_at;
}
}
return expiresAt;
}
expires_at before making API requests. Refresh the session proactively when it’s within 5 minutes of expiring to ensure uninterrupted access.backend/app/routers/auth.py:220-263