npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ping-identity/rn-journey

v1.0.0

Published

Ping Identity Journey for React Native

Downloads

266

Readme

Ping Identity

Ping Identity React Native Journey

This module exposes native-backed Journey clients for Android and iOS.

Integrating the SDK into your project

Note: This module requires that the @ping-identity/rn-core module is already set up and installed.

# Install & setup the core module
yarn add @ping-identity/rn-core
# Install the rn-journey module
yarn add @ping-identity/rn-journey
# If you are developing your app using iOS, run this command
cd ios && pod install

Optional integration packages:

yarn add @ping-identity/rn-storage
yarn add @ping-identity/rn-logger

How to Use the SDK

Step 1: Create a minimal client

Use this baseline configuration first.

import { createJourneyClient } from '@ping-identity/rn-journey';

const client = createJourneyClient({
  serverUrl: 'https://example.com/am',
  realm: 'alpha',
  cookie: 'iPlanetDirectoryPro',
  timeout: 30000,
});

Step 2: Add OIDC module (with optional storage)

Add modules.oidc when your Journey flow needs OIDC token/session operations (for example user(), refresh(), userinfo(), and revoke()).

Storage inside modules.oidc.storage and modules.session.storage is optional. Configure it only if you need native-backed persistence; otherwise omit storage values.

import { createJourneyClient } from '@ping-identity/rn-journey';
import {
  CacheStrategy,
  configureOidcStorage,
  configureSessionStorage,
} from '@ping-identity/rn-storage';

const sessionStorage = configureSessionStorage({
  android: {
    fileName: 'journey-session',
    keyAlias: 'journey-session',
    strongBoxPreferred: true,
    cacheStrategy: 'cache_on_failure',
  },
  ios: {
    account: 'com.example.app.session',
    encryptor: true,
    cacheable: false,
  },
});

const oidcStorage = configureOidcStorage({
  android: {
    fileName: 'journey-oidc',
    keyAlias: 'journey-oidc',
    strongBoxPreferred: true,
    cacheStrategy: CacheStrategy.CACHE_ON_FAILURE,
  },
  ios: {
    account: 'com.example.app.oidc',
    encryptor: true,
    cacheable: false,
  },
});

const client = createJourneyClient({
  serverUrl: 'https://example.com/am',
  realm: 'alpha',
  cookie: 'iPlanetDirectoryPro',
  timeout: 30000,
  modules: {
    oidc: {
      clientId: 'rn-client',
      discoveryEndpoint:
        'https://example.com/am/oauth2/alpha/.well-known/openid-configuration',
      redirectUri: 'com.example.app://callback',
      scopes: ['openid', 'profile', 'email'],
      storage: oidcStorage,
    },
    session: {
      storage: sessionStorage,
    },
  },
});

Pass optional integrations through config.modules. The JS API is createJourneyClient(config). When provided, storage handles in modules.session.storage and modules.oidc.storage must come from configureSessionStorage(...) / configureOidcStorage(...).

Step 3: Add logging integration (optional)

If you install the logger package, pass a JS logger instance created via @ping-identity/rn-logger. If the logger package is not installed/configured, do not pass logger values in Journey config.

import { createJourneyClient } from '@ping-identity/rn-journey';
import { logger } from '@ping-identity/rn-logger';

const jsLogger = logger({ level: 'debug' });

const client = createJourneyClient({
  serverUrl: 'https://example.com/am',
  logger: jsLogger,
  modules: {
    oidc: {
      clientId: 'rn-client',
      discoveryEndpoint:
        'https://example.com/am/oauth2/alpha/.well-known/openid-configuration',
      redirectUri: 'com.example.app://callback',
      scopes: ['openid'],
    },
  },
});

Drive the Journey imperatively

const firstNode = await client.start('Login');
const nextNode = await client.next({
  callbacks: [
    { type: 'NameCallback', value: 'demo-user' },
    { type: 'PasswordCallback', value: 'demo-password' },
  ],
});
const resumedNode = await client.resume('com.example.app://callback?code=123');
const session = await client.user();
const refreshedSession = await client.refresh();
const userInfo = await client.userinfo();
const ssoToken = await client.ssoToken();
await client.revoke();
await client.logoutUser();
await client.dispose();

useJourney does not auto-advance nodes. Progression policy is app-controlled via explicit next(...) calls.

Start options are supported when initiating a journey:

const node = await client.start('Login', {
  forceAuth: true,
  noSession: true,
});

Handle node states explicitly in your UI flow:

const node = await client.start('Login');

switch (node.type) {
  case 'ContinueNode':
    await client.next({
      callbacks: [{ type: 'NameCallback', value: 'demo-user' }],
    });
    break;
  case 'ErrorNode':
    console.log(node.message);
    break;
  case 'FailureNode':
    console.log(node.cause ?? node.message);
    break;
  case 'SuccessNode':
    console.log('Authenticated');
    break;
}

Post Authentication Operations

After a Journey login succeeds, use the following operations to inspect and manage the active user session:

const userSession = await client.user();
const ssoToken = await client.ssoToken();

if (userSession) {
  const refreshedSession = await client.refresh();
  const userInfo = await client.userinfo();
  await client.revoke();
}

await client.logoutUser();
  • user() returns token/session payload (accessToken, optional refreshToken, expiresIn, optional userInfo).
  • ssoToken() returns Journey SSO session payload (value, successUrl, realm) when available.
  • refresh() refreshes token payload for the active user.
  • userinfo() fetches user claims for the active user.
  • revoke() revokes access/refresh tokens for the active user.
  • logoutUser() signs out and clears the active Journey user session.

Use the React hook

import { useJourney } from '@ping-identity/rn-journey';

const [node, actions] = useJourney(client);

await actions.start('Login');

if (node?.type === 'ContinueNode') {
  await actions.next({
    callbacks: [{ type: 'NameCallback', value: 'demo-user' }],
  });
}

Share Journey state across multiple screens (optional)

import { JourneyProvider, useJourney } from '@ping-identity/rn-journey';

function App(): React.ReactElement {
  return (
    <JourneyProvider client={client}>
      <AuthNavigator />
    </JourneyProvider>
  );
}

function LoginScreen(): React.ReactElement {
  const [node, actions] = useJourney();
  return <></>;
}

Render callbacks with useJourneyForm

import { callbackType } from '@ping-identity/rn-types';
import { useJourney, useJourneyForm } from '@ping-identity/rn-journey';

const [node, actions] = useJourney(client);
const form = useJourneyForm(node);

const usernameField = form.getFieldByType(callbackType.NameCallback);
const passwordField = form.getFieldByType(callbackType.PasswordCallback);

form.setValueByType(callbackType.NameCallback, 'demo-user');
form.setValueByType(callbackType.PasswordCallback, 'demo-password');

if (form.canSubmit) {
  await actions.next(form.input);
}

useJourneyForm is headless. It manages normalized fields and submit planning, but does not render UI and does not auto-run callbacks.

Each normalized field includes executionMode and requiresUserInput.

| executionMode | Meaning | requiresUserInput default | | ---------------------- | ----------------------------------------------------------------- | --------------------------- | | manual | Callback value is submitted from form/planned input. | true | | auto_capable | Callback can be executed by app auto-progress policy. | false | | integration_required | Callback family needs extra native/app integration before submit. | false | | output_only | Display/system callback, no input value expected. | false | | unsupported | Callback is not currently handled by helper submit logic. | false |

requiresUserInput exceptions:

| Callback Type | executionMode | requiresUserInput | Reason | | --------------------- | --------------- | ------------------- | ---------------------------------------------------------------------------------------- | | HiddenValueCallback | manual | false | Hidden payload should pass through submit planning without forcing a visible input step. |

TODO(test-runner app)(TODO-SEPARATE-TICKET): add Journey integration and E2E tests (including SuspendedTextOutputCallback deep link/email resume flow) once the test-runner app is set up.

Core callback support

The following AM core callbacks are supported on Android and iOS:

| Callback Type | Description | Input Handling | | --------------------------------- | ------------------------------------------------------------ | -------------- | | BooleanAttributeInputCallback | Collects true or false input. | Manual input | | ChoiceCallback | Collects a single selection from available choices. | Manual input | | ConfirmationCallback | Collects one selected option from a list. | Manual input | | ConsentMappingCallback | Prompts the user to consent to sharing profile data. | Manual input | | HiddenValueCallback | Carries non-visual form values. | Manual input | | KbaCreateCallback | Collects knowledge-based question and answer values. | Manual input | | MetadataCallback | Injects key-value metadata into the flow. | Output-only | | NameCallback | Collects a username. | Manual input | | NumberAttributeInputCallback | Collects a numeric value. | Manual input | | PasswordCallback | Collects a password or OTP value. | Manual input | | PollingWaitCallback | Instructs the client to wait and resubmit later. | Output-only | | StringAttributeInputCallback | Collects string attribute values. | Manual input | | SuspendedTextOutputCallback | Pauses flow and resumes through external callback/deep link. | Output-only | | TermsAndConditionsCallback | Collects acceptance of configured terms and conditions. | Manual input | | TextInputCallback | Collects arbitrary text input. | Manual input | | TextOutputCallback | Provides display-only message content. | Output-only | | ValidatedCreatePasswordCallback | Collects password input with policy validation. | Manual input | | ValidatedCreateUsernameCallback | Collects username input with policy validation. | Manual input |

Integration-dependent families (for example, device profile, FIDO, PingOne Protect, redirect/IdP, and ReCaptcha callbacks) are surfaced in node payloads and require client-side integration before submission (executionMode: 'integration_required').

For FIDO callbacks, run explicit Journey-scoped APIs from @ping-identity/rn-fido (registerForJourney(...) / authenticateForJourney(...)) and then call next(...).

Native parity contract

Journey FIDO callback handling is standardized across Android and iOS with the following native contract:

| Area | Standardized behavior | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | Callback type resolution | Runtime native callback class is authoritative; raw callback JSON type is fallback only. | | Callback execution ownership | FIDO callback execution is owned by @ping-identity/rn-fido Journey-scoped APIs, not next(...) callback mutations. | | Hidden callback ownership | Journey/native callback execution remains the source of truth for callback state; helper layer does not force custom override values. |

Error handling

All promise rejections throw a JourneyError instance, which extends PingError extends Error. Use instanceof to narrow the error type:

import { JourneyError } from '@ping-identity/rn-journey';

try {
  await client.start('Login');
} catch (err) {
  if (err instanceof JourneyError) {
    console.log(err.code, err.type, err.message);
  }
}

Stable Journey error codes:

  • JOURNEY_CONFIG_ERROR
  • JOURNEY_INIT_ERROR
  • JOURNEY_START_ERROR
  • JOURNEY_NEXT_ERROR
  • JOURNEY_RESUME_ERROR
  • JOURNEY_USER_ERROR
  • JOURNEY_LOGOUT_ERROR
  • JOURNEY_DISPOSE_ERROR
  • JOURNEY_STATE_ERROR
  • JOURNEY_CALLBACK_APPLY_ERROR
  • JOURNEY_UNSUPPORTED_CALLBACK_ERROR
  • JOURNEY_MISSING_INTEGRATION_ERROR

License

This project is licensed under the MIT License - see the LICENSE file for details