---
title: 'Introducing Expo App Integrity: Protecting your backend from unauthorized clients'
authors: Nishan Bende
published: September 15, 2025
categories: Product, React Native, Development
tags: iOS, Android, Security, Enterprise apps, Expo app integrity, SDK 54, Mobile app security, API Protection
---

When building apps that connect to a backend, some features or workflows may require stronger integrity checks to protect against abuse. In these cases, it can be useful to verify that requests come from genuine instances of your app running on real devices. This helps reduce the risk of modified clients, emulators, or scripts calling your APIs directly and bypassing safeguards.

Today we’re releasing [`@expo/app-integrity`, a library that makes it easier to integrate platform app attestation services into your Expo project](https://docs.expo.dev/versions/latest/sdk/app-integrity/). It works on both Android and iOS, using [**Google Play Integrity**](https://developer.android.com/google/play/integrity) and [**Apple App Attest**](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity) APIs to verify that your app is authentic and running in a trusted environment.

## How Expo App Integrity works at a high level

1. **App → Platform**: Ask the platform (Google Play or Apple) to check the app’s authenticity.
2. **App → Server**: Send the result of that check to your backend.
3. **Server**: Use the platform’s verification process to confirm the result is valid.
4. **Server**: Decide whether to allow, limit, or block the requested action.

## Android

On Android, `@expo/app-integrity` follows the [**Standard request**](https://developer.android.com/google/play/integrity/standard) flow of Play Integrity. Prepare a token provider once, then request integrity tokens for sensitive actions.

```javascript
import * as AppIntegrity from '@expo/app-integrity';

// Do this once after app launch or before a sensitive action
const cloudProjectNumber = 'your-cloud-project-number';
await AppIntegrity.prepareIntegrityTokenProvider(cloudProjectNumber);

// When you need to gate a server request
const requestHash = 'action-specific-hash';
const result = await AppIntegrity.requestIntegrityCheck(requestHash);

// Send `result` to your server to decrypt and verify
```

### Server verification

Decrypt and verify the token on your backend using the steps in [Google’s guide](https://developer.android.com/google/play/integrity/standard#decrypt-and), then decide how to handle the request.

## iOS

On iOS, the flow is based on [**App Attest**](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity). You generate a hardware-backed key pair per user per device, attest it once, and then use it to assert sensitive requests.

```javascript
import * as AppIntegrity from '@expo/app-integrity';

// Check support before using App Attest
if (AppIntegrity.isSupported) {
  // 1) Create a key for this user/device
  const keyId = await AppIntegrity.generateKey();

  // 2) Ask your server for a unique challenge, then attest the key
  const attestationObject = await AppIntegrity.attestKey(keyId, challengeFromServer);

  // Send keyId + attestationObject to your server for one-time verification

  // 3) For sensitive requests, sign with the attested key
  const payload = { action: 'getGameLevel', levelId: '1234', challenge: challengeFromServer };
  const assertion = await AppIntegrity.generateAssertion(keyId, JSON.stringify(payload));

  // Send assertion + payload to your server for verification
}
```

### Server verification

Use [Apple’s validation steps](https://developer.apple.com/documentation/devicecheck/validating-apps-that-connect-to-your-server) to check both the one-time attestation and subsequent assertions.

## Choosing where to check integrity

You don’t need to gate every request. It is common to require integrity signals for actions like purchasing, redeeming credits, fetching premium content, or mutating important state. Start small, observe, then expand coverage as needed.

## Try it today (alpha!)

[As of the SDK 54 release](https://expo.dev/changelog/sdk-54), `@expo/app-integrity` is officially in alpha and available to try: `npx expo install @expo/app-integrity`. We would appreciate any and all feedback and all contributions are welcome. Find us on [Discord](https://discord.com/invite/expo), we are happy to hear your experiences, good or bad. You can help shape the future of the library while it’s in it’s early stages. This is something we intend to continue with for a very long time so please give it a try!  
  
And join the SDK 54 livestream if you want to see a demo or ask us questions live:

[Video: Expo SDK 54 livestream, Wednesday September 17th at 10am PT](https://youtube.com/live/KBlbkjqxNbM?feature=share)