Search code examples
react-nativejwtexpolocal-storagesupabase

Is it advisable to use localStorage to store JWT for Expo for Web?


I'm using Expo Secure Store to store JWT credentials from Supabase:

const ExpoSecureStoreAdapter = {
  getItem: (key: string) => {
      return SecureStore.getItemAsync(key);
  },
  setItem: (key: string, value: string) => {
      SecureStore.setItemAsync(key, value);
  },
  removeItem: (key: string) => {
      SecureStore.deleteItemAsync(key);
  },
};

Which works well for iOS / Android, but is not supported for Expo Web. Therefore, I'm using localStorage for web clients instead:

const WebLocalStorageAdapter = {
  getItem: async (key: string) => {
    return localStorage.getItem(key);
  },
  setItem: async (key: string, value: string) => {
    return localStorage.setItem(key, value);
  },
  removeItem: async (key: string) => {
    return localStorage.removeItem(key);
  },
}

Then just handling web if needed:

const isWeb = Platform.OS === 'web';
const storageAdapter = isWeb ? WebLocalStorageAdapter : ExpoSecureStoreAdapter;

Is this advisable, or am I opening up an attack vector I'm unaware of, or other issues?


Solution

  • You should generally be okay, the main issue with storing a JWT token in localStorage is that you open yourself up to cross-site scripting (XSS) attacks; however, modern libraries like React mitigate against these attacks by escaping and encoding all untrusted data. Besides data that isn't encoded properly, you leave yourself open to a few vulnerabilities:

    1. Lack of Input Validation/Sanitization: If user input is not validated or sanitized, an attacker could insert malicious JavaScript code
    2. Outdated Libraries/Software: Outdated software or libraries can have known vulnerabilities
    3. Poorly Configured Security Headers: Without the use of certain headers like Content-Security-Policy, you'll be leaving yourself vulnerable

    There's additional info present on this post: Is it safe to store a JWT in localStorage with ReactJS?.