Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

OAuth Token Storage Security: Best Practices for Web & Mobile Apps

Securely handling OAuth access and refresh tokens is essential for protecting user data in web and mobile applications. Follow best‑practice storage methods to reduce token theft risk.

Focus: OAuth token storage security

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

OAuth Token Storage Security: Best Practices for Web and Mobile Apps

Overview

OAuth 2.0 is the de‑facto standard for delegated access. After a user authorizes an app, the server issues an access token (short‑lived) and often a refresh token (long‑lived). If these tokens are compromised, an attacker can act on behalf of the user. The core challenge is to store them in a way that minimizes exposure while keeping the user experience smooth.

Web Applications

1. Store Access Tokens in Memory or Short‑Lived Cookies

  • In‑memory: Keep the access token in a JavaScript variable or a server‑side session. It disappears when the session ends, reducing the window for theft.
  • HttpOnly, Secure cookies: If you must persist the token, use a cookie flagged HttpOnly (inaccessible to JavaScript) and Secure (sent only over HTTPS). This mitigates XSS attacks.
Code snippet
# Example: Setting a secure cookie in Flask
response = make_response()
response.set_cookie(
    key="access_token",
    value=access_token,
    httponly=True,
    secure=True,
    samesite="Strict",
    max_age=3600  # 1 hour
)

2. Store Refresh Tokens Securely on the Server

  • Never expose refresh tokens to the client. Keep them in a server‑side database, linked to the user’s session. When the access token expires, the server silently requests a new one using the stored refresh token.

3. Use the Authorization Code Flow with PKCE

  • For public clients (e.g., single‑page apps), employ the Authorization Code Flow with PKCE. PKCE adds a cryptographic challenge that prevents token replay attacks even if the authorization code is intercepted.

4. Token Refresh Strategy

  • Refresh tokens should have a reasonable lifetime (e.g., 30 days) and be revocable. Implement a revocation endpoint so users can invalidate tokens if they suspect compromise.

Mobile Applications

1. Use Platform‑Specific Secure Storage

  • iOS: Store tokens in the Keychain. It is encrypted, sandboxed, and protected by the device’s passcode.
  • Android: Use EncryptedSharedPreferences or the Android Keystore to keep tokens encrypted at rest.
Code snippet
# Example: Using Android Keystore (pseudo‑code)
from android.keystore import KeyStore
keystore = KeyStore.getInstance("AndroidKeyStore")
keystore.load(null)  # no password for this example
# store token as a secret entry

2. Prefer Short‑Lived Access Tokens

  • Mobile apps often have limited storage and higher risk of device theft. Issue access tokens that expire quickly (e.g., 5–15 minutes) and rely on refresh tokens for renewal.

3. Implement Silent Token Refresh

  • Use a background service that detects token expiration and triggers a silent refresh using the stored refresh token. This avoids prompting the user repeatedly.

4. Guard Against Root/Jailbreak

  • Detect rooted or jailbroken devices. If detected, refuse to store tokens or store them in a more restricted environment (e.g., memory only).

Common Pitfalls

  • Storing tokens in localStorage or sessionStorage: These storages are accessible to any script running on the page, making them vulnerable to XSS.
  • Hard‑coding tokens in source code: Tokens embedded in the app binary can be extracted by reverse engineering.
  • Using the same token across multiple clients: A compromised token on one platform exposes the user on all platforms.
  • Neglecting token revocation: Without a way to invalidate tokens, stolen tokens remain usable until they naturally expire.

Practical Example: Secure Token Flow (Web)

Code snippet
# 1. User initiates login
auth_url = f"{AUTH_ENDPOINT}?response_type=code&client_id=MY_CLIENT&redirect_uri={REDIRECT_URI}&code_challenge={pkce_challenge}&code_challenge_method=S256"

# 2. After redirect, exchange code for tokens
import requests

def exchange_code_for_tokens(code):
    payload = {
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": REDIRECT_URI,
        "client_id": CLIENT_ID,
        "code_verifier": pkce_verifier  # PKCE verifier
    }
    resp = requests.post(TOKEN_ENDPOINT, data=payload)
    data = resp.json()
    return data["access_token"], data["refresh_token"]

access_token, refresh_token = exchange_code_for_tokens(auth_code)

# 3. Store access token in an HttpOnly cookie (server side)
#    Store refresh token in a server‑side DB linked to the user session

Best‑Practice Checklist

  • ✅ Use HTTPS everywhere.
  • ✅ Keep access tokens short‑lived.
  • ✅ Store refresh tokens only on the server or in platform‑secure storage.
  • ✅ Apply HttpOnly, Secure, SameSite flags for cookies.
  • ✅ Implement PKCE for public clients.
  • ✅ Provide a revocation endpoint.
  • ✅ Regularly audit token handling code for XSS and injection risks.

Summary

Secure token storage hinges on separating concerns: keep short‑lived access tokens out of persistent storage, protect refresh tokens with server‑side mechanisms or platform‑specific secure storage, and always use TLS. By following the guidelines above — short token lifetimes, HttpOnly cookies, PKCE, and secure mobile storage — developers can dramatically reduce the risk of token theft in both web and mobile applications.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.