The `@authdog/react-native` SDK brings Authdog to React Native and Expo apps: a provider, session and user hooks, sign-in/out helpers, and a secure-storage adapter. Sign-in uses a deep-link redirect that lands with a token. It reads the [session](/docs/concepts/sessions-tokens) Authdog issues.

## Install

```package-install
@authdog/react-native
npx expo install expo-secure-store
```

Requires React 18/19 and React Native `>=0.74`. There's no hard Expo dependency; `expo-secure-store` is only for persistent storage. Set `EXPO_PUBLIC_PK_AUTHDOG` to your environment's public key (`pk_...`).

## Wrap your app

Pass the public key and a storage adapter. Without one, sessions are held in memory and don't survive a restart, so use the SecureStore adapter in real apps:

```tsx
import * as SecureStore from "expo-secure-store"
import {
  AuthdogProvider,
  createSecureStoreAdapter,
} from "@authdog/react-native"

export default function App() {
  return (
    <AuthdogProvider
      publicKey={process.env.EXPO_PUBLIC_PK_AUTHDOG!}
      storage={createSecureStoreAdapter(SecureStore)}
    >
      <RootNavigator />
    </AuthdogProvider>
  )
}
```

## Sign in with a deep link

`useSignIn` opens the hosted flow. Handle both cold-start and warm links; `useRedirectHandler` checks JWT structure before storing the token:

```tsx
import { useEffect } from "react"
import { Button, Linking } from "react-native"
import { useSignIn, useRedirectHandler } from "@authdog/react-native"

export function SignInButton() {
  const { signIn } = useSignIn()
  const { handleRedirect } = useRedirectHandler()

  useEffect(() => {
    Linking.getInitialURL().then((url) => url && handleRedirect(url))
    const subscription = Linking.addEventListener("url", ({ url }) => {
      handleRedirect(url)
    })
    return () => subscription.remove()
  }, [handleRedirect])

  return <Button title="Sign in" onPress={() => signIn("myapp://callback")} />
}
```

Register the same callback scheme in your app configuration and Authdog environment. The local JWT check is not cryptographic authentication; send the bearer token to a backend that validates it before granting access.

## Read the session

- `useUser()`: `{ user, fetchUser, isAuthenticated, isLoading, error }`
- `useSession()`: `{ session: { token, isAuthenticated }, isLoading }`
- `useSignUp()`, `useSignOut()`: `{ signUp/signOut, isLoading, error }`
- `useAuthz({ permissionsUrl })`: `{ fetchPermissions, hasPermission }` for UI hints

`useAuthz` is for showing and hiding UI only: enforce access on your [backend](/docs/backend) with your [authorization](/docs/concepts/authorization) model.

## Next steps

- [Sign up & sign in](/docs/authentication): the flows behind the redirect.
- [Backend requests](/docs/backend): validate the mobile session on your API.
