# Class SecureStorage

java.lang.Object
com.codename1.security.SecureStorage

public class SecureStorage extends Object

Biometric-gated secure storage backed by the platform keychain. Reading an entry prompts the user for biometric authentication; writing or deleting may or may not, depending on the platform.

Entries are bound to the current set of enrolled biometrics. If the user adds a fingerprint, enrols a new face, or disables device security, every stored entry is automatically invalidated and subsequent `get(String, String)` calls fail with `BiometricError.KEY_REVOKED`. The application must then re-prompt the user for the original value and `set(String, String, String)` it again.

Use this for short, secret strings (auth tokens, refresh tokens, encryption keys). For larger data, encrypt with a key stored here.

##### Platform support

- iOS -- backed by Security.framework (`SecItemAdd` / `SecItemCopyMatching` / `SecItemDelete`) with `kSecAccessControlTouchIDCurrentSet`. Sharing entries with App Extensions requires both the `ios.keychainAccessGroup` build hint AND a call to `setKeychainAccessGroup(String)` passing the same Team-ID-prefixed group identifier.
- Android -- AES/CBC/PKCS7 ciphertext stored in `SharedPreferences` with the key in the `AndroidKeyStore`, locked via `setUserAuthenticationRequired(true)`. The `BiometricPrompt` (API 29+) or `FingerprintManager` (API 23-28) unlocks the cipher for one operation per prompt.
- JavaSE simulator -- backed by `java.util.prefs.Preferences`, gated on the same Biometric Simulation menu used by `Biometrics`. Useful for testing the round-trip and `KEY_REVOKED` paths without a device.
- All other platforms -- this base class is returned as-is and acts as a non-supporting fallback: every method completes with `BiometricError.NOT_AVAILABLE`. Application code does not need platform `if` statements.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `SecureStorage()`
  Subclasses are constructed by the port.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AsyncResource<String>`
  `get(String reason, String account)`
  Retrieves a previously-stored entry, prompting for biometric authentication.
  `static SecureStorage`
  `getInstance()`
  Returns the platform-specific singleton owned by the current port.
  `AsyncResource<Boolean>`
  `remove(String reason, String account)`
  Removes a previously-stored entry.
  `AsyncResource<Boolean>`
  `set(String reason, String account, String value)`
  Stores or overwrites a value for the given account.
  `void`
  `setKeychainAccessGroup(String group)`
  Configures the iOS keychain access group for sharing entries between the main app and its extensions.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### SecureStorage

    protected SecureStorage()
    Subclasses are constructed by the port. Application code obtains the active instance via `getInstance()`.

- ## Method Details

  - ### getInstance

    public static SecureStorage getInstance()
    Returns the platform-specific singleton owned by the current port. On ports that do not implement secure storage this returns a base `SecureStorage` instance whose methods report `BiometricError.NOT_AVAILABLE`.

  - ### get

    public AsyncResource<String> get(String reason, String account)
    Retrieves a previously-stored entry, prompting for biometric authentication. The returned `AsyncResource` completes with the value, or with a `BiometricException` on failure (including `BiometricError.KEY_REVOKED` when biometrics have been re-enrolled since the entry was written). On the fallback base class this completes immediately with `BiometricError.NOT_AVAILABLE`.

  - ### set

    public AsyncResource<Boolean> set(String reason, String account, String value)
    Stores or overwrites a value for the given account. On iOS the user is typically not prompted (Apple's keychain accepts writes without re-authenticating); on Android the user is prompted because the underlying cipher requires biometric authentication. On the fallback base class this completes immediately with `BiometricError.NOT_AVAILABLE`.

  - ### remove

    public AsyncResource<Boolean> remove(String reason, String account)
    Removes a previously-stored entry. No authentication is required since deletion does not reveal the value. On the fallback base class this completes immediately with `BiometricError.NOT_AVAILABLE`.

  - ### setKeychainAccessGroup

    public void setKeychainAccessGroup(String group)

    Configures the iOS keychain access group for sharing entries between the main app and its extensions. The argument must include the Team ID prefix (e.g. `"ABCDE12345.group.com.example.app"`). Pass `null` or empty to clear. Ignored on non-iOS platforms and on the fallback base class.

    The `ios.keychainAccessGroup` build hint must declare the same group in the app's entitlements for this to work.