Customizing Journey module storage in React Native
PingOne Advanced Identity Cloud PingAM React Native
Depending on the authentication use case, your application may need to store SSO session tokens, OAuth 2.0 access tokens, refresh tokens, or ID tokens.
The Orchestration SDK for React Native uses encrypted native storage on both Android and iOS by default, following identity best practices for each platform. For most applications, no additional configuration is required.
If you need to control specific aspects of how tokens are stored — such as the encryption key alias, the storage file name, or the caching behaviour — you can supply a custom storage configuration by using the @ping-identity/rn-storage package.
Installing the storage module
The storage module is provided as a separate package.
Install it alongside @ping-identity/rn-journey:
-
yarn
-
npm
yarn add @ping-identity/rn-storage
npm install @ping-identity/rn-storage
After installation, run pod install in your ios/ directory to link the native dependencies on iOS:
cd ios && pod install
Configuring storage
The storage module exposes helpers for the different types of storage that various modules in the Orchestration SDKs use:
configureSessionStorage()-
Registers a storage configuration for SSO session tokens. Used by the rn-journey module.
configureOidcStorage()-
Registers a storage configuration for OAuth 2.0 access, refresh, and ID tokens. Used by the rn-oidc and rn-journey modules.
configureBindingUserKeyStorage()-
Registers a storage configuration for binding user key metadata. Used by the rn-binding module.
configurePushStorage()-
Registers a storage configuration for push MFA notification credentials. Used by the rn-push module.
configureOathStorage()-
Registers a storage configuration for OATH one-time password credentials. Used by the rn-oath module.
Specify the handle of the create storage instances when configuring the various clients. For example, you could pass handles for both session and OIDC token storage in the config for your journey client, as follows:
import { createJourneyClient } from '@ping-identity/rn-journey';
import {
configureSessionStorage,
configureOidcStorage,
} from '@ping-identity/rn-storage';
const sessionStorage = configureSessionStorage({
android: {
keyAlias: 'com.example.app.session',
fileName: 'ping_session_store',
},
ios: {
account: 'com.example.app.session',
},
});
const oidcStorage = configureOidcStorage({
android: {
keyAlias: 'com.example.app.oidc',
fileName: 'ping_oidc_tokens',
},
ios: {
account: 'com.example.app.oidc',
encryptor: true,
},
});
const journeyClient = createJourneyClient({
serverUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am',
realm: 'alpha',
cookie: 'ch15fefc5407912',
modules: {
session: { storage: sessionStorage },
oidc: { storage: oidcStorage },
},
});
Configuring storage options
All helpers accept a StorageConfig object with platform-specific options nested under android or ios elements.
Options under each key are applied only on that platform and ignored on the other.
Android storage options
Android storage is backed by the encrypted Jetpack DataStore and uses the Android Keystore system.
| Property | Default | Description |
|---|---|---|
|
|
Alias used to identify the encryption key in the Android Keystore. You can use any value that does not clash with any other key names. A common pattern is For example, |
|
|
Name of the file where persistent data is stored. Use a distinct name for each storage instance to avoid data conflicts. |
|
|
When Falls back to the standard Keystore if StrongBox is not available on the device. |
|
|
Controls in-memory caching of storage reads. |
Configuring cache strategy on Android
The cacheStrategy option controls how the Android storage layer handles in-memory caching.
|
Data held in a cache is kept in plain text and is not encrypted. A device that can output a memory dump may expose sensitive information, such as access or ID tokens. |
| Value | Description |
|---|---|
|
Default. No in-memory caching. All reads and writes go directly to persistent encrypted storage. Use for sensitive data that must not remain in memory. |
|
Caches data in memory only when a storage operation fails. Provides a fallback for transient storage interruptions. |
|
Always caches data in memory. Reduces disk I/O for frequently accessed data. |
import { configureSessionStorage, CacheStrategy } from '@ping-identity/rn-storage';
const sessionStorage = configureSessionStorage({
android: {
keyAlias: 'com.example.app.session',
fileName: 'ping_session_store',
cacheStrategy: CacheStrategy.CACHE_ON_FAILURE,
},
});
iOS storage options
iOS storage is backed by the device Keychain.
| Property | Default | Description |
|---|---|---|
|
|
Keychain account name used to group items in the Keychain. Typically uses reverse domain notation, for example |
|
|
When Set to |
|
Platform default |
Controls whether the SDK falls back to an in-memory cache when Keychain access is unavailable. |
Configuring OATH storage options on iOS
configureOathStorage() accepts an additional iosOath element for iOS-specific OATH credential security options.
These are separate from the common ios options and are ignored on Android.
| Property | Description |
|---|---|
|
Keychain service name used to identify and group OATH credentials in the Keychain. |
|
When |
|
When |
|
Custom prompt text displayed in the biometric authentication dialog when accessing OATH credentials. |
|
Keychain access group identifier for sharing OATH credentials across app extensions. |
Error handling
Both configureSessionStorage() and configureOidcStorage() throw a StorageError if the configuration is invalid or if native storage registration fails.
StorageError extends PingError, which in turn extends Error, and includes a code and type property for programmatic handling.
import { configureSessionStorage, StorageError } from '@ping-identity/rn-storage';
try {
const sessionStorage = configureSessionStorage({
android: {
keyAlias: 'com.example.app.session',
fileName: 'ping_session_store',
},
});
} catch (err) {
if (err instanceof StorageError) {
console.error(err.code, err.type, err.message);
}
}