migrateItem()
Moves one item of react-native-keychain or expo-secure-store, with the prompt when it is protected. For the items migrateFrom… skipped as requiresAuth, at a moment the user expects Face ID.
import { migrateItem } from '@apexnative/keychain/migrate';
migrateFromReactNativeKeychain and migrateFromExpoSecureStore never show a prompt, so they leave a protected item where it is and report it as requiresAuth. migrateItem moves one such item: it shows the prompt of the old item, writes the value into this package with the protection you give, and finishes the old item.
Usage
import { AccessControl, Accessible } from '@apexnative/keychain';
import { migrateItem } from '@apexnative/keychain/migrate';
// On the screen that used to unlock rnk's protected password with Face ID.
const report = await migrateItem(
{ library: 'reactNativeKeychain', service: 'auth' },
{
prompt: { title: 'Unlock your account' },
setOptions: {
accessible: Accessible.WhenUnlockedThisDeviceOnly,
accessControl: AccessControl.BiometryCurrentSet,
},
removeSource: true,
}
);
if (report.migrated.length === 1) {
// The password is now the credentials of createKeychain({ service: 'auth' }).
}
Signature
function migrateItem(item: MigrationItem, options?: MigrateItemOptions): Promise<MigrationReport>;
Promise<MigrationReport>PromptWhen the old item is protected: its own promptThrowsINVALID_ARGUMENT for an item or options that aren't valid. A canceled prompt, and any failure of the move, is in the reportPlatformsiOSAndroidParameters
| Parameter | Type | Description |
|---|---|---|
| itemRequired | MigrationItem | Which old item. { library: 'reactNativeKeychain', service? } for a generic password (without service: rnk's default), { library: 'reactNativeKeychain', server } for internet credentials, { library: 'expoSecureStore', key, keychainService? } for an item of expo-secure-store. See MigrationItem. |
| options | MigrateItemOptions | Where and how the new item is written. See below. |
| Option | Type | Description |
|---|---|---|
| prompt | Prompt | The texts of the prompt the old item shows. See Prompt. |
| setOptions | SetOptions | How the new item is written: accessible, accessControl, authValidity, synchronizable, android; no label. |
| into | Keychain | The storage that gets internet credentials and items of expo-secure-store. Default: `keychain`. A generic password goes to the storage of its service. |
| removeSource | boolean | Delete the old item once the new one is written; else mark it as moved. Default false. |
| accessGroup | string | iOS: look for the item in this access group only. |
Returns
A MigrationReport of the one item: its key in migrated, or in skipped with a reason.
Outcomes
| What happened | The report |
|---|---|
| Moved | migrated: [key] |
| The user canceled the prompt | skipped: [{ key, kind, reason: 'error', error }], error.code is USER_CANCELED |
| Another prompt outcome: a lockout, a failed scan | skipped with reason: 'error' and the prompt's code |
| No such item | skipped with reason: 'notFound' |
| The key is taken in this package | skipped with reason: 'exists', nothing overwritten |
A canceled prompt is no exception: the user can try again, and the old item is still there for the next call. An item that isn't protected moves without a prompt, as with migrateFrom….
import { KeychainErrorCode, isKeychainError } from '@apexnative/keychain/migrate';
const [skipped] = report.skipped;
if (skipped && isKeychainError(skipped.error, KeychainErrorCode.UserCanceled)) {
showPasswordForm(); // and offer the move again next time
}