Skip to main content

A worked example

Mei is a talent who uses JodApp Web on her laptop. The ids below are made up.

Mei on the web, from login to an expired session​

  1. Monday 09:00. Mei opens the login page, types her email and password, and clicks "Sign in".
    • The page's clientAction sends POST /identities/user_sessions with a JSON body.
    • Rails counts one attempt from her IP address, finds her account, and checks the password.
    • Rails creates Identities::UserSession 4021: owner Mei, a new uuid, csrf_token: "k7…", her IP address and browser, created_at and updated_at both 09:00.
    • The response sets jodapp_session_id to the signed 4021 and CSRF_TOKEN to k7…, both expiring in 30 days, and returns the current-session JSON.
  2. The router loads the page she was heading to.
    • The JodApp Web server sends GET /identities/user_sessions/current with her cookie forwarded.
    • Rails checks the signature, finds Identities::UserSession 4021, sees it is not expired, and returns the JSON. The page shows her name.
    • updated_at is seconds old, so Rails does not touch it.
  3. 09:20. Mei saves a change to her profile.
    • The browser sends PATCH /identities/users/current with both cookies and X-CSRF-Token: k7…, added by the API client.
    • Rails finds Identities::UserSession 4021, compares the header with csrf_token, and they match.
    • updated_at is 20 minutes old, so Rails sets it to 09:20. This is the only write the session causes all morning.
  4. 09:25. Mei opens another page.
    • Identities::UserSession 4021 is found again. updated_at is 5 minutes old, so nothing is written.
  5. Tuesday. Mei opens Jod once.
    • Identities::UserSession 4021 is found. updated_at moves to Tuesday. It is 1 day old, well inside both limits.
  6. Mei goes on holiday and does not open Jod for 10 days.
    • On day 8 after Tuesday, updated_at passes the 7-day idle limit.
    • The next hourly run of Identities::DeleteExpiredUserSessionsJob deletes Identities::UserSession 4021.
    • Had the job not run, the lookup would refuse it anyway, because not_expired excludes it.
  7. Mei comes back and opens Jod.
    • Her browser still has the cookie, because its Expires is 30 days after login.
    • The JodApp Web server forwards it. Rails finds no Identities::UserSession 4021 and answers 401.
    • JodApp Web sends Mei to the login page. She signs in, gets Identities::UserSession 4788 and two fresh cookies, and carries on.

If Mei had used Jod every day instead, the absolute limit would have ended Identities::UserSession 4021 on day 30, and she would have signed in once then.

Mei on the mobile app, when it exists​

  1. Mei signs in on the app.
    • The app sends POST /identities/user_sessions with "credential": "token" in the JSON body.
    • Rails creates Identities::UserSession 4790 with token_digest set to the SHA-256 of a new random token, and no csrf_token.
    • The response carries the raw token once. The app stores it in the device's secure store. Rails never shows it again.
  2. Every later request from the app carries Authorization: Bearer <token>.
    • Rails hashes the token, finds Identities::UserSession 4790 by token_digest, and applies the same limits and the same touch as on the web.
    • No CSRF check runs, because no cookie was sent.
  3. Mei taps "sign out of all devices" on the app.
    • The app sends DELETE /identities/user_sessions with the bearer header.
    • Rails destroys every Identities::UserSession of Mei's: 4788 from the laptop and 4790 from the phone. It answers 204. The app deletes its token.
    • The laptop's next request finds no Identities::UserSession, gets 401, and lands on the login page.