Token Storage

Overview

After a grant, FusionAuth delivers access tokens to the client. The client may also receive refresh and Id tokens, depending on the scopes requested.

These tokens are signed and signify that an authentication has occurred. You must store these tokens appropriately.

Access Token And Refresh Storage Options

Access tokens are meant to be presented by the client to secure resources to gain access to data or functionality. This includes APIs or other services.

Refresh tokens are designed to be presented by the client to FusionAuth in order to get a new access token.

Refresh tokens have a longer lifetime because they are useful only to FusionAuth. Access tokens are shorter lived because, as mentioned, they allow access to data or functionality.

Both access tokens and refresh tokens should be stored in a secure fashion. FusionAuth recommends that these tokens be stored in location inaccessible to the client.

There is always nuance when recommending solutions based on your application or applications and how tokens are used. Make sure you understand your threat model and how your tokens are used before selecting your token storage.

FusionAuth’s recommended storage mechanisms include:

  • Cookie: send the token down to the browser as a Secure, HttpOnly cookie. If you don’t require cross-site cookie sharing, set SameSite to Strict. Otherwise, set SameSite to Lax, which will share the cookies in certain situations. Learn more about SameSite settings.
  • BFF/Server-side Session: store the token server side, in a session. This is also known as the “backend for frontend” or BFF pattern. The session is typically managed by a framework, and ideally adheres to the same cookie storage recommendations. Learn more about server-side sessions. Please consult your framework documentation around securing sessions and data in sessions.
  • Native Secure Storage: when the client is a native mobile app, store the token in a secure storage area such as iOS Keychain or Android Keystore.

Here is a table of characteristics of recommended JWT storage options.

FeatureCookieBFF/Server-side SessionNative Secure Storage
Scalable client API requestsYesNoYes
Revocation possibleYesYesYes
Revocation straightforwardNoYesNo
Sticky sessions or session datastore requiredNoYesNo
Token sent on HTTP API requests automaticallyYes (you may need to tweak the credentials option)NoNo
Token can be presented to APIs on other domainsNoYes (via server-side requests)Yes
Works in a web browserNoYesNo

The proper JWT storage choice is based on your threat modeling and how much risk a particular service can tolerate. You can also configure your JWTs to be short lived, which minimizes the amount of time a stolen JWT can be used.

If you need to lock down JWTs further, implement token sidejacking protection using cookies and a nonce. An alternative is DPoP, an open feature request for FusionAuth.

Storage Options

Here is a complete list of storage options for access and refresh tokens.

OptionStrengthsWeaknessesSecurity ConsiderationsRecommended
Secure, HTTPOnly cookiesTokens sent automatically when credentials option sent, widely supportedWon’t work if clients are not on same domain as the APIs, requires a browser, APIs must look for access token in cookie header, not in other placesReduces attack surface by preventing JavaScript from accessing tokens, XSS resistant, but requires correct cookie configuration and same-domain policies.
Backend for frontend (BFF)/SessionsEasy to revoke tokens, works with any client, can be combined with cookie approach to provide cross domain access if some APIs live on different domainsAdditional server side component, less scalable because you are routing all API requests through the BFF, single point of failure for all API accessMinimizes token exposure by never sharing tokens with the client, but introduces a new critical infrastructure component that must be secured
Native secure storageOS-provided secure storage options like iOS Keychain or Android Keystore prevent token exfiltrationPlatform-specific implementationPrevents exfiltration by malicious apps, use TLS to prevent attacker-in-the-middle attacks
Mutual-TLS (MTLS)Tokens are bound to client, IETF standardNot widely supported, requires every client to have an X.509 certificateOffers strong token-binding security, but operational complexity and certificate management introduce significant overhead (when available)
Distributed Proof of Possession (DPoP)Tokens are bound to client, IETF standardNot widely supported, requires APIs to do extra work to verify the token, client must do extra work to send the token, still must take care to avoid exfiltration of keyEnhances token security by binding it to a client, but susceptible to implementation flaws and requires stringent key management (when available)
Local Storage, IndexedDBJavaScript can access token and send requests using Authorization or other expected header, supported by some frameworks (Amplify)Tokens vulnerable to exfiltration by any JavaScript running on the pageHighly vulnerable to XSS attacks
In MemoryYour code can access tokens but other code cannotTokens lost when the client reloadsReduces persistence of tokens, limiting exposure
Web workersBrowser APIs provide a layer of isolation between the web worker and the access tokenAll fetch calls must pass through web worker, have to use a library or write web worker integration code, malicious code may still be able to get data via the web worker, access token is removed when page is reloadedProvides isolation for tokens, but risks persist with malicious code targeting the web worker or intercepting network traffic

Id Token Storage Options

Id tokens contain data meant to be used by the client. For example, a JavaScript component can examine an Id token to display the name of a user.

Secure them in the same way you would any other user data that is readable by a browser or mobile app.