npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wocha/react-native

v0.1.0

Published

React Native and Expo hooks for Wocha authentication (OAuth PKCE)

Readme

@wocha/react-native

npm version npm downloads TypeScript License

React Native and Expo hooks for Wocha authentication. Implements the OAuth 2.0 authorisation code flow with PKCE as a public client — no client secret required.

Install

npm install @wocha/react-native
# Recommended Expo peers for production:
npx expo install expo-web-browser expo-secure-store expo-linking

Peer dependencies:

| Package | Required | Purpose | |---------|----------|---------| | react | Yes | Hooks and provider | | react-native | Yes | App lifecycle and Linking fallback | | expo-web-browser | Optional | In-app / system browser OAuth session | | expo-secure-store | Optional | Encrypted token storage (Keychain / Keystore) | | expo-linking | Optional | Deep link callback handling |

When Expo packages are not installed, the SDK falls back to react-native Linking for redirects and in-memory token storage (not suitable for production).

Quick start

1. Register a redirect URI

In the Wocha Console, register a custom URL scheme for your app:

myapp://auth/callback

For Expo, add the scheme to app.json:

{
  "expo": {
    "scheme": "myapp"
  }
}

2. Wrap your app

import { WochaProvider } from "@wocha/react-native";

export default function App() {
  return (
    <WochaProvider
      config={{
        issuer: "https://my-tenant.auth.wocha.ai",
        clientId: "your-client-id",
        redirectUri: "myapp://auth/callback",
      }}
    >
      <RootNavigator />
    </WochaProvider>
  );
}

3. Sign in from a screen

import { useWochaAuth, useSession } from "@wocha/react-native";
import { Button, Text, View } from "react-native";

export function HomeScreen() {
  const { signIn, signOut } = useWochaAuth();
  const { data, status } = useSession();

  if (status === "loading") {
    return <Text>Loading…</Text>;
  }

  if (status === "authenticated" && data) {
    return (
      <View>
        <Text>Signed in as {data.email}</Text>
        <Button title="Sign out" onPress={() => void signOut()} />
      </View>
    );
  }

  return <Button title="Sign in" onPress={() => void signIn()} />;
}

Deep link callbacks are handled automatically by WochaProvider — no separate callback screen is required when using expo-web-browser or Linking.

Configuration

| Field | Type | Required | Description | |-------|------|----------|-------------| | issuer | string | Yes | OIDC issuer URL (e.g. https://my-tenant.auth.wocha.ai) | | clientId | string | Yes | OAuth public client ID | | redirectUri | string | Yes | Deep link callback URL registered in the Console | | scope | string | No | Default: openid profile email org_id offline_access | | audience | string | No | API audience claim when required by your tenant | | apiUrl | string | No | Customer API base for org switching. Defaults to {tenant}.api.wocha.ai/v1 on Wocha Cloud | | storageKeyPrefix | string | No | Prefix for secure storage keys | | onRedirectCallback | (appState?: unknown) => void | No | Called after a successful OAuth callback |

Hooks

| Hook | Description | |------|-------------| | useSession() | Session data, status, error, and refresh() | | useUser() | Current user and auth status | | useOrg() | Active org, org list, and switchOrg() | | useWochaAuth() | Imperative signIn(), signUp(), signOut(), switchOrg(), getAccessToken() | | useAccessToken() | Access token and refresh helpers | | usePermission(check) | SpiceDB permission check (requires apiUrl) |

Permission check

import { usePermission } from "@wocha/react-native";

const { allowed, isLoading } = usePermission({
  resource: { type: "document", id: "doc_123" },
  permission: "read",
});

UI components

Import from @wocha/react-native/components:

| Component | Description | |-----------|-------------| | SignInButton | Triggers the OAuth sign-in flow | | SignOutButton | Signs out and clears tokens | | UserInfo | Displays current user name and email | | AuthGuard | Renders children only when authenticated | | OrgSwitcher | Pressable list for switching organisations |

import {
  SignInButton,
  SignOutButton,
  UserInfo,
  AuthGuard,
  OrgSwitcher,
} from "@wocha/react-native/components";

<AuthGuard fallback={<SignInButton />}>
  <UserInfo />
  <OrgSwitcher />
  <SignOutButton />
</AuthGuard>

Organisation switching

import { useOrg } from "@wocha/react-native";

const { orgId, orgIds, switchOrg, isSwitching } = useOrg();

Security model

  • Public client + PKCE — safe for mobile apps; no client secret in the binary.
  • Secure storage — refresh tokens are stored with expo-secure-store or react-native-keychain when available.
  • Background refresh — access tokens refresh automatically before expiry and when the app returns to the foreground.
  • Deep link validation — OAuth state is verified on every callback.

Self-hosted configuration

<WochaProvider
  config={{
    issuer: "https://auth.internal.example.com",
    clientId: process.env.EXPO_PUBLIC_WOCHA_CLIENT_ID!,
    redirectUri: "myapp://auth/callback",
    apiUrl: "https://api.internal.example.com/v1",
  }}
>
  {children}
</WochaProvider>

Related packages

| Package | Use when | |---------|----------| | @wocha/react | React web SPA | | @wocha/nextjs | Next.js with server-side BFF | | @wocha/sdk | Management API from a backend |

Troubleshooting

Redirect URI mismatch

The redirectUri in config must exactly match a URI registered for your OAuth application in the Console.

Session not persisting

Install expo-secure-store (or react-native-keychain). Without secure storage the SDK uses in-memory storage and tokens are lost when the app closes.

Callback never fires

Confirm your app scheme is configured in app.json / AndroidManifest.xml / Info.plist, and that expo-linking or React Native Linking receives the callback URL.

See the React Native quickstart for a full integration walkthrough.