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

nominee-auth0

v3.0.0

Published

Auth0 strategy for Token Vault and push approvals — without it, a resumed action runs the credential held when the pause started.

Readme

Optional. The nominee core has zero dependencies and works without Auth0. Use this if you want Auth0 to manage token storage and push approvals for you.


Installation

npm i nominee nominee-auth0

What It Does

flowchart TB
    subgraph "nominee-auth0"
        direction TB
        TV["Token Vault\ngetToken()"] 
        CIBA["CIBA\nrequestApproval()"]
    end

    Agent["Agent calls\nnominee.run()"] --> RUN["decision-bound path\n(capability → token)"]
    RUN --> TV
    TV -->|"token exchange\ngrant (federated)"| Auth0["Auth0 Tenant"]
    Auth0 -->|fresh token| TV
    TV --> Agent

    Agent2["Agent calls\nnominee.approve()"] --> CIBA
    CIBA -->|"POST /bc-authorize"| Auth0
    Auth0 -->|push notification| Phone["User's phone 📱"]
    Phone -->|approve / deny| Auth0
    Auth0 -->|poll result| CIBA
    CIBA --> Agent2

| Feature | What it does | |---|---| | Token Vault | Fetches fresh federated connection tokens (GitHub, Google, Slack…) from Auth0. No token storage in your DB. | | CIBA | Pushes an approval request to the user's device and polls until resolved. Real phone notifications, not a polling UI. |


Quickstart

import { Nominee } from 'nominee'
import { Auth0 } from 'nominee-auth0'

const nominee = new Nominee({
  strategy: Auth0({
    domain: process.env.AUTH0_DOMAIN!,          // e.g. 'my-tenant.us.auth0.com'
    clientId: process.env.AUTH0_CLIENT_ID!,
    clientSecret: process.env.AUTH0_CLIENT_SECRET!,
    subjectToken: ({ user }) => sessionStore.getRefreshToken(user),
  }),
})

// Decision-bound: credential resolved inside execute after capability consumption
await nominee.run(
  { tool: 'github.issue.close', input: { repo, issue }, user: 'auth0|user_123', connection: 'github' },
  ({ token }) => closeIssue({ repo, issue, token }),
)

For dev and non-production use, standalone nominee.token() still works:

// Fetches a fresh GitHub token from Auth0 Token Vault
const token = await nominee.token({
  user: 'auth0|user_123',
  connection: 'github',
})

Zero-config — auth0()

For the common single-tenant setup, skip the options entirely. The lowercase auth0() reads everything from the environment:

import { Nominee } from 'nominee'
import { auth0 } from 'nominee-auth0'

const nominee = new Nominee({ strategy: auth0() })

It reads AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, AUTH0_REFRESH_TOKEN (the subject token), and AUTH0_USER_SUB (CIBA login_hint, enabling push approvals when present).

When the core Auth0 vars are absent, auth0() transparently falls back to a built-in mock (a short-TTL token + auto-approve) so an example or test runs with zero setup. Set the env (e.g. via an example's pnpm setup) and the same call becomes real Token Vault + CIBA — no code change. A half-set env throws an actionable error rather than silently mocking.

This is config-code compression, not "zero config": you still provision the tenant once. Use the explicit Auth0({...}) form above when you need per-request subjectToken, multi-tenancy, or custom CIBA options.


CIBA — Push Approvals

For a local or single-process integration, the legacy blocking approval API is the shortest way to try CIBA:

const nominee = new Nominee({
  strategy: Auth0({
    domain: process.env.AUTH0_DOMAIN!,
    clientId: process.env.AUTH0_CLIENT_ID!,
    clientSecret: process.env.AUTH0_CLIENT_SECRET!,
    subjectToken: ({ user }) => sessionStore.getRefreshToken(user),

    // Enable CIBA
    ciba: {
      bindingMessage: (req) => `Approve "${req.action}"?`,
    },
  }),
})

// Blocks this process until the user approves or the request expires.
await nominee.approve({
  user: 'auth0|user_123',
  action: 'repo.delete',
  detail: 'Delete repository: alice/old-project',
})

Production workflows should persist the CIBA request and resume the exact decision-bound action after a restart:

import { Pool } from 'pg'
import { Nominee, ask } from 'nominee'
import { Auth0, PostgresCibaStore } from 'nominee-auth0'
import { PostgresControlStore, postgresDatabase } from 'nominee-postgres'

const database = postgresDatabase(new Pool({ connectionString: process.env.DATABASE_URL }))
const control = new PostgresControlStore(database)
const ciba = new PostgresCibaStore(database)

const nominee = new Nominee({
  production: true,
  policy: { rules: [ask('repo.delete')], fallback: 'deny' },
  actionStore: control,
  receipts: { store: control, delivery: 'strict' },
  strategy: Auth0({
    domain: process.env.AUTH0_DOMAIN!,
    clientId: process.env.AUTH0_CLIENT_ID!,
    clientSecret: process.env.AUTH0_CLIENT_SECRET!,
    subjectToken: ({ user }) => sessionStore.getRefreshToken(user),
    ciba: { store: ciba },
  }),
})

const input = { repo: 'alice/old-project' }
const prepared = await nominee.prepareAction({
  tool: 'repo.delete',
  user: 'auth0|user_123',
  input,
})

if (prepared.status === 'pending_approval') {
  await jobs.save({ actionId: prepared.action.id, input })
  return
}

// In the resumed job, call resumeAction(actionId). When it returns `ready`,
// execute the returned capability with the original, hash-matched input.

Apply both POSTGRES_SCHEMA from nominee-postgres and POSTGRES_CIBA_SCHEMA from this package through your migration system. Production mode rejects an in-memory CIBA store.


With Adapters

Drop-in replacement — just swap the strategy:

import { nomineeTool } from 'nominee-ai'   // or nominee-eve
import { z } from 'zod'

const starRepo = nomineeTool({
  nominee,                // Auth0 strategy under the hood
  user: 'auth0|user_123',
  connection: 'github',
  approval: true,
  action: 'repo.star',
  description: 'Star a GitHub repository',
  inputSchema: z.object({ repo: z.string() }),
  execute: async ({ repo }, ctx) => {
    // ctx.token is a fresh token from Auth0 Token Vault
    await fetch(`https://api.github.com/user/starred/${repo}`, {
      method: 'PUT',
      headers: { Authorization: `Bearer ${ctx.token}` },
    })
    return `Starred ${repo}`
  },
})

Auth0 Setup (the honest version)

nominee removes the runtime token pain — one nominee.token() call, always fresh. It does not remove Auth0/provider setup: that's a one-time job with sharp edges. Here's what actually works, learned the hard way wiring the live GitHub demo:

  1. Enable Token Vault on the connection — via Connected Accounts. Token Vault is now driven by Connected Accounts; set the top-level connected_accounts.active on the connection (the older options.federated_connections_access_tokens is deprecated):
    auth0 api patch "connections/<CONNECTION_ID>" --data '{"connected_accounts":{"active":true}}'
  2. GitHub: use a GitHub App with expiring tokens — not a classic OAuth App. Classic OAuth Apps never issue refresh tokens, so Token Vault has nothing to vault (you'll get federated_connection_refresh_token_not_found). Create a GitHub App, turn on "Expire user authorization tokens", set the callback to https://<tenant>/login/callback, and point the connection at the App's client id/secret.
  3. Grant the exact permission the action needs — App vs repo scope matters. GitHub App user tokens carry account permissions from user authorization, but repository permissions (e.g. metadata=read) require the App to be installed on the repo. Account-only actions (publish a gist, edit profile) need no installation; repo actions do. A 403 "Resource not accessible by integration" means a missing permission — read the x-accepted-github-permissions response header to see exactly which.
  4. Re-vault after changing permissions. Connected Accounts caches the grant. After changing what the user approved, delete the stale connected account (DELETE /me/v1/connected-accounts/{id} via the user's My Account token) and reconnect so the fresh consent is vaulted.
  5. CIBA for push approvals: enable it in the tenant, then set ciba in the strategy.

Once wired, the runtime is just await nominee.token({ user, connection }) — and you can swap this whole strategy for tokens() or OAuth2() without touching your agent code. See the Auth0 documentation for the rest of tenant configuration.


Auth0 Strategy Options

Auth0({
  domain: string           // Auth0 tenant domain
  clientId: string         // M2M application client ID
  clientSecret: string     // M2M application client secret
  subjectToken: (params: GetTokenParams) => string | Promise<string>
  subjectTokenType?: 'refresh_token' | 'access_token'
  fetch?: typeof fetch     // optional custom fetch (defaults to global)

  ciba?: {
    loginHint?: (user: string) => string | Promise<string>
    bindingMessage?: (req: ApprovalRequest) => string  // message shown to user
    pollIntervalMs?: number    // default: from Auth0 response interval
    scope?: string             // default: 'openid'
    audience?: string
  }
})