This topic discusses best practices and recommendations for securely storing CyberArk Identity OpenIDConnect (OIDC) tokens in your applications.
Token types
Three types of OIDC tokens are used with CyberArk Identity: access tokens, ID tokens, and optional refresh tokens.
Access and refresh tokens have two main use cases:
-
When a client application needs to call one or more CyberArk Identity APIs.
In this use case, CyberArk Identity serves as both the OAuth 2.0 authorization server and resource server. The client acquires tokens from the authorization server, and then includes them in any API requests.
-
When a client application secures its APIs using CyberArk Identity tokens.
In this use case, CyberArk Identity is the authorization server while the third-party API is the resource server.
For a more detailed description of each token, see:
-
Access tokens
-
ID tokens
-
Refresh tokens
Client types
Two types of clients are defined in the OAuth 2.0 specification: confidential and public clients. The distinction between clients stems from secret storage. Secrets allow registered clients to make authorized calls to an OAuth 2.0 authorization server.
-
Some clients, such as servers, can store these secrets without the risk of users exposing them. These are known as confidential clients.
-
Public clients, including native, mobile and browser-based applications, cannot securely store such secrets. These clients should use OAuth 2.0 flows that do not store registered secrets in the UI.
We recommend against storing IDtokens. If you must do so, ensure that you clear the tokens when users log out or delete accounts.
In contrast to traditional web apps, single-page applications (SPAs) require client-side API calls to process user interactions.
For SPAs that make APIcalls to one or more servers on a different domain, access tokens are necessary. You may also choose to use refresh tokens.
Recommended Flow: Authorization Code Flow with PKCE
SDK: CyberArk Identity JavaScript SDK
You should store and access tokens exclusively through the OS's secure storage mechanism. Use Keychain for iOSapps and KeyStore for Android apps.
Recommended Flow: Authorization Code Flow with PKCE
SDK: CyberArk Identity SDK for iOS / CyberArk Identity SDK for Android
For web applications rendered entirely server-side, there are no browser-based APIcalls needed to populate the user interface.
These types of apps are often known as traditional web apps. Traditional web apps still require access and refresh tokens. However, they do not need to be stored in the client because the back end performs the APIcalls.
We recommend storing tokens on the server, as this offers traditional web apps the maximum level of security. If this cannot be done, you should use encrypted session cookies so the client cannot read token values.
Recommended Flows: Authorization Code Flow (PKCE is recommended but optional)
Security risks
Keep two well-known vulnerabilities in mind when storing tokens: Cross Site Scripting (XSS) and Cross Site Request Forgery (CSRF) attacks.
-
XSSattacks enable attackers to inject malicious JavaScript into a browser so that important information, such as tokens, can be stolen.
-
CSRF attacks enable attackers to cause an authenticated user's browser to issue requests that modify the application state.
Traditional web app / SPAoptions
You can use the following storage options in both traditional web apps and single-page applications (SPAs):
-
Cookies
-
Local/session storage
Cookies
Cookies are one of the most established and time-tested methods of storing user information. However, you should take care to mitigate both XSSand CSRF attacks.
Advantages
-
Sent automatically with every request, enabling simple implementation for development teams
See AlsoToken ID - A Visa Solution -
Persist across page reloads and browser restarts
Disadvantages
Cookies are vulnerable to both XSSand CSRFattacks. However, you can prevent these attacks in several ways:
-
Use
httpOnly
cookies to ensure that only the server can access cookie contents. This prevents XSSattacks from hijacking tokens stored in cookies. -
Use an anti-CSRF protection mechanism, such as an
X-CSRF-Token
HTTPheader containing the cookie's value. Most web app frameworks provide built-in support for CSRFtoken verification. -
In combination with CSRFtokens, set the
SameSite
attribute of cookies to eitherLax
orStrict
to limit their inclusion in cross-site requests. -
If your application uses cross-origin resource sharing (CORS)to allow cross-domain requests, ensure that request headers are properly set to further prevent CSRF attacks.
Local/session storage
Local storage enables you to save key-value pairs in a reserved section of browser memory. This section of memory follows a same-origin policy, preventing other domains from accessing its contents.
Your application's JavaScript can use the window.sessionStorage
property to access it.
Differences between local and session storage
Local and session storage implement the same Storage
JavaScript interface. However, keep in mind the following differences:
-
Local storage persists until a user clears their browser data, while session storage persists until a user closes their tab or window.
-
Local storage can be accessed across windows or tabs. Session storage is limited to a particular window or tab.
Advantages
-
Both storage options are immune to CSRF attacks.
Disadvantages
-
Local and session storage are vulnerable to XSS attacks. However, you can prevent this in two ways:
-
Implement refresh token rotation, which requires a new refresh token to be used each time an access token is requested.
-
Shorten the lifespan of refresh tokens to limit the potential impact of token theft.
-
-
Tokens stored in
localStorage
orsessionStorage
must be explicitly included with requests using JavaScript.
SPA-onlyoptions
You can use the following storage options in SPAs:
-
Backend for frontend (BFF)
-
JavaScript Memory
-
Workers
Backend for frontend (BFF)
With SPAs, it is recommended to use the backend for frontend (BFF) pattern.
Other storage options expose SPAs to vulnerabilities, and though mitigations exist, they do not completely eliminate the threat of token theft.
With BFFs, you can offload token storage entirely to a backend client. This client can securely acquire and store tokens in order to proxy API requests on behalf of the user.
The following flow describes the role of the BFF:
The user accesses an SPA in their browser.
The user clicks a login button, causing the SPA to redirect to an endpoint on the BFF, such as
/bff/login
.The BFF initiates the standard OpenIDConnect (OIDC) authentication flow.
After the user authenticates with the OIDC provider, the access, ID, and refresh tokens are stored in the BFF.
The backend issues a first-party cookie to the SPA.It is configured as
SameSite: 'Strict'
,httpOnly
, andSecure
.In effect, this cookie creates a sandbox between the SPA and backend for the duration of the user's session.
To issue a request to a protected API, the SPAcalls the BFF with the desired endpoint and payload.
The BFF appends the user's access token and proxies the request to the appropriate API.
The APIresponse is forwarded to the SPA.
Advantages
Never stores the token in the browser; thus, eliminating the risk of client-side token theft
Widely considered the best practice for modern SPAs
Disadvantages
- Requires additional infrastructure to host the BFF, which can increase cost and complexity
JavaScript memory
Advantages
JavaScript memory is accessible only by your web app's JavaScript, eliminating the possibility of XSSand CSRFattacks.
Disadvantages
Data stored in memory does not persist across page refreshes, so special care must be taken to ensure that users are not logged out. You can, however, solve this by storing refresh tokens in httpOnly
cookies. The application can then use them to request new access tokens when the page is refreshed.
Workers
Workers allow you to run JavaScript code in the background without sharing any memory. This is useful for ensuring that sensitive information, such as tokens, cannot be accessed.
Advantages
Workers are inaccessible to other JavaScript, making them resistant to XSSand CSRFattacks.
Disadvantages
Workers are not supported by some older browsers, though this is becoming less of an issue.