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

@canton-vc/credential

v0.3.0

Published

High-level OAuth 2.0 / OIDC client + on-chain disclosure verification helper for Canton-issued verifiable credentials. Wraps the issuer's /oauth/authorize + /oauth/token + /oauth/userinfo endpoints and exposes verifyDisclosure() so any firm running their

Downloads

479

Readme

@canton-vc/credential

OAuth 2.0 + OpenID Connect client SDK for Canton-VC compatible KYC issuers.

Works in modern browsers, Node.js 18+, Bun and Deno. Zero runtime dependencies — backed by the Web Crypto API and the platform fetch.

Install

npm install @canton-vc/credential
# or
pnpm add @canton-vc/credential

Browser usage — redirect flow

import { CantonVcClient, CantonVcOauthError, isCantonVcOauthError } from '@canton-vc/credential';

const client = new CantonVcClient({
  clientId: 'crv_oauth_live_xxxxxxxxxxxxx',
  redirectUri: 'https://your.app/oauth/callback',
});

// On your "Verify identity" button click:
document.querySelector('#verify')?.addEventListener('click', () => {
  client.authorize({ scope: ['openid', 'kyc'] });
});

On your /oauth/callback page:

import { CantonVcClient, isCantonVcOauthError } from '@canton-vc/credential';

const client = new CantonVcClient({
  clientId: 'crv_oauth_live_xxxxxxxxxxxxx',
  redirectUri: 'https://your.app/oauth/callback',
});

try {
  const { code, codeVerifier } = await client.handleCallback();
  // Forward { code, codeVerifier } to your backend — never exchange
  // a code from the browser unless this is a public (PKCE-only) client.
  await fetch('/api/finish-signup', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ code, codeVerifier }),
  });
} catch (err) {
  if (isCantonVcOauthError(err)) {
    console.error(err.code, err.description);
  }
}

Server-side — code exchange

import { CantonVcClient } from '@canton-vc/credential';

const client = new CantonVcClient({
  clientId: process.env.CANTON_VC_CLIENT_ID!,
  clientSecret: process.env.CANTON_VC_CLIENT_SECRET!,
  redirectUri: 'https://your.app/oauth/callback',
});

// inside your /api/finish-signup handler:
const tokens = await client.exchangeCode({ code, codeVerifier });
const claims = await client.getUserinfo(tokens.access_token);

if (claims.identity_verified !== true) throw new Error('KYC required');
return { userId: claims.sub };

Public clients (SPAs / native)

Public clients authenticate with PKCE alone — no client_secret. The SDK handles this automatically when clientSecret is omitted:

const client = new CantonVcClient({
  clientId: 'crv_oauth_live_public_spa_xxxx',
  redirectUri: 'https://your.app/oauth/callback',
});

await client.authorize({ scope: ['openid', 'kyc'] });
// …later…
const { code, codeVerifier } = await client.handleCallback();
const tokens = await client.exchangeCode({ code, codeVerifier });

Custom storage

The SDK needs to persist the PKCE verifier + state between the authorize redirect and the callback. The default storage is sessionStorage with an in-memory fallback. Override with your own implementation when sessionStorage isn't available (React Native, extensions, encrypted stores):

import { CantonVcClient, type SdkStorage } from '@canton-vc/credential';

const storage: SdkStorage = {
  getItem: async (k) => mySecureStore.read(k),
  setItem: async (k, v) => mySecureStore.write(k, v),
  removeItem: async (k) => mySecureStore.delete(k),
};

const client = new CantonVcClient({ clientId, redirectUri }, storage);

Error handling

Every failure throws a CantonVcOauthError with a .code matching the OAuth 2.0 / RFC 9700 vocabulary:

| code | meaning | |---|---| | access_denied | User rejected the consent screen | | state_mismatch | CSRF token from storage did not match the callback query | | missing_verifier | Storage was cleared before the callback (user came back on a new tab?) | | invalid_grant | Server refused the code — expired, reused, or wrong client | | invalid_client | Wrong client_secret or unknown client_id | | pkce_invalid | The verifier doesn't match the original challenge | | network_error | Underlying fetch rejected |

Use isCantonVcOauthError(err) to type-narrow.

API reference

new CantonVcClient(options, storage?)

  • options.clientId — required.
  • options.redirectUri — required, exact match against the value registered in the issuer dashboard.
  • options.clientSecret — required for confidential clients, must NOT be set in the browser.
  • options.issuer — full origin of the issuer deployment. Defaults to https://issuer.example; set this to the URL of the issuer you're integrating with.
  • options.fetch — override the global fetch.

client.buildAuthorizeUrl({ scope, nonce?, redirectUri?, uiLocales? })

Returns { url, state, codeVerifier, nonce? } without navigating. Useful for SSR and testing.

client.authorize({ scope, ... })

Browser convenience — builds the URL and navigates the current tab. Returns a Promise<never>.

client.handleCallback(input?)

Parses the callback URL (default: window.location), validates state, returns { code, codeVerifier, redirectUri, state }.

client.exchangeCode({ code, codeVerifier, redirectUri? })

Exchanges the code for a token response { access_token, token_type, expires_in, scope, id_token? }.

client.getUserinfo(accessToken)

Fetches the userinfo claim set.

License

Apache 2.0 — see LICENSE at the repository root.