Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Secrets: expo-secure-store

AsyncStorage does not encrypt data, so login tokens and other secrets must not be kept in it. The expo-secure-store module saves strings in the system's protected storage: the Keychain on iOS, and encryption with a key from the Android Keystore on Android.

Installing

In the blog project run:

npx expo install expo-secure-store

The module works in Expo Go on a phone and in an emulator. It is not available in a browser.

Methods

MethodWhat it does
SecureStore.setItemAsync(key, value)Saves a string
SecureStore.getItemAsync(key)Returns a string or null
SecureStore.deleteItemAsync(key)Removes a value

A key may contain only Latin letters, digits and the characters ., - and _.

A module for the token

Suppose that after login the server issued a token, a string to send with every request. Create the file:

// lib/auth.ts
import * as SecureStore from 'expo-secure-store';
 
const KEY = 'auth_token';
 
export function saveToken(token: string) {
  return SecureStore.setItemAsync(KEY, token);
}
 
export function getToken() {
  return SecureStore.getItemAsync(KEY);
}
 
export function deleteToken() {
  return SecureStore.deleteItemAsync(KEY);
}

All three functions return promises, just like in AsyncStorage.

Using it on the profile screen

// app/(tabs)/profile.tsx
import { useEffect, useState } from 'react';
import { Button, Text, View } from 'react-native';
import { deleteToken, getToken, saveToken } from '@/lib/auth';
 
export default function Profile() {
  const [token, setToken] = useState<string | null>(null);
 
  useEffect(() => {
    getToken().then(setToken);
  }, []);
 
  async function logIn() {
    await saveToken('demo-token-123');
    setToken('demo-token-123');
  }
 
  async function logOut() {
    await deleteToken();
    setToken(null);
  }
 
  return (
    <View style={{ flex: 1, padding: 16, gap: 12 }}>
      <Text>{token ? 'You are logged in' : 'You are not logged in'}</Text>
      {token ? <Button title="Log out" onPress={logOut} /> : <Button title="Log in" onPress={logIn} />}
    </View>
  );
}

Tap "Log in", close the app and open it again: the "Profile" tab still says "You are logged in". "Log out" removes the token from storage.

What goes where

DataStorage
Tokens, passwords, keysexpo-secure-store
Settings, drafts, cacheAsyncStorage
Many records with searchexpo-sqlite

Secure storage is meant for small values, about 2 KB per key, so large objects do not go there.

Common mistake

Saving the user's password to log in automatically later. Even in secure storage a password is an unnecessary risk. Keep the token the server issued: it can be revoked, and it does not unlock other services where the person uses the same password.

Thanks for reading!

Donate to the site — we work hard for you.