Skip to content

@xid-kit/react-native

React Native provider and hooks for Hosted Auth redirect, PKCE S256, deep-link callback, and secure token storage adapters.

Status

Package status is Current package. It implements the shared native contract: Hosted Auth redirect with PKCE S256, CSRF state validation on the deep-link callback, authorization code exchange against the token endpoint, and secure token 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 XidProvider. The SDK does not hard-bind any native module; Expo apps can use the ready-made adapters from @xid-kit/expo.

import { XidProvider } from '@xid-kit/react-native'
import type { BrowserInterface, TokenCache } from '@xid-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('xid', 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 (
    <XidProvider
      publishableKey="pk_live_..."
      apiUrl="https://xid.dev"
      issuer="https://xid.dev"
      clientId="your_client_id"
      redirectUri="myapp://auth/callback"
      tokenCache={tokenCache}
      browser={browser}
    >
      <RootNavigator />
    </XidProvider>
  )
}

Sign in

signIn() builds the PKCE S256 authorize URL, stores the verifier and OAuth state in the token cache, opens the browser adapter, and exchanges the returned code for tokens. Browser failure, CSRF state mismatch, and token exchange errors surface as signInState.status === 'error'.

import { useSignIn } from '@xid-kit/react-native'

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

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

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 the OAuth state, exchanges the code, and stores the token set.

import { useSignIn } from '@xid-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
XidProvider component Wraps the @xid-kit/react provider and injects tokenCache, browser, issuer, clientId, redirectUri, and scopes
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 token set, then revokes the server session through useAuth().signOut; signOutState reports progress
useXidRnContext 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 access, refresh, and ID tokens plus PKCE verifier and OAuth state
createPkceVerifier / createPkceChallenge functions PKCE S256 utilities delegated to @xid-kit/protocol (Web Crypto)
createRandomString / base64UrlEncode functions URL-safe random string for OAuth state; base64url encoding helper

Re-exports from @xid-kit/react

Session hooks and control components are re-exported unchanged from @xid-kit/react: useAuth, useUser, useSession, useSessionList, useOrganization, useOrganizationList, useAPIKeys, SignedIn, SignedOut, Protect, XidLoaded, XidLoading, XidFailed, and XidDegraded.

Types

Type Description
XidProviderProps @xid-kit/react provider props plus tokenCache, browser, issuer, clientId, redirectUri, and optional scopes (default openid, profile, email)
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, refreshToken, idToken, expiresIn
XidRnContextValue Adapter context shape returned by useXidRnContext

Known limitations

  • No automatic session refresh on token expiry; the stored refresh token is available for application-managed renewal.
  • useAuth().isSignedIn reflects the XidClient cookie session, not TokenCache contents. Reload client state after a successful token exchange to drive live auth state.
  • 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 token set and revokes the server session; failures surface in signOutState instead of being swallowed.
Navigation

Type to search...

Use arrow keys to navigateEnter to selectEscape to close