1{"version":3,"file":"SecureStore.js","sourceRoot":"","sources":["../src/SecureStore.ts"],"names":[],"mappings":"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","sourcesContent":["import ExpoSecureStore from './ExpoSecureStore';\n\nexport type KeychainAccessibilityConstant = number;\n\n// @needsAudit\n/**\n * The data in the keychain item cannot be accessed after a restart until the device has been\n * unlocked once by the user. This may be useful if you need to access the item when the phone\n * is locked.\n */\nexport const AFTER_FIRST_UNLOCK: KeychainAccessibilityConstant = ExpoSecureStore.AFTER_FIRST_UNLOCK;\n\n// @needsAudit\n/**\n * Similar to `AFTER_FIRST_UNLOCK`, except the entry is not migrated to a new device when restoring\n * from a backup.\n */\nexport const AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: KeychainAccessibilityConstant =\n  ExpoSecureStore.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY;\n\n// @needsAudit\n/**\n * The data in the keychain item can always be accessed regardless of whether the device is locked.\n * This is the least secure option.\n */\nexport const ALWAYS: KeychainAccessibilityConstant = ExpoSecureStore.ALWAYS;\n\n// @needsAudit\n/**\n * Similar to `WHEN_UNLOCKED_THIS_DEVICE_ONLY`, except the user must have set a passcode in order to\n * store an entry. If the user removes their passcode, the entry will be deleted.\n */\nexport const WHEN_PASSCODE_SET_THIS_DEVICE_ONLY: KeychainAccessibilityConstant =\n  ExpoSecureStore.WHEN_PASSCODE_SET_THIS_DEVICE_ONLY;\n\n// @needsAudit\n/**\n * Similar to `ALWAYS`, except the entry is not migrated to a new device when restoring from a backup.\n */\nexport const ALWAYS_THIS_DEVICE_ONLY: KeychainAccessibilityConstant =\n  ExpoSecureStore.ALWAYS_THIS_DEVICE_ONLY;\n\n// @needsAudit\n/**\n * The data in the keychain item can be accessed only while the device is unlocked by the user.\n */\nexport const WHEN_UNLOCKED: KeychainAccessibilityConstant = ExpoSecureStore.WHEN_UNLOCKED;\n\n// @needsAudit\n/**\n * Similar to `WHEN_UNLOCKED`, except the entry is not migrated to a new device when restoring from\n * a backup.\n */\nexport const WHEN_UNLOCKED_THIS_DEVICE_ONLY: KeychainAccessibilityConstant =\n  ExpoSecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY;\n\nconst VALUE_BYTES_LIMIT = 2048;\n\n// @needsAudit\nexport type SecureStoreOptions = {\n  /**\n   * - Android: Equivalent of the public/private key pair `Alias`.\n   * - iOS: The item's service, equivalent to [`kSecAttrService`](https://developer.apple.com/documentation/security/ksecattrservice/).\n   * > If the item is set with the `keychainService` option, it will be required to later fetch the value.\n   */\n  keychainService?: string;\n  /**\n   * Option responsible for enabling the usage of the user authentication methods available on the device while\n   * accessing data stored in SecureStore.\n   * - Android: Equivalent to [`setUserAuthenticationRequired(true)`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean))\n   *   (requires API 23).\n   * - iOS: Equivalent to [`kSecAccessControlBiometryCurrentSet`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/ksecaccesscontrolbiometrycurrentset/).\n   * Complete functionality is unlocked only with a freshly generated key - this would not work in tandem with the `keychainService`\n   * value used for the others non-authenticated operations.\n   *\n   * Warning: This option is not supported in Expo Go when biometric authentication is available due to a missing NSFaceIDUsageDescription.\n   * In release builds or when using continuous native generation, make sure to use the `expo-secure-store` config plugin.\n   *\n   */\n  requireAuthentication?: boolean;\n  /**\n   * Custom message displayed to the user while `requireAuthentication` option is turned on.\n   */\n  authenticationPrompt?: string;\n  /**\n   * Specifies when the stored entry is accessible, using iOS's `kSecAttrAccessible` property.\n   * @see Apple's documentation on [keychain item accessibility](https://developer.apple.com/documentation/security/ksecattraccessible/).\n   * @default SecureStore.WHEN_UNLOCKED\n   * @platform ios\n   */\n  keychainAccessible?: KeychainAccessibilityConstant;\n};\n\n// @needsAudit\n/**\n * Returns whether the SecureStore API is enabled on the current device. This does not check the app\n * permissions.\n *\n * @return Promise which fulfils witch `boolean`, indicating whether the SecureStore API is available\n * on the current device. Currently, this resolves `true` on Android and iOS only.\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n  return !!ExpoSecureStore.getValueWithKeyAsync;\n}\n\n// @needsAudit\n/**\n * Delete the value associated with the provided key.\n *\n * @param key The key that was used to store the associated value.\n * @param options An [`SecureStoreOptions`](#securestoreoptions) object.\n *\n * @return A promise that will reject if the value couldn't be deleted.\n */\nexport async function deleteItemAsync(\n  key: string,\n  options: SecureStoreOptions = {}\n): Promise<void> {\n  ensureValidKey(key);\n\n  await ExpoSecureStore.deleteValueWithKeyAsync(key, options);\n}\n\n// @needsAudit\n/**\n * Reads the stored value associated with the provided key.\n *\n * @param key The key that was used to store the associated value.\n * @param options An [`SecureStoreOptions`](#securestoreoptions) object.\n *\n * @return A promise that resolves to the previously stored value. It will return `null` if there is no entry\n * for the given key or if the key has been invalidated. It will reject if an error occurs while retrieving the value.\n *\n * > Keys are invalidated by the system when biometrics change, such as adding a new fingerprint or changing the face profile used for face recognition.\n * > After a key has been invalidated, it becomes impossible to read its value.\n * > This only applies to values stored with `requireAuthentication` set to `true`.\n */\nexport async function getItemAsync(\n  key: string,\n  options: SecureStoreOptions = {}\n): Promise<string | null> {\n  ensureValidKey(key);\n  return await ExpoSecureStore.getValueWithKeyAsync(key, options);\n}\n\n// @needsAudit\n/**\n * Stores a key–value pair.\n *\n * @param key The key to associate with the stored value. Keys may contain alphanumeric characters, `.`, `-`, and `_`.\n * @param value The value to store. Size limit is 2048 bytes.\n * @param options An [`SecureStoreOptions`](#securestoreoptions) object.\n *\n * @return A promise that will reject if value cannot be stored on the device.\n */\nexport async function setItemAsync(\n  key: string,\n  value: string,\n  options: SecureStoreOptions = {}\n): Promise<void> {\n  ensureValidKey(key);\n  if (!isValidValue(value)) {\n    throw new Error(\n      `Invalid value provided to SecureStore. Values must be strings; consider JSON-encoding your values if they are serializable.`\n    );\n  }\n\n  await ExpoSecureStore.setValueWithKeyAsync(value, key, options);\n}\n\n/**\n * Stores a key–value pair synchronously.\n * > **Note:** This function blocks the JavaScript thread, so the application may not be interactive when the `requireAuthentication` option is set to `true` until the user authenticates.\n *\n * @param key The key to associate with the stored value. Keys may contain alphanumeric characters, `.`, `-`, and `_`.\n * @param value The value to store. Size limit is 2048 bytes.\n * @param options An [`SecureStoreOptions`](#securestoreoptions) object.\n *\n */\nexport function setItem(key: string, value: string, options: SecureStoreOptions = {}): void {\n  ensureValidKey(key);\n  if (!isValidValue(value)) {\n    throw new Error(\n      `Invalid value provided to SecureStore. Values must be strings; consider JSON-encoding your values if they are serializable.`\n    );\n  }\n\n  return ExpoSecureStore.setValueWithKeySync(value, key, options);\n}\n\n/**\n * Synchronously reads the stored value associated with the provided key.\n * > **Note:** This function blocks the JavaScript thread, so the application may not be interactive when reading a value with `requireAuthentication`\n * > option set to `true` until the user authenticates.\n * @param key The key that was used to store the associated value.\n * @param options An [`SecureStoreOptions`](#securestoreoptions) object.\n *\n * @return Previously stored value. It will return `null` if there is no entry for the given key or if the key has been invalidated.\n */\nexport function getItem(key: string, options: SecureStoreOptions = {}): string | null {\n  ensureValidKey(key);\n  return ExpoSecureStore.getValueWithKeySync(key, options);\n}\n\nfunction ensureValidKey(key: string) {\n  if (!isValidKey(key)) {\n    throw new Error(\n      `Invalid key provided to SecureStore. Keys must not be empty and contain only alphanumeric characters, \".\", \"-\", and \"_\".`\n    );\n  }\n}\n\nfunction isValidKey(key: string) {\n  return typeof key === 'string' && /^[\\w.-]+$/.test(key);\n}\n\nfunction isValidValue(value: string) {\n  if (typeof value !== 'string') {\n    return false;\n  }\n  if (byteCount(value) > VALUE_BYTES_LIMIT) {\n    console.warn(\n      'Provided value to SecureStore is larger than 2048 bytes. An attempt to store such a value will throw an error in SDK 35.'\n    );\n  }\n  return true;\n}\n\n// copy-pasted from https://stackoverflow.com/a/39488643\nfunction byteCount(value: string) {\n  let bytes = 0;\n\n  for (let i = 0; i < value.length; i++) {\n    const codePoint = value.charCodeAt(i);\n\n    // Lone surrogates cannot be passed to encodeURI\n    if (codePoint >= 0xd800 && codePoint < 0xe000) {\n      if (codePoint < 0xdc00 && i + 1 < value.length) {\n        const next = value.charCodeAt(i + 1);\n\n        if (next >= 0xdc00 && next < 0xe000) {\n          bytes += 4;\n          i++;\n          continue;\n        }\n      }\n    }\n\n    bytes += codePoint < 0x80 ? 1 : codePoint < 0x800 ? 2 : 3;\n  }\n\n  return bytes;\n}\n"]}