---
title: "@vonvon-kit/react-native"
description: "React Native provider and hooks for Hosted Auth redirect, PKCE S256, deep-link callback, and secure token storage adapters."
locale: "en"
---

> Documentation Index
> Fetch the relevant documentation index at: https://vonvon.id/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# @vonvon-kit/react-native

## Status

Registry status: UNPUBLISHED. Install this SDK only from the repository source checkout; do not use an external package registry.

Package status is **Current package**. It implements a native token-session contract: Hosted Auth redirect with PKCE S256, state and nonce validation on the deep-link callback, verified ID token claims, authorization code exchange, and secure session persistence through an injected storage adapter.

A real IdP round-trip on production infrastructure is still pending manual verification. This page documents implemented behavior; it is not a readiness claim.

## Provider setup

Inject a `TokenCache` (platform secure storage) and a `BrowserInterface` (in-app browser) into `VonvonProvider`. The SDK does not hard-bind any native module; Expo apps can use the ready-made adapters from [@vonvon-kit/expo](/sdks/expo).

```tsx
import { VonvonProvider } from '@vonvon-kit/react-native'
import type { BrowserInterface, TokenCache } from '@vonvon-kit/react-native'
import * as Keychain from 'react-native-keychain'

const tokenCache: TokenCache = {
  async getToken(key) {
const result = await Keychain.getGenericPassword({ service: key })
return result ? result.password : null
  },
  async saveToken(key, value) {
await Keychain.setGenericPassword('vonvon', value, { service: key })
  },
  async deleteToken(key) {
await Keychain.resetGenericPassword({ service: key })
  },
}

const browser: BrowserInterface = {
  async openAuthSession(url, redirectUri) {
// Open url with your in-app browser library, wait for the redirectUri
// deep link, then return { type: 'success', url } or { type: 'cancel' }.
throw new Error('Implement with your preferred in-app browser library.')
  },
}

export function App() {
  return (
<VonvonProvider
  issuer="https://vonvon.id"
  clientId="your_client_id"
  redirectUri="myapp://auth/callback"
  tokenCache={tokenCache}
  browser={browser}
>
  <RootNavigator />
</VonvonProvider>
  )
}
```

## Sign in

`signIn()` builds the PKCE S256 authorize URL, stores the verifier, OAuth state, and nonce in the token cache, opens the browser adapter, and exchanges the returned code for a verified native session. Browser failure, state mismatch, ID token verification, and token exchange errors surface as `signInState.status === 'error'`.

```tsx
import { useSignIn } from '@vonvon-kit/react-native'

function SignInScreen() {
  const { signIn, signInState } = useSignIn()

  return (
<Button
  title={signInState.status === 'pending' ? 'Signing in...' : 'Sign in'}
  onPress={() => void signIn()}
/>
  )
}
```

## Deep link callback

When the browser adapter cannot capture the redirect itself, register the redirect URI scheme in your app manifest and forward the deep link to `handleRedirect(url)`. It validates and consumes the OAuth state, verifier, and nonce, exchanges the code, verifies the ID token, and stores the native session.

```tsx
import { useSignIn } from '@vonvon-kit/react-native'
import { useEffect } from 'react'
import { Linking } from 'react-native'

function DeepLinkHandler() {
  const { handleRedirect } = useSignIn()

  useEffect(() => {
const sub = Linking.addEventListener('url', ({ url }) => {
  if (url.startsWith('myapp://auth/callback')) {
    void handleRedirect(url)
  }
})
return () => sub.remove()
  }, [handleRedirect])

  return null
}
```

## Exported API

| Export | Kind | Purpose |
| --- | --- | --- |
| `VonvonProvider` | component | Provides a native token-session context using tokenCache, browser, issuer, clientId, redirectUri, scopes, and optional fetcher |
| `useSignIn` | hook | signIn(options?) runs the full redirect flow; handleRedirect(url) processes a deep-link callback; signInState reports idle, pending, complete, cancelled, or error |
| `useSignOut` | hook | signOut() clears the local session and legacy credentials; signOutState reports progress or storage failures; no revoke request is sent |
| `useVonvonRnContext` | hook | Raw adapter context (advanced use and testing) |
| `exchangeCodeForTokens` | function | Low-level POST to the token endpoint with grant\_type authorization\_code and the PKCE verifier; returns a TokenSet |
| `saveTokenSet / clearTokenSet` | functions | Persist or remove the token set in the TokenCache adapter |
| `TOKEN_KEYS` | as const object | TokenCache key names for the current session envelope and pending PKCE, state, and nonce records; legacy token keys are cleanup-only |
| `createPkceVerifier / createPkceChallenge` | functions | PKCE S256 utilities delegated to @vonvon-kit/protocol (Web Crypto) |
| `createRandomString / base64UrlEncode` | functions | URL-safe random string for OAuth state; base64url encoding helper |

## Native hooks and controls

Unlike [@vonvon-kit/react](/sdks/react), this package uses its own native token context. It exports `useAuth`, `useUser`, `useSession`, `useSignIn`, `useSignOut`, `useVonvonRnContext`, `SignedIn`, `SignedOut`, `VonvonLoaded`, `VonvonLoading`, `exchangeCodeForTokens`, `saveTokenSet`, `readTokenSet`, and `clearTokenSet`; it does not import or re-export the React web SDK.

## Types

| Type | Description |
| --- | --- |
| `VonvonProviderProps` | Native provider props: children, tokenCache, browser, issuer, clientId, redirectUri, optional scopes (default openid, profile, email), and optional fetcher |
| `TokenCache` | Storage adapter contract: getToken, saveToken, deleteToken (all async) |
| `BrowserInterface` | openAuthSession(url, redirectUri) resolving to a BrowserResult |
| `BrowserResult` | Union of success (with callback URL), cancel, and dismiss |
| `SignInOptions` | Per-call overrides for signIn: redirectUri, scopes |
| `SignInState / SignOutState` | Discriminated status unions returned by the hooks |
| `UseSignInReturn / UseSignOutReturn` | Hook return shapes: actions plus state |
| `TokenExchangeInput / TokenSet` | Input and result of exchangeCodeForTokens: accessToken, idToken, expiresIn, and verified ID token claims |
| `VonvonRnContextValue` | Adapter context shape returned by useVonvonRnContext |

## Known limitations

- The SDK has no DPoP sender binding, rejects offline\_access, and requires a new authorization flow after the access token expires.
- useAuth().isSignedIn reflects a locally stored session only after ID token verification; it does not read a web cookie session.
- Organization context is not populated from stored tokens yet.

## Security

- Authorization code with PKCE S256 only. No implicit or password grant.
- Public clients never store client secrets.
- PKCE verifier and OAuth state live in the injected secure storage adapter and are deleted after the code exchange.
- signOut clears the local session and legacy credentials without a refresh or revoke request; storage failures surface in signOutState.

Source: https://vonvon.id/sdks/react-native/index.mdx
