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

@openkey/sdk-react-native

v0.0.5

Published

A React Native OAuth 2.1 + PKCE client for [OpenKey](https://openkey.so). Authenticates users via the system browser (ASWebAuthenticationSession on iOS, Chrome Custom Tabs on Android) -- not a WebView.

Readme

@openkey/sdk-react-native

A React Native OAuth 2.1 + PKCE client for OpenKey. Authenticates users via the system browser (ASWebAuthenticationSession on iOS, Chrome Custom Tabs on Android) -- not a WebView.

Lightweight and headless -- no UI components, just the auth flow.

Installation

bun add @openkey/sdk-react-native

Peer Dependencies

Quick Start

import { OpenKeyRN } from '@openkey/sdk-react-native';
import * as WebBrowser from 'expo-web-browser';

const openkey = new OpenKeyRN({
  host: 'https://openkey.so',
  clientId: 'your-client-id',
  redirectUri: 'myapp://auth/callback',
  openBrowser: (url) =>
    WebBrowser.openAuthSessionAsync(url, 'myapp://auth/callback').then(() => {}),
});

// Start sign-in (opens system browser)
const tokens = await openkey.signIn();
console.log(tokens.accessToken);

// Handle deep link callback (in your deep link handler)
openkey.handleCallback(incomingUrl);

// Refresh tokens
const newTokens = await openkey.refreshToken(tokens.refreshToken!);

// Sign out
await openkey.signOut(tokens.accessToken);

Deep Link Setup

Your app must be configured to receive the redirect URI as a deep link.

iOS (Info.plist)

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>

Android (AndroidManifest.xml)

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="myapp" android:host="auth" android:pathPrefix="/callback" />
</intent-filter>

API Reference

new OpenKeyRN(config)

Create an OAuth client instance.

const openkey = new OpenKeyRN({
  host: 'https://openkey.so',       // OpenKey server URL
  clientId: 'your-client-id',       // OAuth client ID
  redirectUri: 'myapp://auth/callback', // Deep link redirect URI
  openBrowser: (url) => ...,        // Required: opens URL in system browser
  sha256: (input) => ...,           // Optional: custom SHA-256 for PKCE
  timeoutMs: 300_000,               // Optional: sign-in timeout (default 5 min)
});

openkey.signIn()

Start the OAuth 2.0 Authorization Code + PKCE flow. Opens the system browser and returns a promise that resolves when handleCallback() receives the redirect.

const tokens: AuthTokens = await openkey.signIn();

openkey.handleCallback(url)

Handle an incoming deep link redirect. Call this from your app's URL/deep link handler. Returns true if the URL matched a pending sign-in flow, false otherwise.

const handled: boolean = openkey.handleCallback(incomingUrl);

openkey.refreshToken(refreshToken)

Exchange a refresh token for new tokens.

const newTokens: AuthTokens = await openkey.refreshToken(tokens.refreshToken!);

openkey.signOut(accessToken)

Revoke an access token and clear all pending sign-in flows.

await openkey.signOut(tokens.accessToken);

getOpenKeyRN(config?)

Singleton helper. Returns an existing instance or creates one with the provided config.

import { getOpenKeyRN } from '@openkey/sdk-react-native';

// First call: creates the instance
const openkey = getOpenKeyRN({ host: '...', clientId: '...', ... });

// Later calls: returns the same instance
const openkey = getOpenKeyRN();

Types

OpenKeyRNFullConfig

interface OpenKeyRNFullConfig {
  host: string;              // OpenKey server URL
  clientId: string;          // OAuth client ID
  redirectUri: string;       // Deep link redirect URI
  openBrowser: BrowserOpener; // Function to open URL in system browser
  sha256?: SHA256Fn;         // Custom SHA-256 implementation
  timeoutMs?: number;        // Sign-in timeout in ms (default: 300000)
}

AuthTokens

interface AuthTokens {
  accessToken: string;       // OAuth access token
  idToken: string;           // OpenID Connect ID token
  refreshToken?: string;     // Refresh token (if granted)
  expiresIn: number;         // Token lifetime in seconds
}

OpenKeyError

class OpenKeyError extends Error {
  code: OpenKeyErrorCode;
  message: string;
}

PKCE Utilities

Low-level PKCE helpers, exported for advanced use cases:

  • generateCodeVerifier() -- random code verifier string
  • generateCodeChallenge(verifier, sha256?) -- S256 code challenge
  • generateState() -- random state parameter
  • base64UrlEncode(buffer) -- base64url encoding

Error Handling

All errors are thrown as OpenKeyError with a typed error code:

| Code | Description | |------|-------------| | USER_CANCELLED | User dismissed the browser | | TIMEOUT | Auth flow timed out (default 5 min) | | STATE_MISMATCH | CSRF state validation failed | | NETWORK_ERROR | Network request failed | | UNKNOWN | Unexpected error |

import { OpenKeyError } from '@openkey/sdk-react-native';

try {
  const tokens = await openkey.signIn();
} catch (error) {
  if (error instanceof OpenKeyError) {
    switch (error.code) {
      case 'USER_CANCELLED':
        // User closed the browser
        break;
      case 'TIMEOUT':
        // Flow timed out
        break;
      case 'NETWORK_ERROR':
        // Network issue
        break;
    }
  }
}

Security

  • PKCE (Proof Key for Code Exchange) prevents authorization code interception
  • System browser ensures credentials never pass through app code
  • No WebView -- immune to credential harvesting attacks
  • State parameter prevents CSRF attacks
  • Tokens returned to caller -- the SDK does not store tokens; your app controls persistence

Links

License

MIT