Encryption¶
Lokksmith encrypts its persisted state at rest. Everything it stores for a client — access and
refresh tokens, nonces and in-flight auth-flow state — is encrypted before it is written to disk (or
localStorage on the Web), so tokens are never persisted in clear text.
This is on by default and requires no configuration:
The state is encrypted with AES-256-GCM, and the key protecting it is kept in the platform's secure
storage: the Android Keystore, the iOS Keychain, an owner-only key file on Desktop, and
localStorage on the Web. How strong that protection is therefore differs per platform — on Android
it is hardware-backed where the device supports it, while on Desktop it comes down to the operating
system's file permissions.
Web
On the Web the key is stored in localStorage, which is readable by any script on the same
origin. Encryption there therefore provides obfuscation rather than strong protection and does
not defend against cross-site scripting (XSS): a script that can read the encrypted state can
also read the key. Apply a strong Content Security Policy and the usual XSS defenses. Persisting
a non-extractable WebCrypto key in
IndexedDB is the intended future hardening.
Upgrading from an older version
State previously written as plaintext is migrated automatically on first access. There is no manual step and users stay signed in.
Disabling encryption¶
Set encryptionEnabled = false in the options passed to createLokksmith(...). State is then stored
as plaintext JSON and no platform key material is created:
Turning encryption off discards existing state
Encrypted state cannot be read in plaintext mode. It is treated as absent, so the affected client is re-created and the user has to authenticate again. Turning encryption on is a migration and does not lose state; turning it off is not.
Android: excluding the files from backups¶
On Android, Lokksmith keeps two files in the application's filesDir:
| File | Contents |
|---|---|
lokksmith_clients.preferences_pb |
the encrypted client state |
lokksmith_clients.key.preferences_pb |
the encrypted data-encryption key |
Both are covered by Auto Backup unless you exclude them. The key that protects them lives in the Android Keystore and is non-exportable, so it is never part of a backup: on a new device the restored files can never be decrypted. Lokksmith handles that gracefully — unreadable state is treated as absent, the client is re-created and the user authenticates again — but backing the files up in the first place serves no purpose.
To exclude them, add two resource files:
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="file" path="lokksmith_clients.preferences_pb" />
<exclude domain="file" path="lokksmith_clients.key.preferences_pb" />
</full-backup-content>
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<exclude domain="file" path="lokksmith_clients.preferences_pb" />
<exclude domain="file" path="lokksmith_clients.key.preferences_pb" />
</cloud-backup>
<device-transfer>
<exclude domain="file" path="lokksmith_clients.preferences_pb" />
<exclude domain="file" path="lokksmith_clients.key.preferences_pb" />
</device-transfer>
</data-extraction-rules>
and reference them from your application's manifest:
<application
android:fullBackupContent="@xml/backup_rules"
android:dataExtractionRules="@xml/data_extraction_rules">
Both attributes are needed: fullBackupContent applies up to Android 11 (API 30),
dataExtractionRules from Android 12 (API 31) on. Excluding device-transfer as well costs
nothing, since the Keystore key does not transfer to the new device either.
Note
Lokksmith cannot ship these rules itself: both are single-valued <application> attributes that
point at exactly one file for the whole application, so a library declaring them would either
override your own backup rules or break the manifest merge.
If you changed Lokksmith.Options.persistenceFileBaseName, adjust the paths accordingly — they
are <base-name>.preferences_pb and <base-name>.key.preferences_pb.