Kembo
BlogDocsSign in
Kembo

Mobile auth in minutes. Google and Apple sign-in for Expo, Flutter, Capacitor, and Web.

Product

  • Documentation
  • Blog
  • Pricing
  • Get started

Legal

  • Privacy Policy
  • Terms of Service
  • DPA
  • Data Deletion

© 2026 Kembo

Operated by ByteStronauts

← All posts
July 18, 2026·9 min read

Session management for mobile apps: JWTs, refresh tokens, and secure storage

Sign-in is the easy part. Keeping a mobile user logged in safely — short-lived access tokens, rotating refresh tokens, and storage that survives an offline week without leaking — is where real apps get it wrong. Here is how mobile sessions actually work.

session managementJWTrefresh tokensmobile securitymobile authsecure storage

Getting a user signed in feels like the finish line. It is actually the starting line. The harder, longer-lived problem is keeping them signed in — for weeks, across app restarts and flaky networks — without leaving a token lying around that a leaked backup or a jailbroken device could hand to an attacker. This is session management, and it is where a lot of otherwise-solid mobile apps quietly cut corners.

This post lays out how mobile sessions actually work: what an access token is for, why refresh tokens exist, how to store both safely on iOS and Android, and the failure modes that produce the dreaded "logged out for no reason" reviews.

Two tokens, two jobs

Modern auth splits the session into two credentials with very different lifetimes.

  • Access token — usually a JWT, short-lived (minutes to an hour). Sent with every API request to prove who you are. Because it is short-lived, a stolen access token is only useful briefly.
  • Refresh token — long-lived (days to months). Its only job is to obtain new access tokens when they expire. It is never sent to your regular API endpoints, only to the token endpoint.

The whole point of the split: you get the convenience of staying logged in for weeks (refresh token) without the risk of a long-lived credential riding along on every single request (access token).

Why a JWT, and why you still verify it

A JWT is a signed bundle of claims — user id, expiry, issuer — that your backend can verify without a database lookup, because the signature proves it was not tampered with. That makes per-request auth fast. Two things people get wrong:

  • A JWT is readable, not secret. Anyone can base64-decode it and see the claims. Never put anything sensitive in the payload.
  • You must actually verify the signature and expiry on every request — and check the algorithm. Accepting an unverified or alg: none token is a classic, fatal mistake.

Secure storage: where the real risk lives

Tokens are only as safe as where you keep them. On mobile, the storage choice is the difference between a token that is locked to the device and one that leaks through a cloud backup.

  • iOS — Keychain. Hardware-backed, encrypted, and you can mark items as not backed up and only available after first unlock. This is where refresh tokens belong.
  • Android — Keystore / EncryptedSharedPreferences. Keys backed by hardware where available, with encryption at rest.
  • Never store tokens in plain AsyncStorage, SharedPreferences, localStorage, or a plaintext file. Those can end up in backups, logs, or be read on a compromised device.

The backup leak nobody tests for

A refresh token written to unencrypted storage can be swept into an iCloud or Android cloud backup and restored onto a different device — handing a long-lived session to whoever controls that account. Use the platform secure store and mark credentials as non-exportable. It is one API call and it closes a hole you would never see in normal QA.

Refresh token rotation

The strongest pattern is rotation: every time a refresh token is used, it is invalidated and a brand-new one is issued. This gives you theft detection almost for free. If an old, already-used refresh token ever reappears, you know it was stolen and replayed — so you revoke the entire token family and force a re-login.

Rotation requires care on the client:

  • Persist the new refresh token before you consider the refresh successful, or a crash mid-rotation logs the user out.
  • Handle concurrent requests: if three calls hit a 401 at once, you do not want three parallel refreshes racing. Funnel them through a single in-flight refresh and let the others wait for the result.

The failure modes behind "it logged me out"

Mysterious logouts are almost always one of these:

  1. Clock skew. The device clock is off and the access token looks expired (or not-yet-valid). Allow a small leeway when checking expiry.
  2. Lost refresh token. Stored somewhere wiped on update, or never persisted after rotation.
  3. Refresh race. Two refreshes run, one rotates the token, the other now holds a dead one and triggers a security logout.
  4. Offline expiry.The user was offline past the access token's lifetime; the app needs to refresh on reconnect instead of dumping them to the login screen.

How Kembo manages sessions for you

Sessions are exactly the kind of thing you want to get right once and never touch. Kembo issues short-lived access tokens and long-lived refresh tokens, rotates them, and verifies them server-side — so the rules above are enforced for you rather than reimplemented per app.

  • The SDK stores credentials in the platform secure store — Keychain on iOS, Keystore on Android — not in plaintext.
  • Refresh and rotation happen under the hood; your screens just read the signed-in user from a hook and make API calls.
  • The concurrency and clock-skew edge cases that cause phantom logouts are handled in the SDK, not left for you to discover in production.

Don't roll your own token endpoint

Rotation, replay detection, and signature verification are easy to get subtly wrong, and the bugs are security bugs. Whether you use Kembo or another provider, prefer a battle-tested session layer over a homegrown one — this is not where bespoke code earns its keep.

A session you can trust

Good mobile session management is mostly about respecting two lifetimes, storing the long-lived one in hardware-backed storage, rotating it, and handling the boring edge cases — clock skew, races, offline. Get those right and your users stay logged in for weeks and your security team sleeps.

Or let it be handled for you. Start a free Kembo project and get hosted sign-in with secure, rotating sessions out of the box. Next week we step away from code and into compliance: account deletion requirements on the App Store and Google Play.

Ready to skip the Wednesday OAuth panic? Create a free Kembo project.