Sessions & Tokens
How Flowsta issues, scopes, and ends sessions - what your app holds, for how long, and what ends it.
The Three-Token Model
Flowsta uses three types of tokens with different lifetimes:
| Token | Lifetime | Purpose |
|---|---|---|
| Access token | 24 hours | Authorizes API requests from OAuth apps |
SSO session cookie (flowsta_session) | 7 days | Keeps the user signed in across Flowsta's own sites and the consent screen |
| Refresh token | 30 days | Silently obtains new access tokens |
How they work together:
- When a user signs in with their Vault, Flowsta sets the SSO session cookie - a 7-day JWT scoped to
.flowsta.com. While it's valid, Flowsta sites and "Sign in with Flowsta" consent screens recognize the user. - When an OAuth app completes the flow, it receives an access token (24 hours) and a refresh token (30 days).
- When the access token expires, the app exchanges the refresh token for a new access token. The refresh token itself is not rotated - it keeps its original 30-day expiration from the time of issue.
- After the refresh token expires, the app sends the user through the sign-in flow again.
All three are stateless JWTs signed by Flowsta: the server keeps no session list, so a token is valid until it expires or, for refresh tokens, until it is revoked through POST /oauth/revoke.
How sign-in works
Signing in is a cryptographic challenge the user's Vault answers:
- Flowsta Vault requests a one-time challenge (
POST /auth/vault/challenge) - The Vault signs it with the identity key - derived from the user's 24-word recovery phrase, never sent anywhere - and, from 1.6.0, this device's own key beside it
- The signed challenge is exchanged for a session (
POST /auth/vault/token), which returns a JWT and sets theflowsta_sessioncookie
The user approves the sign-in in their Vault, or a site they chose to remember is approved without a prompt. See Zero-Knowledge Architecture for the full picture.
What a session is bound to
- A web session belongs to the identity that signed in. The JWT carries that identity's user id, agent public key and DID. Switching to another identity in the Vault does not end the session and does not move it: the browser stays signed in as the identity that answered the challenge until the user signs out or the token expires.
- Sign-out is per site.
POST /auth/logout(with the session's bearer token) clears theflowsta_sessioncookie for that browser. It does not touch other browsers or devices, and it does not revoke OAuth tokens your app holds - end those withPOST /oauth/revoke. - Devices are independent. A user can be signed in on several devices at once; each holds its own JWT with its own expiry. There is no server-side list of sessions and no way to end them all at once.
For Developers
If you're building an app that uses Flowsta authentication:
Handle expired sessions gracefully
- Detect 401 responses
- Show a "Session expired" message
- Redirect to sign-in with a return URL
Implement token refresh
- Check token expiration before requests
- Refresh proactively (before expiration)
- Handle refresh failures gracefully - after 30 days the refresh token itself expires and the user must sign in again
Store tokens securely
- Use HTTP-only cookies for server-rendered apps (best)
- The
@flowsta/authSDK useslocalStoragefor SPA convenience (acceptable for PKCE flows without client secrets) - Sensitive PKCE data is stored in
sessionStorageand cleared after use
Key your records to the identity, not the browser. Use
sub(or the DID) from/oauth/userinfo. Because a session stays with the identity that signed in, a user who switches identities in their Vault and then signs in to your app again arrives as a differentsub.
See the SDK Documentation for implementation details.
Technical Details
JWT Structure
A session JWT for a device-hosted identity:
{
"id": "user_abc123",
"userId": "user_abc123",
"email": null,
"agentPubKey": "uhCAk...",
"did": "did:flowsta:uhCAk...",
"hostingModel": "device-hosted",
"iat": 1698765432,
"exp": 1699370232,
"iss": "flowsta-auth",
"aud": "flowsta-sites"
}Token Claims
| Claim | Description |
|---|---|
id / userId | Unique user identifier |
email | null for device-hosted identities - the server holds only an email hash |
agentPubKey | Holochain identity (public key) |
did | W3C Decentralized Identifier, did:flowsta:<agent key> |
hostingModel | device-hosted for Vault identities; custodial for legacy web accounts |
iat | Issued at (timestamp) |
exp | Expires at (timestamp, +7 days) |
iss | Issuer (flowsta-auth) |
aud | Audience (flowsta-sites) |
The session holds no password, no private data, and no browsing history. Whoever holds a session token can do what that session is authorized to do until it expires; they cannot reach the recovery phrase, the device keys, or the sealed private records, none of which leave the user's device.
Session Cookie
Set-Cookie: flowsta_session=eyJhbGc...;
HttpOnly;
Secure;
SameSite=Lax;
Max-Age=604800;
Domain=.flowsta.comSee the API Reference for complete technical documentation.
Related Documentation
Need Help?
- Discord: Join our community
- Support: Find out about Flowsta support options
- GitHub: github.com/WeAreFlowsta