Search by

wuninsu / nativephp-secure-storage

Wuninsu

Keep small secrets (such as API tokens) in the iOS Keychain or the Android Keystore from a NativePHP Mobile app.

Package info

github.com/Wuninsu/nativephp-secure-storage

Language:Kotlin

Type:nativephp-plugin

pkg:composer/wuninsu/nativephp-secure-storage

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-10-17 14:55 UTC

This package is auto-updated.

Last update: 2026-11-09 09:43:51 UTC


README

Latest Version License

Keep small secrets, such as an API token, in the iOS Keychain or the Android Keystore from a NativePHP Mobile v4 app.

  • iOS: Keychain generic-password items, readable only while the phone is unlocked, never synced to iCloud or included in backups (kSecAttrAccessibleWhenUnlockedThisDeviceOnly).
  • Android: AES-256-GCM, with the key held in the Android Keystore (hardware-backed where the phone has it). The ciphertext is stored in noBackupFilesDir, so it is never part of a backup.

Values stay on the device they were written on. They do not move to a new phone, and are gone after a reinstall.

Use it for small text values (a few KB at most).

Early release (0.x). The PHP side is covered by tests and the Android code compiles against NativePHP Mobile 4.6. Testing on real phones is in progress, so the API may still change before 1.0.

Requirements

  • PHP 8.3+
  • nativephp/mobile ^4.6
  • Android 8 (API 26) or newer, iOS 18.2 or newer

Install

composer require wuninsu/nativephp-secure-storage

NativePHP compiles only the plugins you register. If your app has no app/Providers/NativeServiceProvider.php yet, publish it first:

php artisan vendor:publish --tag=nativephp-plugins-provider

Then register the plugin and rebuild the native project:

php artisan native:plugin:register wuninsu/nativephp-secure-storage
php artisan native:install --force

Use

use Wuninsu\NativeSecureStorage\Facades\SecureStorage;

SecureStorage::set('api_token', $token);   // true on success
SecureStorage::get('api_token');           // string, or null
SecureStorage::delete('api_token');        // true, also when nothing was stored

get() returns null for every miss. When the reason matters, use read():

use Wuninsu\NativeSecureStorage\SecureStorageStatus;

$result = SecureStorage::read('api_token');

match ($result->status) {
    SecureStorageStatus::Found => $result->value,
    SecureStorageStatus::NotFound => null,       // nothing stored
    SecureStorageStatus::Unavailable => null,    // iOS: the phone is locked; try again later
    SecureStorageStatus::Failed => null,         // no plugin, no bridge, or a native error ($result->code)
};

Keys are 1 to 255 characters. A value that can no longer be decrypted (for example after the Keystore key was reset) is deleted and reads as not found.

Only on the phone

The plugin's native code exists only in a real build (php artisan native:run or a release). It is not in the NativePHP Jump app, and there is no bridge on a web server or in tests. Check before relying on it:

if (SecureStorage::isAvailable()) {
    // inside a built app that contains this plugin
}

Testing

Fake the bridge with NativePHP's FakeBridge:

use Native\Mobile\Testing\FakeBridge;

FakeBridge::enable()
    ->respondTo('WuninsuSecureStorage.Get', ['status' => 'found', 'value' => 'secret'])
    ->respondTo('WuninsuSecureStorage.Set', ['success' => true]);

Bridge functions

Function Parameters Returns
WuninsuSecureStorage.Get key {status: "found", value} or {status: "not_found"}
WuninsuSecureStorage.Set key, value {success: true}
WuninsuSecureStorage.Delete key {success: true}

Errors use NativePHP's envelope: {status: "error", code, message}. code is UNAVAILABLE when iOS refuses because the phone is locked, otherwise FAILED or INVALID_PARAMETERS.

License

MIT