> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/expo/expo/llms.txt
> Use this file to discover all available pages before exploring further.

# expo-secure-store

> Encrypt and securely store key-value pairs locally on the device

# expo-secure-store

**Version:** 55.0.6

Provides a way to encrypt and securely store key-value pairs locally on the device. Uses Keychain on iOS and EncryptedSharedPreferences on Android to ensure data is stored securely.

## Installation

```bash theme={null}
npx expo install expo-secure-store
```

## Usage

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';

// Save data
await SecureStore.setItemAsync('authToken', 'abc123xyz');

// Read data
const token = await SecureStore.getItemAsync('authToken');
console.log('Token:', token);

// Delete data
await SecureStore.deleteItemAsync('authToken');
```

## API Reference

### Methods

<ParamField path="setItemAsync(key, value, options)" type="(key: string, value: string, options?: SecureStoreOptions) => Promise<void>">
  Stores a key-value pair securely

  **Parameters:**

  * `key` (string): Storage key
  * `value` (string): Value to store
  * `options` (SecureStoreOptions): Optional configuration

  ```typescript theme={null}
  await SecureStore.setItemAsync('username', 'john_doe');

  // With options
  await SecureStore.setItemAsync('password', 'secret123', {
    keychainAccessible: SecureStore.WHEN_UNLOCKED,
  });
  ```
</ParamField>

<ParamField path="getItemAsync(key, options)" type="(key: string, options?: SecureStoreOptions) => Promise<string | null>">
  Retrieves a value by key

  Returns `null` if key doesn't exist

  ```typescript theme={null}
  const username = await SecureStore.getItemAsync('username');
  if (username) {
    console.log('Username:', username);
  }
  ```
</ParamField>

<ParamField path="deleteItemAsync(key, options)" type="(key: string, options?: SecureStoreOptions) => Promise<void>">
  Deletes a stored value

  ```typescript theme={null}
  await SecureStore.deleteItemAsync('authToken');
  ```
</ParamField>

<ParamField path="isAvailableAsync()" type="() => Promise<boolean>">
  Checks if SecureStore is available on the platform

  ```typescript theme={null}
  const available = await SecureStore.isAvailableAsync();
  if (!available) {
    console.log('SecureStore not available on this platform');
  }
  ```
</ParamField>

### Types

#### SecureStoreOptions

<ParamField path="keychainService" type="string">
  iOS: Keychain service name. Android: SharedPreferences name

  ```typescript theme={null}
  { keychainService: 'myAppKeychain' }
  ```
</ParamField>

<ParamField path="keychainAccessible" type="KeychainAccessibilityConstant">
  iOS: When the stored data is accessible

  Values:

  * `WHEN_UNLOCKED` - Accessible when device is unlocked (default)
  * `AFTER_FIRST_UNLOCK` - Accessible after first unlock since boot
  * `ALWAYS` - Always accessible (deprecated)
  * `WHEN_PASSCODE_SET_THIS_DEVICE_ONLY` - Only when passcode is set
  * `WHEN_UNLOCKED_THIS_DEVICE_ONLY` - Device-only, when unlocked

  ```typescript theme={null}
  {
    keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
  }
  ```
</ParamField>

<ParamField path="requireAuthentication" type="boolean">
  iOS: Require Face ID/Touch ID to access

  ```typescript theme={null}
  { requireAuthentication: true }
  ```
</ParamField>

<ParamField path="authenticationPrompt" type="string">
  iOS: Prompt shown for biometric authentication

  ```typescript theme={null}
  {
    requireAuthentication: true,
    authenticationPrompt: 'Authenticate to access your password'
  }
  ```
</ParamField>

### Constants

```typescript theme={null}
// Keychain accessibility constants (iOS)
SecureStore.WHEN_UNLOCKED
SecureStore.AFTER_FIRST_UNLOCK
SecureStore.ALWAYS
SecureStore.WHEN_PASSCODE_SET_THIS_DEVICE_ONLY
SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
SecureStore.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY
SecureStore.ALWAYS_THIS_DEVICE_ONLY
```

## Examples

### Basic Storage

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';

async function saveCredentials(username: string, password: string) {
  try {
    await SecureStore.setItemAsync('username', username);
    await SecureStore.setItemAsync('password', password);
    console.log('Credentials saved');
  } catch (error) {
    console.error('Error saving credentials:', error);
  }
}

async function loadCredentials() {
  try {
    const username = await SecureStore.getItemAsync('username');
    const password = await SecureStore.getItemAsync('password');
    return { username, password };
  } catch (error) {
    console.error('Error loading credentials:', error);
    return null;
  }
}
```

### Store Auth Token

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';

async function login(username: string, password: string) {
  // Authenticate with server
  const response = await fetch('https://api.example.com/login', {
    method: 'POST',
    body: JSON.stringify({ username, password }),
  });
  
  const { token } = await response.json();
  
  // Store token securely
  await SecureStore.setItemAsync('authToken', token);
}

async function getAuthToken() {
  return await SecureStore.getItemAsync('authToken');
}

async function logout() {
  await SecureStore.deleteItemAsync('authToken');
}
```

### Biometric Protection

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';
import * as LocalAuthentication from 'expo-local-authentication';

async function saveSensitiveData(key: string, value: string) {
  // Check if biometric auth is available
  const hasHardware = await LocalAuthentication.hasHardwareAsync();
  const isEnrolled = await LocalAuthentication.isEnrolledAsync();
  
  if (hasHardware && isEnrolled) {
    // Store with biometric protection
    await SecureStore.setItemAsync(key, value, {
      requireAuthentication: true,
      authenticationPrompt: 'Authenticate to save data',
    });
  } else {
    // Store without biometric protection
    await SecureStore.setItemAsync(key, value);
  }
}

async function getSensitiveData(key: string) {
  try {
    const value = await SecureStore.getItemAsync(key, {
      requireAuthentication: true,
      authenticationPrompt: 'Authenticate to access data',
    });
    return value;
  } catch (error) {
    console.error('Authentication failed:', error);
    return null;
  }
}
```

### Store JSON Data

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';

interface UserSettings {
  theme: string;
  notifications: boolean;
  language: string;
}

async function saveSettings(settings: UserSettings) {
  const jsonString = JSON.stringify(settings);
  await SecureStore.setItemAsync('userSettings', jsonString);
}

async function loadSettings(): Promise<UserSettings | null> {
  const jsonString = await SecureStore.getItemAsync('userSettings');
  if (!jsonString) return null;
  
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    console.error('Error parsing settings:', error);
    return null;
  }
}
```

### Custom Keychain Service

```typescript theme={null}
import * as SecureStore from 'expo-secure-store';

const KEYCHAIN_SERVICE = 'com.myapp.secure';

async function saveToCustomKeychain(key: string, value: string) {
  await SecureStore.setItemAsync(key, value, {
    keychainService: KEYCHAIN_SERVICE,
  });
}

async function getFromCustomKeychain(key: string) {
  return await SecureStore.getItemAsync(key, {
    keychainService: KEYCHAIN_SERVICE,
  });
}
```

### Complete Auth Example

```tsx theme={null}
import * as SecureStore from 'expo-secure-store';
import { useState, useEffect } from 'react';
import { View, TextInput, Button, Text, StyleSheet } from 'react-native';

export default function AuthExample() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  useEffect(() => {
    checkLoginStatus();
  }, []);

  async function checkLoginStatus() {
    const token = await SecureStore.getItemAsync('authToken');
    setIsLoggedIn(!!token);
  }

  async function handleLogin() {
    // Simulate API call
    const token = 'mock-jwt-token-' + Date.now();
    
    // Store credentials
    await SecureStore.setItemAsync('authToken', token);
    await SecureStore.setItemAsync('username', username);
    
    setIsLoggedIn(true);
  }

  async function handleLogout() {
    await SecureStore.deleteItemAsync('authToken');
    await SecureStore.deleteItemAsync('username');
    setIsLoggedIn(false);
    setUsername('');
    setPassword('');
  }

  if (isLoggedIn) {
    return (
      <View style={styles.container}>
        <Text style={styles.title}>Welcome back!</Text>
        <Button title="Logout" onPress={handleLogout} />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Login</Text>
      
      <TextInput
        style={styles.input}
        placeholder="Username"
        value={username}
        onChangeText={setUsername}
        autoCapitalize="none"
      />
      
      <TextInput
        style={styles.input}
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      
      <Button title="Login" onPress={handleLogin} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', padding: 20, gap: 15 },
  title: { fontSize: 24, fontWeight: 'bold', textAlign: 'center' },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    padding: 10,
    borderRadius: 5,
  },
});
```

## Platform Support

| Platform | Supported |
| -------- | --------- |
| iOS      | ✅         |
| Android  | ✅         |
| Web      | ❌         |

<Note>
  On iOS, SecureStore uses the system Keychain. On Android, it uses EncryptedSharedPreferences with AES-256 encryption.
</Note>

## Security Features

### iOS (Keychain)

* Hardware-backed encryption when available
* Secure Enclave support
* Face ID/Touch ID integration
* Automatic iCloud Keychain sync (optional)
* Data persists across app reinstalls (configurable)

### Android (EncryptedSharedPreferences)

* AES-256 encryption
* Hardware-backed encryption on supported devices
* Data removed on app uninstall

## Best Practices

1. **Store Only Sensitive Data**: Don't use SecureStore for non-sensitive data (use AsyncStorage instead)
2. **Keep Values Small**: Limit stored values to a few kilobytes
3. **Handle Errors**: Always wrap operations in try/catch blocks
4. **Biometric Auth**: Use `requireAuthentication` for highly sensitive data
5. **Clean Up**: Delete sensitive data when no longer needed
6. **Check Availability**: Use `isAvailableAsync()` before operations

<Warning>
  SecureStore is not available on web. For cross-platform apps, implement a fallback storage mechanism or handle gracefully.
</Warning>

## Common Use Cases

* **Auth tokens**: Store JWT tokens or session IDs
* **API keys**: Store API keys and secrets
* **User credentials**: Store encrypted passwords (when necessary)
* **Payment info**: Store sensitive payment tokens
* **Private keys**: Store cryptographic keys

## Limitations

* **Value size**: Limited to a few kilobytes per entry
* **Not for large data**: Use file system for large files
* **Web not supported**: No secure storage equivalent in browsers
* **No synchronization**: Data not automatically synced across devices

## Resources

* [Official Documentation](https://docs.expo.dev/versions/latest/sdk/securestore/)
* [GitHub Repository](https://github.com/expo/expo/tree/main/packages/expo-secure-store)
