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

oidcdoctor

v0.1.0

Published

Agent-native CLI that wires OIDC login into your app AND proves it works against Keycloak. Scaffolds login code, reconciles your app config against the actual Keycloak client, then runs a REAL authorization-code + PKCE handshake over plain HTTP (no browse

Readme

oidcdoctor

Wire OIDC login into your app — and prove it actually works against Keycloak.

oidcdoctor is an agent-native CLI (and MCP server) that scaffolds your OIDC login, reconciles your app config against the real Keycloak client, then runs a real authorization-code + PKCE handshake over plain HTTP — no browser — to assert a token is issued. When it fails, it maps the exact error to a precise fix on both sides (app and Keycloak) and loops.

scaffold  →  analyze (reconcile)  →  verify (real handshake)  →  sync (fix Keycloak)  →  verify ✓

Why

The #1 Keycloak pain is the redirect_uri mismatch — and its cousins: PKCE required-but-missing, public-vs-confidential confusion, standard flow disabled, missing web origins. These only fail at runtime, in a browser, with an opaque error. AI agents are great at writing login code, but they can't tell if it works — there's no feedback loop. oidcdoctor is that loop.

The moat is verification, not codegen. Anything can emit a Next.js auth route. oidcdoctor proves the route gets a token, and if it doesn't, tells you exactly which of the two sides to change.

The redirect_uri mismatch, concretely

Your app sends http://localhost:3000/api/auth/callback. Keycloak has http://localhost:3000/api/auth/callback/ registered (trailing slash), or https://… (scheme), or port 3001. Keycloak matches literally (apart from a single trailing *), so login dies with invalid_redirect_uri. oidcdoctor's reconciler pinpoints which component differs — scheme, host, port, path, or trailing slash — and gives you the fix.

Install

npm install -g oidcdoctor      # or: npx -y oidcdoctor <command>

Then wire it into your agent:

oidcdoctor install             # writes the MCP entry for Claude Code + Cursor

This adds oidcdoctor to .mcp.json (Claude Code) and .cursor/mcp.json (Cursor), launching npx -y oidcdoctor mcp. For Codex (TOML), the command prints the snippet for ~/.codex/config.toml. Manual entry:

{
  "mcpServers": {
    "oidcdoctor": { "command": "npx", "args": ["-y", "oidcdoctor", "mcp"] }
  }
}

Quick start

oidcdoctor init                            # write a starter oidcdoctor.json
oidcdoctor scaffold --framework next --out .   # generate login code
oidcdoctor sync                            # create/patch the Keycloak client to match
oidcdoctor verify                          # run the REAL handshake; assert a token is issued
oidcdoctor analyze                         # static reconcile, anytime

oidcdoctor.json

{
  "framework": "next",
  "intent": {
    "issuer": "https://keycloak.example.com/realms/myrealm",
    "clientId": "my-app",
    "redirectUri": "http://localhost:3000/api/auth/callback",
    "postLogoutRedirectUri": "http://localhost:3000/",
    "clientType": "public",
    "usePkce": true,
    "pkceMethod": "S256",
    "scopes": ["openid", "profile", "email"]
  },
  "keycloak": {
    "auth": { "grant": "password", "username": "admin", "password": "admin", "clientId": "admin-cli" }
  },
  "testUser": { "username": "testuser", "password": "testpassword" }
}

The Keycloak issuer is {baseUrl}/realms/{realm}; oidcdoctor derives the OIDC endpoints (/protocol/openid-connect/{auth,token,logout}) and Admin REST base (/admin/realms/{realm}/clients) from it.

How it works: the reconcile + verify loop

  1. analyze (reconcile) — pure, fully unit-tested. Compares the app intent against the live Keycloak client and detects every classic failure class with a code, a human message, and a fix for both sides:

    | code | what it catches | |------|-----------------| | redirect_uri_mismatch | URI not matched (exact + Keycloak * wildcard; flags scheme/host/port/trailing-slash) | | client_type_mismatch | app uses a secret but client is public (or vice-versa) | | pkce_required_missing | client requires PKCE, app doesn't send it | | pkce_method_mismatch | app's method differs from the required one | | standard_flow_disabled | auth-code flow turned off on the client | | web_origins_missing | public/browser client origin not in Web Origins (CORS) | | missing_openid_scope | openid absent — no id_token, not OIDC | | post_logout_mismatch | post-logout URI not registered |

  2. verify (the capstone) — runs the real flow with fetch: builds the authorize URL, GETs the Keycloak login page, scrapes the form action, POSTs the test user's credentials (carrying cookies), catches the 302 to redirect_uri?code=…&state=…, asserts state matches, exchanges the code at the token endpoint (with code_verifier, and client_secret for confidential clients), and asserts a token came back. On any failure it maps the symptom to the same Finding vocabulary as the reconciler — so "it didn't work" always ships with the precise fix.

  3. sync — creates the Keycloak client if missing, otherwise applies the minimal patch from planClientPatch to make it consistent. Re-run verify to confirm.

The verification harness (the headline)

The reason to trust oidcdoctor is that its own test suite proves the loop — hermetically, with no network, no Docker, no real Keycloak, and no browser. An in-process fake Keycloak (test/helpers.ts, built on node:http) implements the authorization, token, logout, and Admin REST endpoints, validates PKCE (S256) and redirect_uri, and can be configured broken. The heal-loop test:

  1. stands up a broken client (redirect_uri unregistered + standard flow off),
  2. verifyLogin fails with a redirect_uri_mismatch diagnosis,
  3. reads the live client, plans the patch, syncs it via the Admin API,
  4. re-runs verifyLogintokenIssued: true.

That's the whole product, proven end to end in milliseconds.

Programmatic API

import { reconcile, planClientPatch, verifyLogin, KeycloakAdmin, scaffold } from "oidcdoctor";

const report = reconcile(intent, keycloakClient);     // { ok, findings }
if (!report.ok) {
  const patch = planClientPatch(intent, keycloakClient);
  await new KeycloakAdmin(opts).syncClient(intent, patch);
}
const result = await verifyLogin(intent, { username, password });  // { ok, tokenIssued, step, diagnosis? }
const files = scaffold("next", intent);               // GeneratedFile[]

MCP tools

When run as an MCP server (oidcdoctor mcp), it exposes four agent-facing tools, all of which nudge the agent to verify, not just generate:

  • analyze — reconcile intent vs. a described/live Keycloak client.
  • verify_login — run the real auth-code + PKCE handshake.
  • sync_client — create/patch the Keycloak client to match the app.
  • scaffold — return generated login files for a framework.

Supported frameworks

  • Next.js (App Router) — route handlers under app/api/auth/..., auth-code
    • PKCE, callback that exchanges the code and sets a session cookie.
  • FastAPI — Authlib (Starlette OAuth), login/callback/logout.
  • Django — mozilla-django-oidc settings + URLs.

The core (reconcile + verify + sync) works for any stack — the scaffolders are a convenience; point oidcdoctor at any app's intent and it'll prove the login regardless of language.

Limitations

  • Keycloak-first. The reconciler models Keycloak's client semantics exactly. Generic OIDC providers (Auth0, Okta, Entra, …) are on the roadmap.
  • No browser flows. Verification drives the handshake over HTTP with fetch; flows that require real JavaScript/WebAuthn in a browser are out of scope.
  • Password-grant test user. verify submits the Keycloak login form with a username/password; social/IdP-brokered logins aren't covered yet.

License

MIT © 2026 Abdulmunim Jemal