Table of Contents
Refresh Tokens
It sounds like you have a Session Cookie issue. Even if your JWT token is valid for 30 days inside the cookie, the browser (or mobile webview) will delete that cookie the moment the "session" ends unless you explicitly tell it to save it to the hard drive. Here is why you're getting logged out and how the "big players" like Amazon stay logged in.
- The "Persistent" vs. "Session" Cookie When you set a cookie without an explicit Expires or Max-Age attribute, it is treated as a Session Cookie. These live only in the browser's RAM. When you restart your phone or force-close the app, that RAM is cleared, and the cookie vanishes—even if the JWT inside it was meant to last a month. The Fix: You must set a Max-Age on the cookie itself when you send it from your server.
Server-side Example (Node/Express): res.cookie('token', jwtToken, { httpOnly: true, secure: true, maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days in milliseconds sameSite: 'lax' });
- How Amazon Does It (Refresh Tokens) Amazon doesn’t just use one long-lived cookie. That would be a security risk (if someone steals that 30-day cookie, they have total access). Instead, they use a Rotating Token Pattern.
- Access Token (Short-lived): A JWT that lasts ~15 minutes. It’s used for every API call.
- Refresh Token (Long-lived): A random string stored in a Persistent Cookie (with Max-Age).
- The Flow: When you open the app after a restart, the short-lived JWT is gone. The app sees this, sends the Refresh Token to the server, and the server says "I recognize this device/session" and sends back a brand new 15-minute JWT.
- Check your "Secure" settings On mobile devices (iOS/Android), browsers are extremely strict. If you are developing locally or over HTTP:
- If you set Secure: true, the cookie will not save unless you are on https://.
- If you don't set SameSite: 'Lax' or 'Strict', some mobile browsers will reject the cookie entirely upon restart.
Summary Checklist for 30-Day Login:
Component Requirement Cookie Attribute Must include Max-Age or Expires. Storage Type Ensure it's not sessionStorage (which wipes on close). Protocol Must use HTTPS for Secure cookies to persist on mobile. Strategy Use a Refresh Token in a persistent cookie and a JWT in memory. Would you like me to help you write the logic for a Refresh Token system so your app is more secure than using a single 30-day JWT?
Login
The problem: Right now anyone can hammer POST /auth/login or POST /auth/refresh with unlimited requests — brute-forcing passwords or tokens.
What it would look like:
The fix: Use flask-limiter to add per-IP rate limits:
Why it's deferred: Requires deciding on limits, storage backend for counters (in-memory vs Redis), and how to handle legitimate users behind NAT/shared IPs.