Stripe Identity: ID Authentication Made Simple

Authors
Jan Jaworski
Software Engineer
@
Callstack

There’s no easier way to verify identities than Stripe Identity. It lets you programmatically confirm the identity of users around the globe by scanning an image of an official form of ID, so you can prevent attacks from fraudsters while minimizing friction for legitimate payments.

Stripe Identity is an open source React Native wrapper for the native Stripe SDKs. The idea is to compare your Face ID with images of you and your IDs by means of biometric technology. 

With the Stripe Identity React Native SDK, you can confidently verify the authenticity of ID documents from over 33 countries in your React Native application.

How to use the Stripe Identity React Native SDK

To verify your user’s identity, you need to have a document upload sheet displayed in your application. There are few steps to do that. First of all, you have to install Stripe Identity React Native SDK.

The next step is to set up a server to create a VerificationSession, which is the programmatic representation of the verification. For security reasons, the VerificationSession API is not directly accessible from the mobile client. Instead, your server provides the SDK with an ephemeral key—a short-lived API key with restricted access to the VerificationSession API. 

You can think of an ephemeral key as a session authorizing the SDK to retrieve and update a specific VerificationSession object for the duration of the session. After successfully creating a VerificationSession and ephemeral key, send the VerificationSession id and ephemeral key secret to the client to show the document upload sheet. 

Third step is to show the “document upload” sheet to the user. With Stripe Identity React Native, you can do this in two ways - via a hook called useStripeIdentity, or a method called presentIdentityVerificationSheet. That depends on whether you want to use it in functional or class based components.

You can find example code in the repository or integration guide.

Getting started with the useStripeIdentity hook

The easiest way to use the SDK is to import the useStripeIdentity hook directly in a functional component. You should pass the necessary information you fetched from your server directly to the hook.

import React from "react";
import { View, Button, Text, Image } from "react-native";
import { useStripeIdentity } from "@stripe/stripe-identity-react-native";
// brand logo that needs to be passed to Stripe Identity hook
import logo from "./assets/{{YOUR_BRAND_LOGO}}.png";
// simplified example of fetch function for Stripe Identity
// it can be replaced with more robust implementation that handles error handling, analytics, etc.
// other fetching libraries like Axios can be used as a replacement for native fetch()
const fetchVerificationSessionParams = async () => {
try {
const data = await fetch(
`${YOUR_SERVER_BASE_URL}/create-verification-session`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
}
}
);
const json = await data.json();
return json;
} catch (e) {
return {};
}
};
// options needed to make correct request to Stripe Identity
const fetchOptions = async () => {
const response = await fetchVerificationSessionParams();
return {
sessionId: response.id,
ephemeralKeySecret: response.ephemeral_key_secret,
brandLogo: Image.resolveAssetSource(logo)
};
};
function VerifyScreen() {
// hook provided by Stripe Identity SDK allows API consumers to get important states and values without too much work from their side.
const { status, present, loading } = useStripeIdentity(fetchOptions);
return (
<View>
<Button title="Verify" disabled={loading} onPress={present} />
<Text>Status: {status}</Text>
</View>
);
}

The hook returns 3 fields: status (FlowCompleted, FlowCanceled, FlowFailed), loading boolean, or error, and a method: present. Use the present method to display a document verification sheet. Clicking the verify button will open a native modal view.

Using the Stripe Identity SDK without hooks

If you use class-based components or prefer to implement the SDK without using hooks in your RN application, you can import an async method called presentIdentityVerificationSheet and prepare your own implementation. You will pass the same parameters as with functional components. 

This method returns a status and an optional error.

import React from "react";
import { View, Button, Text } from "react-native";
import { presentIdentityVerificationSheet } from "@stripe/stripe-identity-react-native";
const fetchVerificationSessionParams = async () => {
// same implementation as in function component
};
const fetchOptions = async () => {
// same implementation as in function component
};
class VerifyScreen extends React.Component {
constructor(props) {
super(props);
this.state = { loading: false, status: undefined, error: undefined };
}
present = async () => {
// without provided hooks implementation user has to manage error and loading states manually
this.setState({ loading: true });
const options = await fetchOptions();
this.setState({ loading: false });
const { status, error } = await presentIdentityVerificationSheet(options);
this.setState({ status, error });
};
render() {
return (
<View>
<View>
{this.state.loading ? (
<View>
<Text>Loading...</Text>
</View>
) : (
<Button title="Verify Identity" onPress={this.present} />
)}
</View>
<Text>Status: {this.state.status}</Text>
</View>
);
}
}

Verifying results

Based on the status (FlowCompleted, FlowCancelled, FlowFails), you'll need to handle these outcomes in your application. Please refer to the official documentation to read more about setting up a webhook flow.

Error handling

When implementing such a critical feature for your app, it is important to correctly implement error handling and provide users with clear information about the source of the issue and how they should proceed. If the error is on their side, your application should tell the user what to do to fix the problem. If the problem is due to code or server issues, there should be a clear message saying it.

Stripe Identity SDK provides a number of statuses and messages that can be used to create robust error handling implementation in your application.

Both useStripeIdentity and presentIdentityVerificationSheet provide you with information about the errors.

TypeScript support

Stripe Identity React Native SDK provides TypeScript support - it’s actually written in TypeScript. If you use it in your RN project, you can also use the types that SDK provided - StripeError and IdentityVerificationSheetStatus. Both can be useful while using the method presentIdentityVerificationSheet.

Stripe Identity features

Stripe Identity SDK offers a number of features that allow you to quickly introduce identity verification in your app. It ensures a secure and law-compliant implementation that should cover most of you and your users’ needs.

Simplified security

It’s simple for you to securely collect your user’s personally identifiable information (PII) such as identity document images. Sensitive PII data is sent directly to Stripe Identity instead of passing through your server. More information in the integration security guide.

Automatic document capture

We automatically capture images of the front and back of government-issued photo ID to ensure a clear and readable image.

Prebuilt UI

We provide IdentityVerificationSheet, a prebuilt UI that combines all the steps required to collect ID documents, selfies, and ID numbers into a single sheet that displays on top of your app.

Automated verification

Stripe Identity's automated verification technology looks for patterns to help determine if an ID document is real or fake and uses distinctive physiological characteristics of faces to match your users' selfies to photos on their ID document.

Collected identity information is checked against a global set of databases to confirm that it exists. Learn more about the verification checks supported by Stripe Identity, accessing verification results, or integration guide on handling verification outcomes.

Summary

Stripe Identity was born to make the ID verification process faster and more efficient. Thanks to the technology used, online businesses can easily confirm their users’ identities. It’s a great convenience and, most importantly, a viable safety measure that should be widely adopted.

Insights

Learn more about Security

cover

Dec 17Podcast

A (Secure) Christmas Carol: The Story of Npmezer Scrooge

A holiday story about npm audits, unpinned dependencies, and the real cost of ignoring JavaScript security warnings.

cover

Aug 20Article

Secure Communication Between Isolated React Native Instances

react-native-sandbox now supports secure, direct communication between sandboxed React Native instances, modeled after the web’s postMessage API with origin-based access control.

cover

May 13Article

React Native Legal: Zero-Config OSS License Screens for Your App

Add license acknowledgments to your React Native app with ease using React Native Legal-a zero-config tool for OSS compliance across iOS, Android, tvOS, and AndroidTV platforms.

cover

Jul 3Podcast

Authorization: Security Deep-Dive With Okta (Part 2)

Let's talk access control, delegated authorization, and more. Learn modern security frameworks and get tips for creating reliable apps.

cover

Jul 2Podcast

Authentication: Security Deep-Dive With Okta (Part 1)

Join us as we discuss authentication's past, present, and future. From MFA to passkeys, learn how to enhance security and efficiency in your applications.

cover

Mar 8Article

Learn Once, Hack Everywhere

Demystify reverse engineering of mobile apps, dive into tools, analyze .apk files, and secure React Native code with our article.

cover

Feb 21Article

SSL Pinning in React Native Apps

Learn to implement SSL pinning to future-proof your React Native app against security attacks. Dig deeper into native SSL implementations for iOS & Android.

cover

Nov 21Article

Secure Your React Native app

Learn how to make your React Native app as secure fot your application and customers.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.