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

@evantra-identity/react

v0.1.1

Published

Sign in with Evantra — React, React Native and Expo components plus the OAuth 2.0 / PKCE core for Evantra Identity.

Readme

@evantra-identity/react

Official, public package for Sign in with Evantra — React and React Native components, plus the OAuth 2.0 / PKCE core.

  • Web (React / Next.js) — provider, buttons and URL helpers
  • Mobile (React Native / Expo) — framework-agnostic core with deep-link handling
  • OAuth — authorization code flow with PKCE (RFC6749, RFC7636, RFC8252)

Licensed MIT.

Full walkthrough: Evantra Identity — Client Integration Guide


Install

pnpm add @evantra-identity/react

Ships as ESM (type: module) with TypeScript declarations. React 18+ is a peer dependency. Node 18+.

Not on the npm registry yet. Until the release lands, install the prebuilt tarball instead — the import path is identical:

npm install ./evantra/dist-artifacts/evantra-identity-react-0.1.0.tgz

See the Distribution Guide.


Quick start (web)

import {
  EvantraIdentityProvider,
  EvantraSignInButton,
  EvantraRegisterButton,
} from "@evantra-identity/react";

export function AuthButtons() {
  return (
    <EvantraIdentityProvider
      config={{
        identityWebBaseUrl: "https://identity.evantradebuckman.com",
        identityApiBaseUrl: "https://evantra-headquarters.onrender.com",
        clientId: "evt_client_…",
      }}
    >
      <EvantraSignInButton returnTo="/welcome">
        Sign in with Evantra
      </EvantraSignInButton>

      <EvantraRegisterButton returnTo="/welcome">
        Create account
      </EvantraRegisterButton>
    </EvantraIdentityProvider>
  );
}

returnTo must be a same-origin relative path on the identity application. Absolute URLs are rejected, so the identity app can never be used as an open redirect.


Full OAuth flow

import {
  createEvantraAuthorizeUrl,
  createEvantraPkcePair,
  createEvantraState,
  consumeEvantraWebCallback,
  exchangeEvantraCode,
} from "@evantra-identity/react";

// 1. Start
const { verifier, challenge } = await createEvantraPkcePair();
const state = createEvantraState();

sessionStorage.setItem("evantra_pkce_verifier", verifier);
sessionStorage.setItem("evantra_oauth_state", state);

window.location.assign(
  createEvantraAuthorizeUrl(
    defaultIdentityApiBaseUrl(),
    {
      clientId: "evt_client_…",
      redirectUri: "https://app.example.com/oauth/callback",
      codeChallenge: challenge,
      state,
    },
  ),
);

// 2. On your callback page
const { code } = consumeEvantraWebCallback(state);

const tokens = await exchangeEvantraCode(
  { clientId: "evt_client_…" },
  {
    code,
    codeVerifier: sessionStorage.getItem("evantra_pkce_verifier")!,
    redirectUri: "https://app.example.com/oauth/callback",
  },
);

Why the authorize URL points at the identity API host, not the web app. /oauth/authorize is the API's authorization endpoint. When the visitor has no session the API redirects them to the identity web app to sign in (and register, and verify their email), then completes the request and returns the code to your redirectUri. Pointing at the web app directly would skip the endpoint that issues the code. Use defaultIdentityApiBaseUrl() rather than hardcoding the host so a future endpoint change needs no edit.

consumeEvantraWebCallback also strips the code from the address bar so it is not bookmarked or shared.


Mobile (React Native / Expo)

import {
  consumeEvantraNativeCallback,
  exchangeEvantraCode,
  createEvantraAuthorizeUrl,
  createEvantraPkcePair,
  createEvantraState,
  defaultIdentityApiBaseUrl,
} from "@evantra-identity/react";

const REDIRECT_URI = "com.example.app://oauth/callback";

const { verifier, challenge } = await createEvantraPkcePair();
const state = createEvantraState();

await SecureStore.setItemAsync("evantra_pkce_verifier", verifier);
await SecureStore.setItemAsync("evantra_oauth_state", state);

const result = await WebBrowser.openAuthSessionAsync(
  createEvantraAuthorizeUrl(
    defaultIdentityApiBaseUrl(),
    {
      clientId: "evt_client_…",
      redirectUri: REDIRECT_URI,
      codeChallenge: challenge,
      state,
    },
  ),
  REDIRECT_URI,
);

const { code } = consumeEvantraNativeCallback(result.url!, state);

const tokens = await exchangeEvantraCode(
  { clientId: "evt_client_…" },
  {
    code,
    codeVerifier: (await SecureStore.getItemAsync("evantra_pkce_verifier"))!,
    redirectUri: REDIRECT_URI,
  },
);

Registered redirect URI shapes:

| Platform | Redirect URI | |---|---| | Web | https://app.example.com/oauth/callback | | iOS / Android / Expo | com.example.app://oauth/callback | | Desktop / CLI | http://127.0.0.1:PORT/callback |


Exports

Components

| Export | Purpose | |---|---| | EvantraIdentityProvider | Supplies configuration via context | | useEvantraIdentity() | Reads the current configuration | | EvantraSignInButton | Link to the hosted sign-in page | | EvantraRegisterButton | Link to the hosted registration page | | EvantraAuthorizeButton | Link to /oauth/authorize |

OAuth core

| Export | Purpose | |---|---| | createEvantraPkcePair() | PKCE verifier + S256 challenge | | createEvantraState() | Unguessable CSRF state value | | createEvantraAuthorizeUrl() | Builds the authorize URL | | createEvantraLoginUrl() | Hosted sign-in URL | | createEvantraRegisterUrl() | Hosted registration URL | | defaultIdentityApiBaseUrl() | The identity API origin (authorize/token/userinfo) | | defaultIdentityWebBaseUrl() | The identity web origin (login/register screens) | | consumeEvantraWebCallback() | Reads the code from the browser URL | | consumeEvantraNativeCallback() | Reads the code from a deep link | | exchangeEvantraCode() | Code → tokens | | refreshEvantraToken() | Refresh token → tokens | | revokeEvantraToken() | Revokes a token | | fetchEvantraUserInfo() | Loads the user profile | | EVANTRA_DEFAULT_SCOPE | "openid profile email" | | EvantraOAuthError | Typed OAuth failure |


Security notes

  • Always use PKCE (S256).
  • Never embed a client_secret in a browser or mobile app. Those are public clients.
  • Always send state and verify it on return. consumeEvantraWebCallback(state) and consumeEvantraNativeCallback(url, state) throw invalid_state when the value does not match.
  • Store the PKCE verifier in sessionStorage (web) or SecureStore/keystore (native) — never localStorage.
  • Exchange the code on your backend when your client is confidential.
  • Check email_verified before trusting an address.
  • Verify the id_token before trusting its claims. This package does not verify ID tokens for you: signature checking needs the JWKS and is deliberately left to the caller. Use a dedicated library (jose, openid-client) against the identity service's JWKS, and validate iss, aud, exp and nonce. Treat the token as untrusted until then.

See Security checklist.