ping-identity
    Preparing search index...

    Ping Identity

    Ping Identity React Native External IDP

    The Ping External IDP library empowers your React Native applications to seamlessly authenticate users through external Identity Providers (IDPs) such as Google, Facebook, and Apple. Acting as a plugin for the journey module, it streamlines the integration process by providing the necessary configurations and functionalities to initiate and manage authentication flows with these external services.

    This library abstracts away the complexities of dealing with different IDP protocols and SDKs, offering a unified and developer-friendly API. By leveraging Ping External IDP, you can enhance your application's user experience by offering familiar and convenient login options.

    The library supports native authentication through provider-specific SDKs (Google, Facebook, Apple) for an integrated in-app login flow when used with AIC Journey orchestration.

    Supported authentication experiences:

    • Native: uses provider-specific SDKs (Google, Facebook, Apple) for an integrated in-app login flow.
    • Browser-based: coming in a future release.

    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-external-idp module
    yarn add @ping-identity/rn-external-idp
    # If you are developing your app using iOS, run this command
    cd ios && pod install

    Optional integration packages:

    yarn add @ping-identity/rn-logger
    

    Define the URI scheme in your app's android/app/build.gradle so native provider flows can return to your app when the native SDK requires an app redirect. This configuration is required for devices that do not support Auth Tabs and fall back to Custom Tabs:

    android {
    defaultConfig {
    manifestPlaceholders["appRedirectUriScheme"] = "myapp"
    // Replace "myapp" with your registered custom scheme (e.g. "com.example.myapp")
    }
    }

    This creates a redirect URI of the form myapp://callback.

    To enable native Google or Facebook login (avoiding a browser redirect), add the respective SDK dependencies to your app's android/app/build.gradle:

    dependencies {
    // Google Sign-In
    implementation("com.google.android.libraries.identity.googleid:googleid:1.1.1")
    // Required for devices running Android 13 and below
    implementation("androidx.credentials:credentials-play-services-auth:1.5.0")

    // Facebook Login
    implementation("com.facebook.android:facebook-login:18.0.3")
    }

    Add your app's custom URL scheme to ios/<YourApp>/Info.plist so the OS can route the OAuth redirect back to your app:

    <key>CFBundleURLTypes</key>
    <array>
    <dict>
    <key>CFBundleURLSchemes</key>
    <array>
    <string>myapp</string>
    </array>
    </dict>
    </array>

    Replace myapp with the scheme registered in your AIC configuration (e.g. com.example.myapp).

    Native Google, Facebook, and Apple Sign-In handlers are detected at runtime via dynamic class lookup. Add the desired provider pods to your Podfile:

    # Google Sign-In
    pod 'PingExternalIdPGoogle'
    
    # Facebook Login
    pod 'PingExternalIdPFacebook'
    
    # Apple Sign-In
    pod 'PingExternalIdPApple'
    

    Run pod install after updating the Podfile.

    When a native provider pod is absent, authorizeForJourney rejects with EXTERNAL_IDP_UNSUPPORTED_PROVIDER.

    If you use Google or Facebook Sign-In on iOS, route incoming provider callback URLs from your app delegate to the linked native provider handlers. Apple Sign-In does not need this callback routing.

    #if canImport(PingExternalIdPFacebook)
    import PingExternalIdPFacebook
    #endif
    #if canImport(PingExternalIdPGoogle)
    import PingExternalIdPGoogle
    #endif

    func application(
    _ application: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
    ) -> Bool {
    var handled = false
    #if canImport(PingExternalIdPFacebook)
    handled = FacebookHandler.handleOpenURL(application, url: url, options: options)
    #endif
    #if canImport(PingExternalIdPGoogle)
    handled = GoogleHandler.handleOpenURL(application, url: url, options: options) || handled
    #endif
    return handled
    }

    1. Create a Web application OAuth 2.0 client ID — use this client ID in your AIC connector configuration.
    2. Create an Android OAuth 2.0 client ID — associate it with your app's package name and SHA-1 signing certificate fingerprint.
    3. Create an iOS OAuth 2.0 client ID — associate it with your app's bundle ID. Add the iOS client ID to GIDClientID and add the reversed client ID as a URL scheme in Info.plist. If CFBundleURLTypes already exists, add the Google Sign-In entry to the existing array.
    <key>GIDClientID</key>
    <string>YOUR_IOS_CLIENT_ID</string>

    <key>CFBundleURLTypes</key>
    <array>
    <dict>
    <key>CFBundleURLName</key>
    <string>google-signin</string>
    <key>CFBundleURLSchemes</key>
    <array>
    <string>YOUR_IOS_REVERSED_CLIENT_ID</string>
    </array>
    </dict>
    </array>

    Follow the Facebook Android SDK guide to register your app and generate key hashes.

    Add to android/app/src/main/res/values/strings.xml:

    <resources>
    <string name="facebook_app_id">YOUR_FACEBOOK_APP_ID</string>
    <string name="fb_login_protocol_scheme">fbYOUR_FACEBOOK_APP_ID</string>
    <string name="facebook_client_token">YOUR_CLIENT_TOKEN</string>
    </resources>

    Add to your AndroidManifest.xml inside <application>:

    <activity android:name="com.facebook.CustomTabActivity" android:exported="true">
    <intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data android:scheme="@string/fb_login_protocol_scheme"/>
    </intent-filter>
    </activity>

    Follow the Facebook iOS SDK guide to register your app bundle ID and configure iOS settings.

    Add to ios/<YourApp>/Info.plist:

    <key>FacebookAppID</key>
    <string>YOUR_FACEBOOK_APP_ID</string>
    <key>FacebookClientToken</key>
    <string>YOUR_CLIENT_TOKEN</string>
    <key>FacebookDisplayName</key>
    <string>YOUR_APP_DISPLAY_NAME</string>

    <key>CFBundleURLTypes</key>
    <array>
    <dict>
    <key>CFBundleURLName</key>
    <string>facebook-login</string>
    <key>CFBundleURLSchemes</key>
    <array>
    <string>fbYOUR_FACEBOOK_APP_ID</string>
    </array>
    </dict>
    </array>

    If CFBundleURLTypes already exists, add the Facebook Login entry to the existing array.


    import { createExternalIdpClient } from '@ping-identity/rn-external-idp';
    import { logger } from '@ping-identity/rn-logger';

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

    const externalIdp = createExternalIdpClient({
    // Required app return URI for Auth Tab-capable devices.
    // Must include a URI scheme (e.g. 'com.myapp://callback').
    // When omitted, Android falls back to the appRedirectUriScheme manifest placeholder.
    redirectUri: 'com.myapp://callback',

    // Optional - pass a logger instance from @ping-identity/rn-logger.
    logger: jsLogger,
    });

    The client is reusable — create it once (e.g. with useMemo) and share it across callbacks in a flow.

    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 External IDP config. JavaScript-side External IDP logs use this logger on both platforms.

    import { createExternalIdpClient } from '@ping-identity/rn-external-idp';
    import { logger } from '@ping-identity/rn-logger';

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

    const externalIdp = createExternalIdpClient({
    redirectUri: 'com.myapp://callback',
    logger: jsLogger,
    });

    Call authorizeForJourney when the Journey node contains an IdpCallback. The native SDK handles the redirect internally; no deep-link listener or journey.resume() call is needed. After the promise resolves, call journey.next({}) to advance the flow.

    try {
    await externalIdp.authorizeForJourney(journey, {
    // index: 0 // Use when there are multiple IdpCallbacks in one node
    });
    await journey.next({});
    } catch (error) {
    // See Errors section
    }

    Call selectProviderForJourney before journey.next({}) when the Journey node contains a SelectIdpCallback. The callback state is mutated natively and next() picks it up automatically.

    await externalIdp.selectProviderForJourney(journey, 'google', {
    // index: 0 // Use when there are multiple SelectIdpCallbacks in one node
    });
    await journey.next({});
    import { createExternalIdpClient } from '@ping-identity/rn-external-idp';

    const externalIdp = createExternalIdpClient({
    redirectUri: 'com.myapp://callback',
    });

    async function handleExternalIdpNode(
    journey: JourneyInstance,
    callbacks: Callback[],
    ) {
    for (const cb of callbacks) {
    if (cb.type === 'SelectIdpCallback') {
    const provider = getUserSelectedProvider(); // e.g. 'google'
    await externalIdp.selectProviderForJourney(journey, provider);
    }

    if (cb.type === 'IdpCallback') {
    await externalIdp.authorizeForJourney(journey);
    }
    }

    await journey.next({});
    }

    import { createExternalIdpClient } from '@ping-identity/rn-external-idp';
    import type {
    ExternalIdpClient,
    ExternalIdpConfig,
    ExternalIdpAuthorizeOptions,
    ExternalIdpSelectOptions,
    ExternalIdpResult,
    } from '@ping-identity/rn-external-idp';

    function createExternalIdpClient(config: ExternalIdpConfig): ExternalIdpClient;

    interface ExternalIdpClient {
    authorizeForJourney(
    journey: JourneyInstance,
    options?: ExternalIdpAuthorizeOptions,
    ): Promise<ExternalIdpResult>;

    selectProviderForJourney(
    journey: JourneyInstance,
    provider: string,
    options?: ExternalIdpSelectOptions,
    ): Promise<void>;
    }

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

    import { ExternalIdpError } from '@ping-identity/rn-external-idp';

    try {
    await externalIdpClient.authorizeForJourney(node, providerId);
    } catch (err) {
    if (err instanceof ExternalIdpError) {
    console.log(err.code, err.type, err.message);
    }
    }

    Stable error codes:

    • EXTERNAL_IDP_AUTHORIZE_ERROR
    • EXTERNAL_IDP_CANCELLED
    • EXTERNAL_IDP_UNSUPPORTED_PROVIDER
    • EXTERNAL_IDP_CALLBACK_NOT_FOUND
    • EXTERNAL_IDP_CONFIG_ERROR
    • EXTERNAL_IDP_ACTIVITY_UNAVAILABLE (Android)
    • EXTERNAL_IDP_WINDOW_UNAVAILABLE (iOS)

    • AIC with Journey orchestration: browser fallback is not supported on Android or iOS. The native Android and iOS SDKs do not provide a browser-based fallback for IdpCallback Journey flows. Native provider SDKs must be linked for each target platform: Google or Facebook on Android, and Google, Facebook, or Apple on iOS. When the required native provider SDK is absent, authorizeForJourney rejects with EXTERNAL_IDP_UNSUPPORTED_PROVIDER.

    © Copyright 2025-2026 Ping Identity Corporation. All Rights Reserved