Socket
Socket
Sign inDemoInstall

react-native-keychain

Package Overview
Dependencies
0
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.5 to 5.0.0

android/README.md

281

index.js
// @flow
import { NativeModules, Platform } from 'react-native';
const { RNKeychainManager } = NativeModules;

@@ -43,2 +44,14 @@

export const STORAGE_TYPE = Object.freeze({
FB: 'FacebookConceal',
AES: 'KeystoreAESCBC',
RSA: 'KeystoreRSAECB',
KC: 'keychain', // <~ iOS only
});
export const SECURITY_RULES = Object.freeze({
NONE: 'none',
AUTOMATIC_UPGRADE: 'automaticUpgradeToMoreSecuredStorage',
});
export type SecAccessible = $Values<typeof ACCESSIBLE>;

@@ -52,2 +65,8 @@

export type SecStorageType = $Values<typeof STORAGE_TYPE>;
export type SecSecurityRules = $Values<typeof SECURITY_RULES>;
export type SecBiometryType = $Values<typeof BIOMETRY_TYPE>;
export type Options = {

@@ -61,41 +80,88 @@ accessControl?: SecAccessControl,

securityLevel?: SecMinimumLevel,
storage?: SecStorageType,
rules?: SecSecurityRules,
};
export type Result = {|
+service: string,
+storage: string,
|};
export type UserCredentials = {|
+username: string,
+password: string,
...Result,
|};
export type SharedWebCredentials = {|
+server: string,
...UserCredentials,
|};
function normalizeOptions(serviceOrOptions?: string | Options): ?Options {
return typeof serviceOrOptions === 'string'
? { service: serviceOrOptions }
: serviceOrOptions;
}
//* EXPORTS */
/**
* (Android only) Returns guaranteed security level supported by this library
* on the current device.
* @return {Promise} Resolves to `SECURITY_LEVEL` when supported, otherwise `null`.
* Saves the `username` and `password` combination for `service`.
* @param {string} username Associated username or e-mail to be saved.
* @param {string} password Associated password to be saved.
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `{ service, storage }` when successful
*/
export function getSecurityLevel(): Promise<?($Values<typeof SECURITY_LEVEL>)> {
if (!RNKeychainManager.getSecurityLevel){
return Promise.resolve(null);
}
return RNKeychainManager.getSecurityLevel();
export function setGenericPassword(
username: string,
password: string,
serviceOrOptions?: string | Options
): Promise<false | Result> {
const options = normalizeOptions(serviceOrOptions);
return RNKeychainManager.setGenericPasswordForOptions(
options,
username,
password
);
}
/**
* Inquire if the type of local authentication policy (LAPolicy) is supported
* on this device with the device settings the user chose.
* @param {object} options LAPolicy option, iOS only
* @return {Promise} Resolves to `true` when supported, otherwise `false`
* Fetches login combination for `service`.
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `{ service, username, password, storage }` when successful
*/
export function canImplyAuthentication(options?: Options): Promise<boolean> {
if (!RNKeychainManager.canCheckAuthentication) {
return Promise.resolve(false);
}
return RNKeychainManager.canCheckAuthentication(options);
export function getGenericPassword(
serviceOrOptions?: string | Options
): Promise<false | SharedWebCredentials> {
const options = normalizeOptions(serviceOrOptions);
return RNKeychainManager.getGenericPasswordForOptions(options);
}
/**
* Get what type of hardware biometry support the device has.
* @return {Promise} Resolves to a `BIOMETRY_TYPE` when supported, otherwise `null`
* Deletes all generic password keychain entries for `service`.
* @param {object} options An Keychain options object.
* @return {Promise} Resolves to `true` when successful
*/
export function getSupportedBiometryType(): Promise<?($Values<typeof BIOMETRY_TYPE>)> {
if (!RNKeychainManager.getSupportedBiometryType) {
return Promise.resolve(null);
}
return RNKeychainManager.getSupportedBiometryType();
export function resetGenericPassword(
serviceOrOptions?: string | Options
): Promise<boolean> {
const options = normalizeOptions(serviceOrOptions);
return RNKeychainManager.resetGenericPasswordForOptions(options);
}
/**
* Checks if we have a login combination for `server`.
* @param {string} server URL to server.
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `{service, storage}` when successful
*/
export function hasInternetCredentials(
server: string,
options?: Options
): Promise<false | Result> {
return RNKeychainManager.hasInternetCredentialsForServer(server, options);
}
/**
* Saves the `username` and `password` combination for `server`.

@@ -105,4 +171,4 @@ * @param {string} server URL to server.

* @param {string} password Associated password to be saved.
* @param {object} options Keychain options, iOS only
* @return {Promise} Resolves to `true` when successful
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `{service, storage}` when successful
*/

@@ -114,3 +180,3 @@ export function setInternetCredentials(

options?: Options
): Promise<void> {
): Promise<false | Result> {
return RNKeychainManager.setInternetCredentialsForServer(

@@ -120,3 +186,2 @@ server,

password,
getMinimumSecurityLevel(options),
options

@@ -127,19 +192,5 @@ );

/**
* Checks if we have a login combination for `server`.
* @param {string} server URL to server.
* @return {Promise} Resolves to `true` when successful
*/
export function hasInternetCredentials(server: string): Promise<boolean> {
return RNKeychainManager.hasInternetCredentialsForServer(server);
}
export type UserCredentials = {|
+username: string,
+password: string,
|};
/**
* Fetches login combination for `server`.
* @param {string} server URL to server.
* @param {object} options Keychain options, iOS only
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `{ server, username, password }` when successful

@@ -160,83 +211,26 @@ */

*/
export function resetInternetCredentials(
server: string,
options?: Options
): Promise<void> {
return RNKeychainManager.resetInternetCredentialsForServer(server, options);
export function resetInternetCredentials(server: string): Promise<void> {
return RNKeychainManager.resetInternetCredentialsForServer(server);
}
function getOptionsArgument(serviceOrOptions?: string | Options) {
if (Platform.OS !== 'ios') {
return typeof serviceOrOptions === 'object'
? serviceOrOptions.service
: serviceOrOptions;
/**
* Get what type of hardware biometry support the device has.
* @param {object} options An Keychain options object.
* @return {Promise} Resolves to a `BIOMETRY_TYPE` when supported, otherwise `null`
*/
export function getSupportedBiometryType(): Promise<null | SecBiometryType> {
if (!RNKeychainManager.getSupportedBiometryType) {
return Promise.resolve(null);
}
return typeof serviceOrOptions === 'string'
? { service: serviceOrOptions }
: serviceOrOptions;
}
function getMinimumSecurityLevel(serviceOrOptions?: string | Options) {
var specifiedLevel = undefined;
if (typeof serviceOrOptions === 'object') {
specifiedLevel = serviceOrOptions.securityLevel;
if (Platform.OS === 'ios') {
return RNKeychainManager.getSupportedBiometryType();
}
return specifiedLevel || SECURITY_LEVEL.ANY;
return RNKeychainManager.getSupportedBiometryType();
}
/**
* Saves the `username` and `password` combination for `service`.
* @param {string} username Associated username or e-mail to be saved.
* @param {string} password Associated password to be saved.
* @param {string|object} serviceOrOptions Reverse domain name qualifier for the service, defaults to `bundleId` or an options object.
* @return {Promise} Resolves to `true` when successful
*/
export function setGenericPassword(
username: string,
password: string,
serviceOrOptions?: string | Options
): Promise<boolean> {
return RNKeychainManager.setGenericPasswordForOptions(
getOptionsArgument(serviceOrOptions),
username,
password,
getMinimumSecurityLevel(serviceOrOptions)
);
}
//* IOS ONLY */
export type SharedWebCredentials = {|
+server: string,
+username: string,
+password: string,
|};
/**
* Fetches login combination for `service`.
* @param {string|object} serviceOrOptions Reverse domain name qualifier for the service, defaults to `bundleId` or an options object.
* @return {Promise} Resolves to `{ service, username, password }` when successful
*/
export function getGenericPassword(
serviceOrOptions?: string | Options
): Promise<false | SharedWebCredentials> {
return RNKeychainManager.getGenericPasswordForOptions(
getOptionsArgument(serviceOrOptions)
);
}
/**
* Deletes all generic password keychain entries for `service`.
* @param {string|object} serviceOrOptions Reverse domain name qualifier for the service, defaults to `bundleId` or an options object.
* @return {Promise} Resolves to `true` when successful
*/
export function resetGenericPassword(
serviceOrOptions?: string | Options
): Promise<boolean> {
return RNKeychainManager.resetGenericPasswordForOptions(
getOptionsArgument(serviceOrOptions)
);
}
/**
* Asks the user for a shared web credential.

@@ -246,3 +240,5 @@ * @return {Promise} Resolves to `{ server, username, password }` if approved and

*/
export function requestSharedWebCredentials(): Promise<false | SharedWebCredentials> {
export function requestSharedWebCredentials(): Promise<
false | SharedWebCredentials
> {
if (Platform.OS !== 'ios') {

@@ -268,3 +264,3 @@ return Promise.reject(

username: string,
password: ?string
password?: string
): Promise<void> {

@@ -284,1 +280,54 @@ if (Platform.OS !== 'ios') {

}
/**
* Inquire if the type of local authentication policy (LAPolicy) is supported
* on this device with the device settings the user chose.
* @param {object} options LAPolicy option, iOS only
* @return {Promise} Resolves to `true` when supported, otherwise `false`
*/
export function canImplyAuthentication(options?: Options): Promise<boolean> {
if (!RNKeychainManager.canCheckAuthentication) {
return Promise.resolve(false);
}
return RNKeychainManager.canCheckAuthentication(options);
}
//* ANDROID ONLY */
/**
* (Android only) Returns guaranteed security level supported by this library
* on the current device.
* @param {object} options A keychain options object.
* @return {Promise} Resolves to `SECURITY_LEVEL` when supported, otherwise `null`.
*/
export function getSecurityLevel(
options?: Options
): Promise<null | SecMinimumLevel> {
if (!RNKeychainManager.getSecurityLevel) {
return Promise.resolve(null);
}
return RNKeychainManager.getSecurityLevel(options);
}
/** Refs: https://www.saltycrane.com/cheat-sheets/flow-type/latest/ */
export default {
SECURITY_LEVEL,
ACCESSIBLE,
ACCESS_CONTROL,
AUTHENTICATION_TYPE,
BIOMETRY_TYPE,
STORAGE_TYPE,
SECURITY_RULES,
getSecurityLevel,
canImplyAuthentication,
getSupportedBiometryType,
setInternetCredentials,
getInternetCredentials,
resetInternetCredentials,
setGenericPassword,
getGenericPassword,
resetGenericPassword,
requestSharedWebCredentials,
setSharedWebCredentials,
};
{
"name": "react-native-keychain",
"version": "4.0.5",
"version": "5.0.0",
"description": "Keychain Access for React Native",

@@ -44,5 +44,5 @@ "main": "index.js",

"devDependencies": {
"flow-bin": "0.78",
"react-native": "^0.57.4"
"flow-bin": "0.105.2",
"react-native": "^0.61.2"
}
}

@@ -1,9 +0,60 @@

<p align="center"><img src="https://user-images.githubusercontent.com/378279/36642269-6195b10c-1a3d-11e8-9e1b-37a3d1bcf7b3.png" align="center" width="150" height="201" alt="" /></p>
<h1 align="center">react-native-keychain</h1>
<p align="center"><img
src="https://user-images.githubusercontent.com/378279/36642269-6195b10c-1a3d-11e8-9e1b-37a3d1bcf7b3.png"
align="center" width="150" height="201" alt=""
/>
</p>
[![Travis](https://img.shields.io/travis/oblador/react-native-keychain.svg)](https://travis-ci.org/oblador/react-native-keychain) [![npm](https://img.shields.io/npm/v/react-native-keychain.svg)](https://npmjs.com/package/react-native-keychain) [![npm](https://img.shields.io/npm/dm/react-native-keychain.svg)](https://npmjs.com/package/react-native-keychain)
Keychain/Keystore Access for React Native.
# Keychain/Keystore Access for React Native
- [Keychain/Keystore Access for React Native](#keychainkeystore-access-for-react-native)
- [Installation](#installation)
- [Usage](#usage)
- [API](#api)
- [`setGenericPassword(username, password, [{ accessControl, accessible, accessGroup, service, securityLevel }])`](#setgenericpasswordusername-password--accesscontrol-accessible-accessgroup-service-securitylevel-)
- [`getGenericPassword([{ authenticationPrompt, service }])`](#getgenericpassword-authenticationprompt-service-)
- [`resetGenericPassword([{ service }])`](#resetgenericpassword-service-)
- [`setInternetCredentials(server, username, password, [{ accessControl, accessible, accessGroup, securityLevel }])`](#setinternetcredentialsserver-username-password--accesscontrol-accessible-accessgroup-securitylevel-)
- [`hasInternetCredentials(server, [{ authenticationPrompt }])`](#hasinternetcredentialsserver--authenticationprompt-)
- [`getInternetCredentials(server, [{ authenticationPrompt }])`](#getinternetcredentialsserver--authenticationprompt-)
- [`resetInternetCredentials(server, [{}])`](#resetinternetcredentialsserver-)
- [`requestSharedWebCredentials()` (iOS only)](#requestsharedwebcredentials-ios-only)
- [`setSharedWebCredentials(server, username, password)` (iOS only)](#setsharedwebcredentialsserver-username-password-ios-only)
- [`canImplyAuthentication([{ authenticationType }])` (iOS only)](#canimplyauthentication-authenticationtype--ios-only)
- [`getSupportedBiometryType([{}])`](#getsupportedbiometrytype)
- [`getSecurityLevel([{ accessControl }])` (Android only)](#getsecuritylevel-accesscontrol--android-only)
- [Options](#options)
- [Data Structure Properties/Fields](#data-structure-propertiesfields)
- [`Keychain.ACCESS_CONTROL` enum](#keychainaccess_control-enum)
- [`Keychain.ACCESSIBLE` enum](#keychainaccessible-enum)
- [`Keychain.AUTHENTICATION_TYPE` enum](#keychainauthentication_type-enum)
- [`Keychain.BIOMETRY_TYPE` enum](#keychainbiometry_type-enum)
- [`Keychain.SECURITY_LEVEL` enum (Android only)](#keychainsecurity_level-enum-android-only)
- [`Keychain.STORAGE_TYPE` enum (Android only)](#keychainstorage_type-enum-android-only)
- [`Keychain.RULES` enum (Android only)](#keychainrules-enum-android-only)
- [Important Behavior](#important-behavior)
- [Rule 1: Automatic Security Level Upgrade](#rule-1-automatic-security-level-upgrade)
- [Manual Installation](#manual-installation)
- [iOS](#ios)
- [Option: Manually](#option-manually)
- [Option: With CocoaPods](#option-with-cocoapods)
- [Enable `Keychain Sharing` entitlement for iOS 10+](#enable-keychain-sharing-entitlement-for-ios-10)
- [Android](#android)
- [Option: Manually](#option-manually-1)
- [Proguard Rules](#proguard-rules)
- [Unit Testing with Jest](#unit-testing-with-jest)
- [Using a Jest `__mocks__` Directory](#using-a-jest-mocks-directory)
- [Using a Jest Setup File](#using-a-jest-setup-file)
- [Notes](#notes)
- [Android Notes](#android-notes)
- [iOS Notes](#ios-notes)
- [macOS Catalyst](#macos-catalyst)
- [Security](#security)
- [Maintainers](#maintainers)
- [For Developers / Contributors](#for-developers--contributors)
- [License](#license)
## Installation

@@ -49,17 +100,19 @@

## API
### `setGenericPassword(username, password, [{ accessControl, accessible, accessGroup, service, securityLevel }])`
Will store the username/password combination in the secure storage. Resolves to `true` or rejects in case of an error.
Will store the username/password combination in the secure storage. Resolves to `{service, storage}` or rejects in case of an error. `storage` - is a name of used internal cipher for saving secret; `service` - name used for storing secret in internal storage (empty string resolved to valid default name).
### `getGenericPassword([{ authenticationPrompt, service }])`
Will retrieve the username/password combination from the secure storage. Resolves to `{ username, password }` if an entry exists or `false` if it doesn't. It will reject only if an unexpected error is encountered like lacking entitlements or permission.
Will retrieve the username/password combination from the secure storage. Resolves to `{ username, password, service, storage }` if an entry exists or `false` if it doesn't. It will reject only if an unexpected error is encountered like lacking entitlements or permission.
### `resetGenericPassword([{ service }])`
Will remove the username/password combination from the secure storage.
Will remove the username/password combination from the secure storage. Resolves to `true` in case of success.
### `setInternetCredentials(server, username, password, [{ accessControl, accessible, accessGroup, securityLevel }])`
Will store the server/username/password combination in the secure storage.
Will store the server/username/password combination in the secure storage. Resolves to `{ username, password, service, storage }`;

@@ -76,3 +129,3 @@ ### `hasInternetCredentials(server, [{ authenticationPrompt }])`

Will remove the server/username/password combination from the secure storage.
Will remove the server/username/password combination from the secure storage.

@@ -87,3 +140,3 @@ ### `requestSharedWebCredentials()` (iOS only)

### `canImplyAuthentication([{ authenticationType }])`
### `canImplyAuthentication([{ authenticationType }])` (iOS only)

@@ -94,67 +147,143 @@ Inquire if the type of local authentication policy is supported on this device with the device settings the user chose. Should be used in combination with `accessControl` option in the setter functions. Resolves to `true` if supported.

Get what type of hardware biometry support the device has. Resolves to a `Keychain.BIOMETRY_TYPE` value when supported, otherwise `null`.
Get what type of hardware biometry support the device has. Resolves to a `Keychain.BIOMETRY_TYPE` value when supported, otherwise `null`.
> This method returns `null`, if the device haven't enrolled into fingerprint/FaceId. Even though it has hardware for it.
### `getSecurityLevel()` (Android only)
### `getSecurityLevel([{ accessControl }])` (Android only)
Get security level that is supported on the current device with the current OS.
Get security level that is supported on the current device with the current OS. Resolves to `Keychain.SECURITY_LEVEL` enum value.
### Security Levels (Android only)
### Options
If set, `securityLevel` parameter specifies minimum security level that the encryption key storage should guarantee for storing credentials to succeed.
#### Data Structure Properties/Fields
* `ANY` - no security guarantees needed (default value); Credentials can be stored in FB Secure Storage;
* `SECURE_SOFTWARE` - requires for the key to be stored in the Android Keystore, separate from the encrypted data;
* `SECURE_HARDWARE` - requires for the key to be stored on a secure hardware (Trusted Execution Environment or Secure Environment). Read [this article](https://developer.android.com/training/articles/keystore#ExtractionPrevention) for more information.
| Key | Platform | Description | Default |
| -------------------------- | ------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ |
| **`accessControl`** | All | This dictates how a keychain item may be used, see possible values in `Keychain.ACCESS_CONTROL`. | *None* (iOS), `BIOMETRY_ANY` default for Android. |
| **`accessible`** | iOS only | This dictates when a keychain item is accessible, see possible values in `Keychain.ACCESSIBLE`. | *`Keychain.ACCESSIBLE.WHEN_UNLOCKED`* |
| **`accessGroup`** | iOS only | In which App Group to share the keychain. Requires additional setup with entitlements. | *None* |
| **`authenticationPrompt`** | iOS only | What to prompt the user when unlocking the keychain with biometry or device password. | `Authenticate to retrieve secret` |
| **`authenticationType`** | iOS only | Policies specifying which forms of authentication are acceptable. | `Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS` |
| **`service`** | All | Reverse domain name qualifier for the service associated with password. | *App bundle ID* |
| **`storage`** | Android only | Force specific cipher storage usage during saving the password | Select best available storage |
| **`rules`** | Android only | Force following to a specific security rules | Default: `Keychain.RULES.AUTOMATIC_UPGRADE` |
### Options
#### `Keychain.ACCESS_CONTROL` enum
| Key | Platform | Description | Default |
|---|---|---|---|
|**`accessControl`**|iOS only|This dictates how a keychain item may be used, see possible values in `Keychain.ACCESS_CONTROL`. |*None*|
|**`accessible`**|iOS only|This dictates when a keychain item is accessible, see possible values in `Keychain.ACCESSIBLE`. |*`Keychain.ACCESSIBLE.WHEN_UNLOCKED`*|
|**`accessGroup`**|iOS only|In which App Group to share the keychain. Requires additional setup with entitlements. |*None*|
|**`authenticationPrompt`**|iOS only|What to prompt the user when unlocking the keychain with biometry or device password. |`Authenticate to retrieve secret`|
|**`authenticationType`**|iOS only|Policies specifying which forms of authentication are acceptable. |`Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS`|
|**`service`**|All|Reverse domain name qualifier for the service associated with password. |*App bundle ID*|
| Key | Description |
| --------------------------------------------- | -------------------------------------------------------------------------------------- |
| **`USER_PRESENCE`** | Constraint to access an item with either Touch ID or passcode. |
| **`BIOMETRY_ANY`** | Constraint to access an item with Touch ID for any enrolled fingers. |
| **`BIOMETRY_CURRENT_SET`** | Constraint to access an item with Touch ID for currently enrolled fingers. |
| **`DEVICE_PASSCODE`** | Constraint to access an item with a passcode. |
| **`APPLICATION_PASSWORD`** | Constraint to use an application-provided password for data encryption key generation. |
| **`BIOMETRY_ANY_OR_DEVICE_PASSCODE`** | Constraint to access an item with Touch ID for any enrolled fingers or passcode. |
| **`BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE`** | Constraint to access an item with Touch ID for currently enrolled fingers or passcode. |
#### `Keychain.ACCESS_CONTROL` enum
> Note #1: `BIOMETRY_ANY`, `BIOMETRY_CURRENT_SET`, `BIOMETRY_ANY_OR_DEVICE_PASSCODE`, `BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE` - recognized by Android as a requirement for Biometric enabled storage (Till we got a better implementation);
>
> Note #2: For Android we support only two states: `Default` (use the best available secured storage) and `Fingerprint` (use only biometric protected storage);
| Key | Description |
|-----|-------------|
|**`USER_PRESENCE`**|Constraint to access an item with either Touch ID or passcode.|
|**`BIOMETRY_ANY`**|Constraint to access an item with Touch ID for any enrolled fingers.|
|**`BIOMETRY_CURRENT_SET`**|Constraint to access an item with Touch ID for currently enrolled fingers.|
|**`DEVICE_PASSCODE`**|Constraint to access an item with a passcode.|
|**`APPLICATION_PASSWORD`**|Constraint to use an application-provided password for data encryption key generation.|
|**`BIOMETRY_ANY_OR_DEVICE_PASSCODE`**|Constraint to access an item with Touch ID for any enrolled fingers or passcode.|
|**`BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE`**|Constraint to access an item with Touch ID for currently enrolled fingers or passcode.|
Refs:
- <https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc>
#### `Keychain.ACCESSIBLE` enum
| Key | Description |
|-----|-------------|
|**`WHEN_UNLOCKED`**|The data in the keychain item can be accessed only while the device is unlocked by the user.|
|**`AFTER_FIRST_UNLOCK`**|The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.|
|**`ALWAYS`**|The data in the keychain item can always be accessed regardless of whether the device is locked.|
|**`WHEN_PASSCODE_SET_THIS_DEVICE_ONLY`**|The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device. Items with this attribute never migrate to a new device.|
|**`WHEN_UNLOCKED_THIS_DEVICE_ONLY`**|The data in the keychain item can be accessed only while the device is unlocked by the user. Items with this attribute do not migrate to a new device.|
|**`AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY`**|The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user. Items with this attribute never migrate to a new device.|
|**`ALWAYS_THIS_DEVICE_ONLY`**|The data in the keychain item can always be accessed regardless of whether the device is locked. Items with this attribute never migrate to a new device.|
| Key | Description |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`WHEN_UNLOCKED`** | The data in the keychain item can be accessed only while the device is unlocked by the user. |
| **`AFTER_FIRST_UNLOCK`** | The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user. |
| **`ALWAYS`** | The data in the keychain item can always be accessed regardless of whether the device is locked. |
| **`WHEN_PASSCODE_SET_THIS_DEVICE_ONLY`** | The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device. Items with this attribute never migrate to a new device. |
| **`WHEN_UNLOCKED_THIS_DEVICE_ONLY`** | The data in the keychain item can be accessed only while the device is unlocked by the user. Items with this attribute do not migrate to a new device. |
| **`AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY`** | The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user. Items with this attribute never migrate to a new device. |
| **`ALWAYS_THIS_DEVICE_ONLY`** | The data in the keychain item can always be accessed regardless of whether the device is locked. Items with this attribute never migrate to a new device. |
Refs:
- <https://developer.apple.com/documentation/security/ksecattraccessiblewhenunlocked>
#### `Keychain.AUTHENTICATION_TYPE` enum
| Key | Description |
|-----|-------------|
|**`DEVICE_PASSCODE_OR_BIOMETRICS`**|Device owner is going to be authenticated by biometry or device passcode.|
|**`BIOMETRICS`**|Device owner is going to be authenticated using a biometric method (Touch ID or Face ID).|
| Key | Description |
| ----------------------------------- | ----------------------------------------------------------------------------------------- |
| **`DEVICE_PASSCODE_OR_BIOMETRICS`** | Device owner is going to be authenticated by biometry or device passcode. |
| **`BIOMETRICS`** | Device owner is going to be authenticated using a biometric method (Touch ID or Face ID). |
Refs:
- <https://developer.apple.com/documentation/localauthentication/lapolicy>
#### `Keychain.BIOMETRY_TYPE` enum
| Key | Description |
|-----|-------------|
|**`TOUCH_ID`**|Device supports authentication with Touch ID.|
|**`FACE_ID`**|Device supports authentication with Face ID.|
|**`FINGERPRINT`**|Device supports authentication with Android Fingerprint.|
| Key | Description |
| ----------------- | --------------------------------------------------------------- |
| **`TOUCH_ID`** | Device supports authentication with Touch ID. (iOS only) |
| **`FACE_ID`** | Device supports authentication with Face ID. (iOS only) |
| **`FINGERPRINT`** | Device supports authentication with Fingerprint. (Android only) |
Refs:
- <https://developer.apple.com/documentation/localauthentication/labiometrytype?language=objc>
#### `Keychain.SECURITY_LEVEL` enum (Android only)
If set, `securityLevel` parameter specifies minimum security level that the encryption key storage should guarantee for storing credentials to succeed.
| Key | Description |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ANY` | no security guarantees needed (default value); Credentials can be stored in FB Secure Storage; |
| `SECURE_SOFTWARE` | requires for the key to be stored in the Android Keystore, separate from the encrypted data; |
| `SECURE_HARDWARE` | requires for the key to be stored on a secure hardware (Trusted Execution Environment or Secure Environment). Read [this article](https://developer.android.com/training/articles/keystore#ExtractionPrevention) for more information. |
#### `Keychain.STORAGE_TYPE` enum (Android only)
| Key | Description |
| ----- | -------------------------------------- |
| `FB` | Facebook compatibility cipher |
| `AES` | Encryptions without human interaction. |
| `RSA` | Encryption with biometrics. |
#### `Keychain.RULES` enum (Android only)
| Key | Description |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NONE` | No rules. Be dummy, developer control everything |
| `AUTOMATIC_UPGRADE` | Upgrade secret to the best available storage as soon as it is available and user request secret extraction. Upgrade not applied till we request the secret. |
## Important Behavior
### Rule 1: Automatic Security Level Upgrade
As a rule library try to apply the best possible encryption and access method for storing secrets.
What does it mean in practical use case?
> Scenario #1: User has a new phone and run on it application with this module and store secret on device.
> Several days later user configured biometrics on the device and run application again. When user will try to access the secret, library will detect security enhancement and will upgrade secret storage to the best possible.
---
Q: What will happens if user disable/drop biometrics usage?
A: User will lost ability to extract secret from storage. On re-enable biometrics access to the secret will be possible to access again.
---
Q: Is it possible any automatic downgrading?
A: From security perspective any Automatic downgrading is treated as "a loss of the trust" point.
Developer should implement own logic to allow downgrade and deal with "security loss". _(My recommendation - never do that!)_
---
Q: How to disable automatic upgrade?
A: Do call `getGenericPassword({ ...otherProps, rules: "none" })` with extra property `rules` set to `none` string value.
---
Q: How to force a specific level of encryption during saving the secret?
A: Do call `setGenericPassword({ ...otherProps, storage: "AES" })` with forced storage.
> Note: attempt to force storage `RSA` when biometrics is not available will force code to reject call with errors specific to device biometric configuration state.
## Manual Installation

@@ -217,6 +346,6 @@

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.facebook.react:react-native:0.19.+'
+ compile project(':react-native-keychain')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:23.0.1'
implementation 'com.facebook.react:react-native:0.19.+'
+ implementation project(':react-native-keychain')
}

@@ -306,3 +435,3 @@ ```

### Android
### Android Notes

@@ -318,6 +447,11 @@ The module will automatically use the appropriate CipherStorage implementation based on API level:

### iOS
### iOS Notes
If you need Keychain Sharing in your iOS extension, make sure you use the same App Group and Keychain Sharing group names in your Main App and your Share Extension. To then share the keychain between the Main App and Share Extension, use the `accessGroup` and `service` option on `setGenericPassword` and `getGenericPassword`, like so: `getGenericPassword({ accessGroup: 'group.appname', service: 'com.example.appname' })`
Refs:
- <https://developer.apple.com/documentation/localauthentication>
- <https://developer.apple.com/documentation/security>
### macOS Catalyst

@@ -331,2 +465,8 @@

![Android Security Framework](https://source.android.com/security/images/authentication-flow.png)
* [Android authentication](https://source.android.com/security/authentication)
* [Android Cipher](https://developer.android.com/guide/topics/security/cryptography)
* [Android Protected Confirmation](https://developer.android.com/training/articles/security-android-protected-confirmation)
## Maintainers

@@ -340,6 +480,6 @@

<img width="150" height="150" src="https://github.com/oblador.png?v=3&s=150">
<br>
<br />
<strong>Joel Arvidsson</strong>
</a>
<br>
<br />
Author

@@ -350,6 +490,6 @@ </td>

<img width="150" height="150" src="https://github.com/vonovak.png?v=3&s=150">
</br>
<br />
<strong>Vojtech Novak</strong>
</a>
<br>
<br />
Maintainer

@@ -360,8 +500,17 @@ </td>

<img width="150" height="150" src="https://github.com/pcoltau.png?v=3&s=150">
</br>
<br />
<strong>Pelle Stenild Coltau</strong>
</a>
<br>
<br />
Maintainer
</td>
<td align="center">
<a href="https://github.com/OleksandrKucherenko">
<img width="150" height="150" src="https://github.com/OleksandrKucherenko.png?v=3&s=150">
<br />
<strong>Oleksandr Kucherenko</strong>
</a>
<br />
Contributor
</td>
</tr>

@@ -371,4 +520,8 @@ <tbody>

## For Developers / Contributors
- [How to Configure Android Studio for Development](android/README.md)
## License
MIT © Joel Arvidsson 2016-2018
MIT © Joel Arvidsson 2016-2020
declare module 'react-native-keychain' {
export interface Result {
service: string;
storage: string;
}
export interface UserCredentials {
username: string;
password: string;
}
export interface UserCredentials extends Result {
username: string;
password: string;
}
export interface SharedWebCredentials {
server: string;
username: string;
password: string;
}
export interface SharedWebCredentials extends UserCredentials {
server: string;
}
export enum ACCESSIBLE {
WHEN_UNLOCKED = "AccessibleWhenUnlocked",
AFTER_FIRST_UNLOCK = "AccessibleAfterFirstUnlock",
ALWAYS = "AccessibleAlways",
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY = "AccessibleWhenPasscodeSetThisDeviceOnly",
WHEN_UNLOCKED_THIS_DEVICE_ONLY = "AccessibleWhenUnlockedThisDeviceOnly",
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY = "AccessibleAfterFirstUnlockThisDeviceOnly",
ALWAYS_THIS_DEVICE_ONLY = "AccessibleAlwaysThisDeviceOnly"
}
export enum ACCESSIBLE {
WHEN_UNLOCKED = 'AccessibleWhenUnlocked',
AFTER_FIRST_UNLOCK = 'AccessibleAfterFirstUnlock',
ALWAYS = 'AccessibleAlways',
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY = 'AccessibleWhenPasscodeSetThisDeviceOnly',
WHEN_UNLOCKED_THIS_DEVICE_ONLY = 'AccessibleWhenUnlockedThisDeviceOnly',
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY = 'AccessibleAfterFirstUnlockThisDeviceOnly',
ALWAYS_THIS_DEVICE_ONLY = 'AccessibleAlwaysThisDeviceOnly',
}
export enum ACCESS_CONTROL {
USER_PRESENCE = "UserPresence",
BIOMETRY_ANY = "BiometryAny",
BIOMETRY_CURRENT_SET = "BiometryCurrentSet",
DEVICE_PASSCODE = "DevicePasscode",
APPLICATION_PASSWORD = "ApplicationPassword",
BIOMETRY_ANY_OR_DEVICE_PASSCODE = "BiometryAnyOrDevicePasscode",
BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE = "BiometryCurrentSetOrDevicePasscode"
}
export enum ACCESS_CONTROL {
USER_PRESENCE = 'UserPresence',
BIOMETRY_ANY = 'BiometryAny',
BIOMETRY_CURRENT_SET = 'BiometryCurrentSet',
DEVICE_PASSCODE = 'DevicePasscode',
APPLICATION_PASSWORD = 'ApplicationPassword',
BIOMETRY_ANY_OR_DEVICE_PASSCODE = 'BiometryAnyOrDevicePasscode',
BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE = 'BiometryCurrentSetOrDevicePasscode',
}
export enum AUTHENTICATION_TYPE {
DEVICE_PASSCODE_OR_BIOMETRICS = "AuthenticationWithBiometricsDevicePasscode",
BIOMETRICS = "AuthenticationWithBiometrics"
}
export enum AUTHENTICATION_TYPE {
DEVICE_PASSCODE_OR_BIOMETRICS = 'AuthenticationWithBiometricsDevicePasscode',
BIOMETRICS = 'AuthenticationWithBiometrics',
}
export enum SECURITY_LEVEL {
SECURE_SOFTWARE,
SECURE_HARDWARE,
ANY
}
export enum BIOMETRY_TYPE {
TOUCH_ID = 'TouchID',
FACE_ID = 'FaceID',
FINGERPRINT = 'Fingerprint'
}
export enum SECURITY_LEVEL {
SECURE_SOFTWARE,
SECURE_HARDWARE,
ANY,
}
export interface Options {
accessControl?: ACCESS_CONTROL;
accessGroup?: string;
accessible?: ACCESSIBLE;
authenticationPrompt?: string;
authenticationType?: AUTHENTICATION_TYPE;
service?: string;
securityLevel? : SECURITY_LEVEL;
}
export enum BIOMETRY_TYPE {
TOUCH_ID = 'TouchID',
FACE_ID = 'FaceID',
FINGERPRINT = 'Fingerprint',
}
function canImplyAuthentication(
options?: Options
): Promise<boolean>;
export enum STORAGE_TYPE {
FB = 'FacebookConceal',
AES = 'KeystoreAESCBC',
RSA = 'KeystoreRSAECB',
KC = 'keychain',
}
function getSupportedBiometryType(
): Promise<BIOMETRY_TYPE | null>;
export enum SECURITY_RULES {
NONE = 'none',
AUTOMATIC_UPGRADE = 'automaticUpgradeToMoreSecuredStorage',
}
function setInternetCredentials(
server: string,
username: string,
password: string,
options?: Options
): Promise<void>;
export interface Options {
accessControl?: ACCESS_CONTROL;
accessGroup?: string;
accessible?: ACCESSIBLE;
authenticationPrompt?: string;
authenticationType?: AUTHENTICATION_TYPE;
service?: string;
securityLevel?: SECURITY_LEVEL;
storage?: STORAGE_TYPE;
rules?: SECURITY_RULES;
}
function getInternetCredentials(
server: string
): Promise<false | UserCredentials>;
function setGenericPassword(
username: string,
password: string,
options?: Options
): Promise<false | Result>;
function hasInternetCredentials(
server: string
): Promise<boolean>;
function getGenericPassword(
options?: Options
): Promise<false | SharedWebCredentials>;
function resetInternetCredentials(
server: string
): Promise<void>;
function resetGenericPassword(options?: Options): Promise<boolean>;
function setGenericPassword(
username: string,
password: string,
options?: Options
): Promise<boolean>;
function hasInternetCredentials(
server: string,
options?: Options
): Promise<false | Result>;
function getGenericPassword(
options?: Options
): Promise<false | { service: string, username: string, password: string }>;
function setInternetCredentials(
server: string,
username: string,
password: string,
options?: Options
): Promise<false | Result>;
function resetGenericPassword(
options?: Options
): Promise<boolean>
function getInternetCredentials(
server: string,
options?: Options
): Promise<false | UserCredentials>;
function requestSharedWebCredentials(
): Promise<SharedWebCredentials>;
function resetInternetCredentials(
server: string,
options?: Options
): Promise<void>;
function setSharedWebCredentials(
server: string,
username: string,
password: string
): Promise<void>;
function getSupportedBiometryType(
options?: Options
): Promise<null | BIOMETRY_TYPE>;
function getSecurityLevel(
): Promise<SECURITY_LEVEL>
/** IOS ONLY */
function requestSharedWebCredentials(): Promise<false | SharedWebCredentials>;
function setSharedWebCredentials(
server: string,
username: string,
password?: string,
): Promise<void>;
function canImplyAuthentication(options?: Options): Promise<boolean>;
/** ANDROID ONLY */
function getSecurityLevel(options?: Options): Promise<null | SECURITY_LEVEL>;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc