> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native Passkeys

> Configure native passkey support for the JavaScript SDK on Expo and bare React Native — associated domains, asset links, and client setup.

`signInWithPasskey()` works the same on React Native as it does on the web, but passkeys are bound to a domain, so mobile apps need extra native setup before the OS will create or use them. You must associate your app with a domain you control and point the Dynamic client at that same domain with `metadata.universalLink`.

<Note>
  Complete [React Native Setup](/docs/javascript/react-native/setup) first — this page only covers the passkey-specific native configuration. Passkey usage (`signInWithPasskey()`, registration) is documented on [Authenticate with Passkey](/docs/javascript/authentication-methods/passkey) and is identical across platforms.
</Note>

## Prerequisites

Before you start, make sure you have:

* A React Native app with the JavaScript SDK integrated (see [Expo](/docs/javascript/react-native/expo) or [Bare React Native](/docs/javascript/react-native/bare-react-native)).
* A domain you control, to host the required `.well-known` endpoints. This is the value you set as `metadata.universalLink`.
* **iOS:** an Apple Developer account, your Team ID, and your app's bundle identifier.
* **Android:** your app's package name and the SHA-256 fingerprint of your signing certificate.

## Install the passkey package

If you have not already installed it during setup, add `react-native-passkey`.

<Tabs>
  <Tab title="Expo">
    ```shell theme={"system"}
    npx expo install react-native-passkey
    ```
  </Tab>

  <Tab title="Bare React Native">
    ```shell theme={"system"}
    npm install react-native-passkey
    cd ios && bundle exec pod install && cd ..
    ```
  </Tab>
</Tabs>

## Point the client at your domain

Set `metadata.universalLink` to the domain that will host the `.well-known` endpoints. This is the origin passkeys are associated with, so it must match exactly.

```ts dynamicClient.ts theme={"system"}
import { createDynamicClient } from '@dynamic-labs-sdk/client';

export const dynamicClient = createDynamicClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  metadata: {
    name: 'My App',
    nativeLink: 'myapp://',
    universalLink: 'https://yourdomain.com', // Must match the associated domain below
  },
});
```

## Configure iOS

Host an Apple App Site Association (AASA) file at `https://yourdomain.com/.well-known/apple-app-site-association`. It must be served as JSON (no `.json` extension) over HTTPS. Passkeys use the `webcredentials` key; keep the empty `applinks` block too — Apple can silently ignore the file if it's absent. Replace `TEAMID` with your Apple Team ID and `com.example.myapp` with your bundle identifier:

```json apple-app-site-association theme={"system"}
{
  "applinks": {
    "details": []
  },
  "webcredentials": {
    "apps": ["TEAMID.com.example.myapp"]
  }
}
```

<Accordion title="Live example">
  Dynamic's demo app serves a working file at [`demo.dynamic.xyz/.well-known/apple-app-site-association`](https://demo.dynamic.xyz/.well-known/apple-app-site-association) (abridged to the demo app):

  ```json apple-app-site-association theme={"system"}
  {
    "applinks": {
      "details": [
        {
          "appIDs": ["HSCFHA4GVS.xyz.dynamic.demo"],
          "components": [{ "/": "/", "comment": "Opens the Dynamic Demo app" }]
        }
      ]
    },
    "webcredentials": {
      "apps": ["HSCFHA4GVS.xyz.dynamic.demo"]
    }
  }
  ```
</Accordion>

Then declare the associated domain in your app so iOS trusts the credential relationship.

<Tabs>
  <Tab title="Expo">
    Add the domain to `app.json` and rebuild the native app:

    ```json app.json theme={"system"}
    {
      "expo": {
        "ios": {
          "associatedDomains": ["webcredentials:yourdomain.com"]
        }
      }
    }
    ```

    ```shell theme={"system"}
    npx expo prebuild --clean
    npx expo run:ios
    ```
  </Tab>

  <Tab title="Bare React Native">
    In Xcode, open **Signing & Capabilities**, add the **Associated Domains** capability, and add an entry:

    ```
    webcredentials:yourdomain.com
    ```

    Rebuild the app so the entitlement is applied:

    ```shell theme={"system"}
    npx react-native run-ios
    ```
  </Tab>
</Tabs>

<Note>
  Validate your AASA file with the [Branch AASA Validator](https://branch.io/resources/aasa-validator/) before testing on device — Apple caches it, so misconfigurations are easy to miss.
</Note>

## Configure Android

Host a Digital Asset Links file at `https://yourdomain.com/.well-known/assetlinks.json`. Replace `com.example.myapp` with your package name and `SHA_HEX_VALUE` with the SHA-256 fingerprint(s) of your signing certificate:

```json assetlinks.json theme={"system"}
[
  {
    "relation": [
      "delegate_permission/common.get_login_creds",
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.myapp",
      "sha256_cert_fingerprints": ["SHA_HEX_VALUE"]
    }
  }
]
```

<Accordion title="Live example">
  Dynamic's demo app serves a working file at [`demo.dynamic.xyz/.well-known/assetlinks.json`](https://demo.dynamic.xyz/.well-known/assetlinks.json) (abridged to the demo app):

  ```json assetlinks.json theme={"system"}
  [
    {
      "relation": ["delegate_permission/common.get_login_creds"],
      "target": { "namespace": "web", "site": "https://demo.dynamic.xyz" }
    },
    {
      "relation": [
        "delegate_permission/common.get_login_creds",
        "delegate_permission/common.handle_all_urls"
      ],
      "target": {
        "namespace": "android_app",
        "package_name": "xyz.dynamic.demo",
        "sha256_cert_fingerprints": [
          "AE:09:4E:8A:6E:7B:50:C3:01:05:06:28:BB:7D:FB:2A:A3:85:CC:9A:4C:93:A2:25:07:B2:E5:93:2E:0D:D7:48",
          "F3:09:3C:BA:94:AE:21:E0:DE:7A:E6:CB:C5:6A:EF:52:53:AD:BE:6E:7E:70:5D:58:9E:1C:C8:C5:37:02:E3:26"
        ]
      }
    }
  ]
  ```
</Accordion>

Rebuild the app after hosting the file:

```shell theme={"system"}
npx expo run:android
# or, on bare React Native:
npx react-native run-android
```

## Sign in with a passkey

Once the associations resolve, passkeys behave exactly as on the web — call `signInWithPasskey()` (or `useSignInWithPasskey()` in React). See [Authenticate with Passkey](/docs/javascript/authentication-methods/passkey).

<Tip>
  Passkeys failing on device? Confirm the `.well-known` files are served over HTTPS with no redirects, that `metadata.universalLink` matches the associated domain exactly, and see [Troubleshooting](/docs/overview/troubleshooting/general).
</Tip>
