Skip to main content
Para supports OAuth authentication with providers like Google, Apple, Discord, X, and Facebook. Use authenticateWithOAuth() to handle the entire OAuth flow in a single call — it manages the redirect, polls for completion, and creates wallets for new users.

Prerequisites

Before implementing OAuth authentication, ensure you have completed the basic Para setup for your React Native or Expo application.

Standard OAuth

Use para.authenticateWithOAuth() to authenticate a user via a third-party OAuth provider. The method manages the OAuth redirect, polls for completion, waits for session establishment, and creates wallets for new signups. For standard OAuth providers, use the onOAuthUrl callback to open the OAuth URL in an in-app browser.

Installation

Install the In-App Browser package to handle OAuth redirects:
npm install react-native-inappbrowser-reborn
# or
yarn add react-native-inappbrowser-reborn
For iOS, add the following to your Info.plist to define your URL scheme:
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>your-app-scheme</string>
    </array>
  </dict>
</array>
For Android, add your URL scheme to AndroidManifest.xml:
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask">
    <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="your-app-scheme" />
    </intent-filter>
</activity>

Implementation

import { para } from "../your-para-client";
import { OAuthMethod } from "@getpara/react-native-wallet";
import { InAppBrowser } from "react-native-inappbrowser-reborn";

const APP_SCHEME = "your-app-scheme";

async function handleOAuthLogin(provider: OAuthMethod) {
  try {
    const result = await para.authenticateWithOAuth({
      method: provider,
      appScheme: APP_SCHEME,
      redirectCallbacks: {
        onOAuthUrl: async (url) => {
          await InAppBrowser.openAuth(url, APP_SCHEME, {
            ephemeralWebSession: false,
            showTitle: false,
            enableUrlBarHiding: true,
          });
        },
      },
    });

    if (result.hasCreatedWallets && result.recoverySecret) {
      console.log("Recovery secret:", result.recoverySecret);
    }

    console.log("Auth info:", result.authInfo);
    // Navigate to your authenticated screen
  } catch (error) {
    console.error("OAuth failed:", error);
  }
}
Both react-native-inappbrowser-reborn and expo-web-browser use secure browser implementations that leverage the device’s native browser engine rather than a WebView. This provides stronger security protections and support for modern authentication methods.

Telegram & Farcaster

Telegram and Farcaster authentication require a different approach than standard OAuth. These providers authenticate through Para’s hosted portal, which needs to send events back to the SDK when authentication completes. On mobile, this requires opening the portal in a WebView (not an in-app browser) so the portal can communicate via window.ReactNativeWebView.postMessage(). You must forward messages from the WebView to the SDK using para.handleWebViewMessage().
Telegram and Farcaster cannot use InAppBrowser or expo-web-browser because the portal needs a live message channel to send authentication events (TELEGRAM_SUCCESS, FARCASTER_SUCCESS) back to the SDK. Only a WebView provides this channel via onMessage.
import { useState } from "react";
import { Modal } from "react-native";
import { WebView, type WebViewMessageEvent } from "react-native-webview";
import { para } from "../your-para-client";
import type { OAuthMethod } from "@getpara/react-native-wallet";

const APP_SCHEME = "your-app-scheme";

function TelegramOrFarcasterAuth() {
  const [portalUrl, setPortalUrl] = useState<string | null>(null);

  const handleAuth = async (method: OAuthMethod) => {
    try {
      const result = await para.authenticateWithOAuth({
        method,
        appScheme: APP_SCHEME,
        redirectCallbacks: {
          onOAuthUrl: (url) => {
            // Show the portal URL in a WebView instead of an in-app browser
            setPortalUrl(url);
          },
        },
      });

      setPortalUrl(null);

      if (result.hasCreatedWallets && result.recoverySecret) {
        console.log("Recovery secret:", result.recoverySecret);
      }

      console.log("Auth info:", result.authInfo);
      // Navigate to your authenticated screen
    } catch (error) {
      setPortalUrl(null);
      console.error("Auth failed:", error);
    }
  };

  const handleWebViewMessage = (event: WebViewMessageEvent) => {
    try {
      const data = JSON.parse(event.nativeEvent.data);
      // Forward portal events (TELEGRAM_SUCCESS, FARCASTER_SUCCESS, etc.) to the SDK
      para.handleWebViewMessage(data);
    } catch {
      // Ignore non-JSON messages
    }
  };

  return (
    <>
      {/* Your auth buttons */}
      <Button title="Continue with Telegram" onPress={() => handleAuth("TELEGRAM")} />
      <Button title="Continue with Farcaster" onPress={() => handleAuth("FARCASTER")} />

      {/* WebView modal for portal interaction */}
      <Modal visible={!!portalUrl} animationType="slide">
        <WebView
          source={{ uri: portalUrl! }}
          onMessage={handleWebViewMessage}
          javaScriptEnabled
        />
      </Modal>
    </>
  );
}
Install react-native-webview if you haven’t already:
npm install react-native-webview
# or for Expo:
npx expo install react-native-webview

Method Reference

This method must be paired with para.onStatePhaseChange() to handle portal URLs that appear after OAuth completes (e.g. passkey or password setup for returning users). See the guide for your platform for the full state listener pattern.

Cancelling Authentication

Both OAuth polling and session polling accept an isCanceled callback. Return true from isCanceled to stop the polling loop — for example, when the user dismisses the in-app browser or navigates away. The cancellation is clean: no error is thrown, and the optional onCancel callback fires.
const result = await para.authenticateWithOAuth({
  method: "GOOGLE",
  appScheme: APP_SCHEME,
  oAuthPollingCallbacks: {
    isCanceled: () => userClickedCancel,
    onCancel: () => console.log("OAuth polling canceled"),
  },
  sessionPollingCallbacks: {
    isCanceled: () => userClickedCancel,
    onCancel: () => console.log("Session polling canceled"),
  },
});
Calling para.logout() also cancels all active polling and resets the state phases back to unauthenticated. This is useful for implementing a “Cancel” button that fully resets the auth flow:
const handleCancel = async () => {
  await para.logout();
  // All polling stops, state phases reset to unauthenticated
};

Handling Results

authenticateWithOAuth() returns the same AuthenticateResponse as email/phone auth. See the authentication guide for full response type documentation.

Next Steps