Secure Storage
Store strings in the iOS Keychain and Android Keystore with AES-256-GCM.
- iOS, supported
- Android, supported
- Web, not supported
- Package
- @capnative/capacitor-secure-storage
- npm version
- 8.0.1
- Capacitor
- 8.x · MIT
API checked against the repository README, TypeScript definitions, and npm on October 25, 2026.The README marks this major as maintained.
Install
Peer dependency: @capacitor/core >= 8.0.0
npm install @capnative/capacitor-secure-storage
npx cap syncUsage
import { SecureStorage } from '@capnative/capacitor-secure-storage';
await SecureStorage.set({
key: 'access_token',
value: 'my-secret-token',
});
const { value } = await SecureStorage.get({
key: 'access_token',
});Platform setup
The plugin stores strings only. Keys must be non-empty and at most 256 UTF-8 bytes. clear() removes values this plugin stored and does not touch other Keychain or Keystore items.
The README does not list Info.plist keys or Android permissions. The Android manifest in the repository is empty.
iOS
Values go in the iOS Keychain. Minimum version is iOS 15.
TODO: the README does not document the Keychain accessibility attribute or access group.
Android
Values are encrypted with AES-256-GCM and the key is held in the Android Keystore. Minimum version is API 24.
Web
There is no web implementation. The web class rejects every method with UNAVAILABLE instead of writing to localStorage. The source comment calls that fallback a security problem, so it is intentionally absent.
API
Method signatures match SecureStorage in the plugin repository. Import it from @capnative/capacitor-secure-storage.
set()
Stores a string value securely. If the key already exists, its value is overwritten. Empty string values are allowed.
set(options: { key: string; value: string }) => Promise<void>| Param | Type | Description |
|---|---|---|
| options.key | string | Non-empty key, at most 256 UTF-8 bytes. |
| options.value | string | String value to store. Empty strings are allowed. |
get()
Retrieves a stored value. The value is null if the key does not exist.
get(options: { key: string }) => Promise<{ value: string | null }>| Param | Type | Description |
|---|---|---|
| options.key | string | Key to read. |
Returns Promise<{ value: string | null }>
has()
Checks whether a key exists.
has(options: { key: string }) => Promise<{ value: boolean }>| Param | Type | Description |
|---|---|---|
| options.key | string | Key to check. |
Returns Promise<{ value: boolean }>
remove()
Deletes a key. Succeeds even if the key does not exist.
remove(options: { key: string }) => Promise<void>| Param | Type | Description |
|---|---|---|
| options.key | string | Key to delete. |
clear()
Deletes every value stored by this plugin and nothing else.
clear() => Promise<void>Type aliases
SecureStorageErrorCode
'INVALID_KEY' | 'INVALID_VALUE' | 'STORAGE_ERROR' | 'KEYCHAIN_ERROR' | 'KEYSTORE_ERROR' | 'ENCRYPTION_ERROR' | 'DECRYPTION_ERROR' | 'UNAVAILABLE'
Reported as error.code. MAX_KEY_LENGTH in the definitions file is 256 UTF-8 bytes.
Errors
Rejected promises expose a stable code. Match on that code rather than the message text.
| Code | Platform | Meaning |
|---|---|---|
| INVALID_KEY | iOS, Android | The key is empty or exceeds 256 UTF-8 bytes. |
| INVALID_VALUE | iOS, Android | The value passed to set is not a string. |
| STORAGE_ERROR | iOS, Android | An unexpected storage operation failed, or Android could not persist a change. |
| KEYCHAIN_ERROR | iOS | The iOS Keychain operation failed. |
| KEYSTORE_ERROR | Android | The Android Keystore could not be accessed or updated. |
| ENCRYPTION_ERROR | Android | The value could not be encrypted. |
| DECRYPTION_ERROR | Android | The stored value is corrupt, tampered with, or cannot be decrypted with the available Keystore key. |
| UNAVAILABLE | Web | Secure storage is not supported on the web. There is no insecure storage fallback. |