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()}
/>
)
}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 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.