Refresh tokens and rotation

The 15-minute problem

You made the access token expire in 15 minutes β€” great for security, annoying for users, who'd have to log in every quarter hour. The fix is a second token: a long-lived refresh token (days or weeks) whose only job is to mint fresh access tokens. The access token is used constantly and dies fast; the refresh token is used rarely β€” only when the access token expires β€” and is guarded far more carefully.

The flow: login returns both. The client uses the access token until it expires, then sends the refresh token to POST /auth/refresh and gets a new access token back. The user never sees a login screen for weeks.