06.A

Auth · TOTP + JWT

Password → TOTP → tokens issued → silent refresh on 401. The user never sees a re-login.
$auth.demo --start --mfa=totp
>8 stages · play to walk through
step 1 / 8
Client
browser · axios
local state
access_tokenttl 15m
refresh_tokenttl 7d (httpOnly cookie)
totp · 349 360
Auth Service
lambda · /login /verify-totp /refresh
wire log · lane bus
→ POST /login
User Store
dynamodb · users · refresh_jti
users#jun.cao
pw_hash: argon2$...
totp_secret: ●●●●●●●●●●
refresh_jti: —
// the trick: silent refresh interceptor
client · axios.ts
// axios silent refresh interceptor
api.interceptors.response.use(
  r => r,
  async (err) => {
    const cfg = err.config;
    if (err.response?.status === 401 && !cfg._retry) {
      cfg._retry = true;
      await api.post('/refresh');     // httpOnly cookie sent
      return api(cfg);                // retry original request
    }
    throw err;
  }
);

The access token is short-lived (15 min) and held in JS memory; the refresh token lives 7 days in an httpOnly cookie so it can't be read by JS — only the browser sends it back to /refresh.

When a request returns 401, the axios interceptor catches it, calls /refresh (the cookie rides along automatically), and retries the original call. The user never sees a re-login.

Each refresh rotates the refresh token'sjti on the server — replay attacks invalidate the chain immediately.

auth --totp --jwt