Security: Avoid storing OAuth refresh tokens in localStorage
Summary
@elfsquad/authentication currently stores OAuth tokens, including the refresh_token, in localStorage.
Because localStorage is accessible to any JavaScript executing in the application's origin, a successful Cross-Site Scripting (XSS) vulnerability could allow an attacker to extract the refresh token and impersonate the user for an extended period. This significantly increases the impact of XSS vulnerabilities.
Current Behavior
- Access token stored in
localStorage
- Refresh token stored in
localStorage
Security Risk
A refresh token typically has a much longer lifetime than an access token. If it is stored in localStorage, any injected or compromised script can read and exfiltrate it.
Example:
const refreshToken = localStorage.getItem("refresh_token");
// Attacker exfiltrates the token
This could enable:
- Long-lived account/session takeover
- Token refresh outside the user's browser
- Continued access until the token is revoked or expires
Recommendation
Prefer one of the following approaches:
Preferred
- Store the refresh token in an HttpOnly, Secure, SameSite cookie.
- Keep the access token in memory and obtain a new one through a refresh endpoint when needed.
Alternative
If the architecture permits, adopt a Backend-for-Frontend (BFF) pattern so OAuth tokens never reach the browser.
Benefits
- Prevents JavaScript from directly reading refresh tokens.
- Reduces the impact of XSS vulnerabilities.
- Aligns with current OAuth security best practices for browser-based applications.
Notes
If browser storage must be used due to architectural constraints, additional mitigations such as short-lived access tokens, refresh token rotation with reuse detection, a strict Content Security Policy (CSP), and strong XSS defenses should be implemented. However, these measures do not eliminate the risk of token theft from localStorage.
Security: Avoid storing OAuth refresh tokens in
localStorageSummary
@elfsquad/authenticationcurrently stores OAuth tokens, including therefresh_token, inlocalStorage.Because
localStorageis accessible to any JavaScript executing in the application's origin, a successful Cross-Site Scripting (XSS) vulnerability could allow an attacker to extract the refresh token and impersonate the user for an extended period. This significantly increases the impact of XSS vulnerabilities.Current Behavior
localStoragelocalStorageSecurity Risk
A refresh token typically has a much longer lifetime than an access token. If it is stored in
localStorage, any injected or compromised script can read and exfiltrate it.Example:
This could enable:
Recommendation
Prefer one of the following approaches:
Preferred
Alternative
If the architecture permits, adopt a Backend-for-Frontend (BFF) pattern so OAuth tokens never reach the browser.
Benefits
Notes
If browser storage must be used due to architectural constraints, additional mitigations such as short-lived access tokens, refresh token rotation with reuse detection, a strict Content Security Policy (CSP), and strong XSS defenses should be implemented. However, these measures do not eliminate the risk of token theft from
localStorage.