### Install iOS Pods Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Installs CocoaPods dependencies for the iOS example app. ```bash pod install --project-directory=ios ``` -------------------------------- ### Development Setup Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Prerequisites, setup instructions, example app usage, and E2E testing for react-native-keychain. ```APIDOC ## Development ### Prerequisites - Node.js >= 16 - Yarn 3.6.1 (uses workspaces) - Xcode (for iOS) - Android SDK with API 23+ (for Android) - CocoaPods (for iOS) ### Setup ```bash # Install dependencies (all workspaces) yarn install # Build the library (TypeScript → lib/) yarn prepare # Run typecheck yarn typecheck # Run linter yarn lint # Format code yarn format ``` ### Example App ```bash cd KeychainExample # iOS pod install --project-directory=ios yarn start # Metro bundler # Build & run via Xcode or react-native run-ios # Android yarn start # Metro bundler # Build & run via Android Studio or react-native run-android ``` ### Running E2E Tests Tests use **Detox** with physical emulator/simulator: ```bash cd KeychainExample # iOS yarn test:ios # Builds + runs Detox tests # Android yarn test:android # Builds + runs Detox tests ``` Test specs are in `KeychainExample/e2e/testCases/`. They cover: - Access control (passcode, biometric) for both credential types - Storage types (AES-CBC, AES-GCM, AES-GCM-NO-AUTH, RSA) — Android only - Security levels (Any, Software, Hardware) — Android only E2E tests use biometric simulation: `device.matchFace()` on iOS, ADB fingerprint touch on Android. Passcode on Android is `1111`. ### Build Output `yarn prepare` (via react-native-builder-bob) generates: - `lib/commonjs/` — CommonJS modules (with ESM interop) - `lib/module/` — ES modules - `lib/typescript/` — Type declarations ``` -------------------------------- ### Start Metro Bundler Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Starts the Metro bundler for the React Native example app. ```bash yarn start ``` -------------------------------- ### Install react-native-keychain with npm Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/index.md Use this command to install the library using npm. Ensure you have Node.js and npm installed. ```bash npm install react-native-keychain ``` -------------------------------- ### Install react-native-keychain with Yarn Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/index.md Use this command to install the library using Yarn. Ensure you have Node.js and Yarn installed. ```bash yarn add react-native-keychain ``` -------------------------------- ### Configure Jest Setup File Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/jest.md Add a reference to a setup file in your Jest configuration to mock react-native-keychain. Ensure the path to the setup file is correct. ```javascript module.exports = { // ... other configurations ... setupFiles: ['/jest.setup.js'], }; ``` -------------------------------- ### Install react-native-keychain with pnpm Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/index.md Use this command to install the library using pnpm. Ensure you have Node.js and pnpm installed. ```bash pnpm add react-native-keychain ``` -------------------------------- ### Install Dependencies Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Installs all project dependencies across workspaces using Yarn. ```bash yarn install ``` -------------------------------- ### Mock react-native-keychain in Jest Setup Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/jest.md In your Jest setup file, mock the 'react-native-keychain' module to use a custom mock implementation. Ensure the path to your mock file is correct relative to the setup file. ```typescript // jest.setup.js import keychainMock from './path/to/keychainMock'; jest.mock('react-native-keychain', () => keychainMock); ``` -------------------------------- ### Unit Test Keychain Operations Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/jest.md Example unit tests for functions interacting with react-native-keychain. These tests mock the keychain operations to ensure predictable behavior without calling native code. ```typescript import Keychain from 'react-native-keychain'; describe('Keychain Manager', () => { it('should save and retrieve credentials', async () => { // Mock saving credentials await Keychain.setGenericPassword('testUser', 'testPassword'); expect(Keychain.setGenericPassword).toHaveBeenCalledWith( 'testUser', 'testPassword' ); // Mock retrieving credentials const credentials = await Keychain.getGenericPassword(); expect(credentials).toEqual({ username: 'mockUser', password: 'mockPassword', service: 'mockService', storage: 'mockStorage', }); }); it('should check if a password exists', async () => { const exists = await Keychain.hasGenericPassword(); expect(exists).toBe(true); }); it('should reset credentials', async () => { const reset = await Keychain.resetGenericPassword(); expect(reset).toBe(true); }); it('should get supported biometry type', async () => { const biometryType = await Keychain.getSupportedBiometryType(); expect(biometryType).toBe('MOCK_TouchID'); }); }); ``` -------------------------------- ### Build Library Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Builds the TypeScript library into distributable formats. ```bash yarn prepare ``` -------------------------------- ### CI/CD Pipelines Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Overview of the CI/CD workflows for testing, documentation generation, and deployment. ```APIDOC ## CI/CD Pipelines | Workflow | Trigger | What it does | |----------|---------|-------------| | `e2e_tests.yaml` | Push/PR to master | Builds APKs + iOS app, runs Detox E2E tests on Android API 33/34/35 emulators and iOS simulator | | `lint_and_types.yaml` | Push/PR to master | Runs ESLint + TypeScript typecheck | | `docs.yaml` | Release created | Builds Docusaurus site, deploys to GitHub Pages | | `deploy.yaml` | Release created | Builds library via bob, publishes to NPM | ``` -------------------------------- ### Coding Conventions Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Guidelines for TypeScript, Android, iOS development, formatting, linting, and option normalization. ```APIDOC ## Coding Conventions - **TypeScript**: Strict mode, no unused locals/parameters, `verbatimModuleSyntax`, ESNext target - **Android**: Kotlin with coroutines, Java 17 compatibility, AndroidX libraries - **iOS**: Objective-C++ (.mm files), supports both TurboModule and Bridge - **Formatting**: Prettier for JS/TS/JSON/MD files - **Linting**: ESLint with `@react-native/eslint-config` - **Option normalization**: All public functions normalize options through `normalizeAuthPrompt()` which sets default `title` and `cancel` for auth prompts ``` -------------------------------- ### Run E2E Tests on Android Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Builds and runs End-to-End tests for the Android platform using Detox. ```bash yarn test:android ``` -------------------------------- ### Run E2E Tests on iOS Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Builds and runs End-to-End tests for the iOS platform using Detox. ```bash yarn test:ios ``` -------------------------------- ### Store, Retrieve, and Reset Credentials Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/usage.md Use `setGenericPassword` to store credentials, `getGenericPassword` to retrieve them, and `resetGenericPassword` to remove them. Specify a `service` key to manage distinct sets of credentials. Ensure that only string values are stored; use `JSON.stringify` and `JSON.parse` for objects. ```tsx import * as Keychain from 'react-native-keychain'; async () => { const username = 'zuck'; const password = 'poniesRgr8'; // Store the credentials await Keychain.setGenericPassword(username, password, {service: 'service_key'}); try { // Retrieve the credentials const credentials = await Keychain.getGenericPassword({service: 'service_key'}); if (credentials) { console.log( 'Credentials successfully loaded for user ' + credentials.username ); } else { console.log('No credentials stored'); } } catch (error) { console.error("Failed to access Keychain", error); } // Reset the stored credentials await Keychain.resetGenericPassword({service: 'service_key'}); }; ``` -------------------------------- ### Lint Code Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Runs the linter to enforce code style and catch potential issues. ```bash yarn lint ``` -------------------------------- ### Mocking react-native-keychain with Jest __mocks__ Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/jest.md This approach mocks the entire `react-native-keychain` module for all tests by placing the mock in the `__mocks__` directory. Ensure the mock object structure matches the actual module. ```typescript // index.ts or index.js inside __mocks__/react-native-keychain const keychainMock = { SECURITY_LEVEL: { SECURE_SOFTWARE: 'MOCK_SECURITY_LEVEL_SECURE_SOFTWARE', SECURE_HARDWARE: 'MOCK_SECURITY_LEVEL_SECURE_HARDWARE', ANY: 'MOCK_SECURITY_LEVEL_ANY', }, // ... rest of the keychainMock object ... // (Copy the entire keychainMock object from above) }; module.exports = keychainMock; ``` -------------------------------- ### Format Code Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Formats code according to Prettier standards. ```bash yarn format ``` -------------------------------- ### Mocking Keychain Module for Jest Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/jest.md This mock object should replicate the structure of the actual module, including enums and functions. It uses `jest.fn()` to mock module methods. ```typescript // keychainMock.ts or keychainMock.js const keychainMock = { SECURITY_LEVEL: { SECURE_SOFTWARE: 'MOCK_SECURITY_LEVEL_SECURE_SOFTWARE', SECURE_HARDWARE: 'MOCK_SECURITY_LEVEL_SECURE_HARDWARE', ANY: 'MOCK_SECURITY_LEVEL_ANY', }, ACCESSIBLE: { WHEN_UNLOCKED: 'MOCK_AccessibleWhenUnlocked', AFTER_FIRST_UNLOCK: 'MOCK_AccessibleAfterFirstUnlock', ALWAYS: 'MOCK_AccessibleAlways', WHEN_PASSCODE_SET_THIS_DEVICE_ONLY: 'MOCK_AccessibleWhenPasscodeSetThisDeviceOnly', WHEN_UNLOCKED_THIS_DEVICE_ONLY: 'MOCK_AccessibleWhenUnlockedThisDeviceOnly', AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: 'MOCK_AccessibleAfterFirstUnlockThisDeviceOnly', }, ACCESS_CONTROL: { USER_PRESENCE: 'MOCK_UserPresence', BIOMETRY_ANY: 'MOCK_BiometryAny', BIOMETRY_CURRENT_SET: 'MOCK_BiometryCurrentSet', DEVICE_PASSCODE: 'MOCK_DevicePasscode', APPLICATION_PASSWORD: 'MOCK_ApplicationPassword', BIOMETRY_ANY_OR_DEVICE_PASSCODE: 'MOCK_BiometryAnyOrDevicePasscode', BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE: 'MOCK_BiometryCurrentSetOrDevicePasscode', }, AUTHENTICATION_TYPE: { DEVICE_PASSCODE_OR_BIOMETRICS: 'MOCK_AuthenticationWithBiometricsDevicePasscode', BIOMETRICS: 'MOCK_AuthenticationWithBiometrics', }, STORAGE_TYPE: { FB: 'MOCK_FacebookConceal', AES: 'MOCK_KeystoreAESCBC', RSA: 'MOCK_KeystoreRSAECB', KC: 'MOCK_keychain', }, setGenericPassword: jest.fn().mockResolvedValue({ service: 'mockService', storage: 'mockStorage', }), getGenericPassword: jest.fn().mockResolvedValue({ username: 'mockUser', password: 'mockPassword', service: 'mockService', storage: 'mockStorage', }), resetGenericPassword: jest.fn().mockResolvedValue(true), hasGenericPassword: jest.fn().mockResolvedValue(true), getAllGenericPasswordServices: jest.fn() .mockResolvedValue(['mockService1', 'mockService2']), setInternetCredentials: jest.fn().mockResolvedValue({ service: 'mockService', storage: 'mockStorage', }), getInternetCredentials: jest.fn().mockResolvedValue({ username: 'mockUser', password: 'mockPassword', service: 'mockService', storage: 'mockStorage', }), resetInternetCredentials: jest.fn().mockResolvedValue(), getSupportedBiometryType: jest.fn().mockResolvedValue('MOCK_TouchID'), canImplyAuthentication: jest.fn().mockResolvedValue(true), getSecurityLevel: jest.fn().mockResolvedValue('MOCK_SECURE_SOFTWARE'), isPasscodeAuthAvailable: jest.fn().mockResolvedValue(true) }; export default keychainMock; ``` -------------------------------- ### Key Types Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md TypeScript types defining the structure of options and results for keychain operations. ```APIDOC ## Key Types - **`SetOptions`**: `accessible`, `securityLevel`, `storage`, `accessControl`, `authenticationPrompt`, `service`, `cloudSync`, `accessGroup` - **`GetOptions`**: `accessControl`, `authenticationPrompt`, `service` - **`BaseOptions`**: `service`, `server`, `cloudSync`, `accessGroup` - **`Result`**: `{ service, storage }` - **`UserCredentials`**: `{ username, password, service, storage }` - **`AuthenticationPrompt`**: `{ title?, subtitle?, description?, cancel? }` ``` -------------------------------- ### Check for Stored Data in Keychain/Keystore Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/data-persistence.md Use `hasGenericPassword` or `hasInternetCredentials` to check if data exists before attempting to retrieve it. Ensure the correct service or server is specified. ```typescript import Keychain from 'react-native-keychain'; const isGenericPasswordAvailable = await Keychain.hasGenericPassword({ service: 'service_key' }); const isInternetCredentialAvailable = await Keychain.hasInternetCredentials({ server: 'https://google.com' }); ``` -------------------------------- ### Key Enums Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Enumerations used for configuring keychain item accessibility, access control, authentication types, security levels, storage types, biometry types, and error codes. ```APIDOC ## Key Enums - **`ACCESSIBLE`**: When keychain items are accessible (e.g., `WHEN_UNLOCKED`, `AFTER_FIRST_UNLOCK`) - **`ACCESS_CONTROL`**: Auth gates (e.g., `BIOMETRY_ANY`, `DEVICE_PASSCODE`, `BIOMETRY_ANY_OR_DEVICE_PASSCODE`) - **`AUTHENTICATION_TYPE`**: Biometrics vs passcode authentication - **`SECURITY_LEVEL`**: Android security level (`ANY`, `SECURE_SOFTWARE`, `SECURE_HARDWARE`) - **`STORAGE_TYPE`**: Android cipher type (`AES_GCM`, `AES_GCM_NO_AUTH`, `RSA`, `AES_CBC`) - **`BIOMETRY_TYPE`**: Device biometry (`TOUCH_ID`, `FACE_ID`, `OPTIC_ID`, `FINGERPRINT`, `FACE`, `IRIS`) - **`ERROR_CODE`**: Standardized error codes (`PASSCODE_NOT_SET`, `BIOMETRIC_NOT_ENROLLED`, etc.) ``` -------------------------------- ### Public API Functions Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Functions for managing generic and internet credentials, checking availability, and retrieving security information. ```APIDOC ## Public API Functions All functions are exported from `src/index.ts`. ### Store Generic Password - **Function**: `setGenericPassword(username, password, options?)` - **Description**: Store credentials by service. ### Retrieve Generic Password - **Function**: `getGenericPassword(options?)` - **Description**: Retrieve credentials by service. ### Check Generic Password Existence - **Function**: `hasGenericPassword(options?)` - **Description**: Check if credentials exist. ### Reset Generic Password - **Function**: `resetGenericPassword(options?)` - **Description**: Delete credentials by service. ### List All Generic Password Services - **Function**: `getAllGenericPasswordServices(options?)` - **Description**: List all service keys. ### Store Internet Credentials - **Function**: `setInternetCredentials(server, username, password, options?)` - **Description**: Store credentials by server URL. ### Retrieve Internet Credentials - **Function**: `getInternetCredentials(server, options?)` - **Description**: Retrieve credentials by server. ### Check Internet Credentials Existence - **Function**: `hasInternetCredentials(options)` - **Description**: Check if internet credentials exist. ### Reset Internet Credentials - **Function**: `resetInternetCredentials(options)` - **Description**: Delete internet credentials. ### Get Supported Biometry Type - **Function**: `getSupportedBiometryType()` - **Description**: Get device biometry type. ### Check Authentication Policy Support (iOS) - **Function**: `canImplyAuthentication(options?)` - **Description**: Check auth policy support (iOS). ### Get Security Level (Android) - **Function**: `getSecurityLevel(options?)` - **Description**: Get security level (Android). ### Check Passcode Authentication Availability - **Function**: `isPasscodeAuthAvailable()` - **Description**: Check passcode auth availability. ### Request Shared Web Credentials (iOS) - **Function**: `requestSharedWebCredentials()` - **Description**: Get Safari shared credentials (iOS). ### Set Shared Web Credentials (iOS) - **Function**: `setSharedWebCredentials(server, username, password?)` - **Description**: Set Safari shared credentials (iOS). ``` -------------------------------- ### Typecheck Code Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md Runs the TypeScript type checker to ensure code quality. ```bash yarn typecheck ``` -------------------------------- ### iOS Keychain Behavior Modification Source: https://github.com/oblador/react-native-keychain/blob/master/AGENTS.md When modifying iOS keychain behavior, ensure platform-specific code is guarded using TARGET_OS_IOS, TARGET_OS_VISION, or TARGET_OS_UIKITFORMAC macros. Map any new error domains to standardized ERROR_CODE values. ```objective-c #import #import #if TARGET_OS_IOS || TARGET_OS_VISION || TARGET_OS_UIKITFORMAC // iOS specific code here #endif ``` -------------------------------- ### Force Specific Encryption Level Source: https://github.com/oblador/react-native-keychain/blob/master/website/docs/faq.md To force a specific encryption level when saving a secret, use the 'storage' option. Note that attempting to force RSA storage without available biometrics will result in an error. ```tsx setGenericPassword({ ...otherProps, storage: "AES_GCM_NO_AUTH" }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.