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

oauth-guard

v1.0.0

Published

A zero-config local proxy that automatically fetches and refreshes OAuth2 Client Credentials tokens for API testing tools like Postman and curl.

Readme

🛡️ oauth-guard

NPM Version License Node Support PRs Welcome

A zero-config, zero-dependency local proxy server that automatically manages, caches, and refreshes OAuth2 Client Credentials tokens. Built specifically to solve token expiration friction in API testing tools like Postman, Insomnia, and curl.


🛑 The Friction

When testing APIs secured by the OAuth2 Client Credentials grant, developers face a persistent workflow interruption.

According to the OAuth2 specification (RFC 6749, sections 4.2.2 and 4.4.3), auth servers should not issue a refresh_token for Client Credentials. Because of this, popular desktop API clients (like Postman) cannot automatically refresh tokens when they expire.

This leaves developers with three painful choices during testing:

  1. Manually trigger token requests and copy-paste new Authorization headers every hour.
  2. Write custom pre-request scripts in Postman that execute on every single request, slowing down response times and cluttering test collections.
  3. Deal with unexpected 401 Unauthorized errors mid-flow.

⚡ What It Is (and What It Isn't)

oauth-guard runs a lightweight proxy on your local machine. You direct your API client (Postman, curl, or a local dev frontend) to http://localhost:8787 instead of the real API base URL.

The proxy intercepts incoming calls, checks process memory for a valid token, auto-refreshes it proactively if it has expired (or is about to expire), attaches it to the Authorization header, and forwards your request to the target API.

  • What it is: A simple, single-binary-equivalent Node.js developer tool configured with one JSON file. It is optimized for local loopback testing.
  • What it isn't: It is not an enterprise API gateway, production sidecar, or Kubernetes service mesh component. If you need advanced cluster ingress token-management, mutual TLS (mTLS), or cluster-level caching, check out infrastructure-focused utilities like Go's observatorium/token-refresher or Go libraries like udhos/oauth2.

🔄 How It Works

sequenceDiagram
    autonumber
    actor Client as API Client (Postman / curl)
    participant Proxy as localhost:8787 (oauth-guard)
    participant Auth as OAuth Provider (Auth0/Okta)
    participant API as Target API (e.g. Gateway)

    Client->>Proxy: GET /v1/users
    alt Token is missing or expires in < 30s
        Proxy->>Auth: POST /oauth/token (grant_type=client_credentials)
        Auth-->>Proxy: Return JSON (access_token + expires_in)
    end
    Proxy->>API: GET /v1/users (Authorization: Bearer <token>)
    API-->>Proxy: Return Data (JSON/Binary/Stream)
    Proxy-->>Client: Pipe back response unchanged (200 OK)

🛠️ Concurrency Safety (Singleflight Request Coalescing)

If your test suite launches multiple requests in parallel (or you open a dashboard making 10 concurrent API calls) while the cached token is expired or missing, standard proxies trigger 10 simultaneous token requests. This can lead to rate-limiting blocks or invalidating previously generated tokens.

oauth-guard implements single-flight request coalescing. When multiple concurrent requests arrive, only one network request is made to the token endpoint. All other concurrent requests wait in a queue and resolve safely once that single request completes.


🚀 Installation & Usage

Option 1: Run with npx (No Global Installation)

npx oauth-guard start --config config.json

Option 2: Install Globally

npm install -g oauth-guard

📂 Configuration Examples

Create a config.json file in your workspace (copy from config.example.json to start).

Example 1: Auth0 (Requires audience and Form Body Credentials)

{
  "tokenEndpoint": "https://dev-your-tenant.us.auth0.com/oauth/token",
  "clientId": "your_auth0_client_id",
  "clientSecret": "your_auth0_client_secret",
  "credentialStyle": "body",
  "audience": "https://api.yourdomain.local",
  "targetApiBaseUrl": "https://api.yourdomain.com",
  "listenPort": 8787
}

Example 2: Okta / Standard OAuth (Basic Auth Credentials + Custom Timeout)

{
  "tokenEndpoint": "https://your-org.okta.com/oauth2/default/v1/token",
  "clientId": "your_client_id",
  "clientSecret": "your_client_secret",
  "credentialStyle": "basic",
  "targetApiBaseUrl": "https://api.yourdomain.com",
  "listenPort": 8787,
  "scope": "read:users write:users",
  "targetTimeoutMs": 15000
}

⚙️ Configuration Reference

| Parameter | Type | Required | Default | Description | | :--- | :--- | :---: | :---: | :--- | | tokenEndpoint | string | Yes | — | The full URL to request OAuth tokens (e.g., https://auth.company.com/oauth/token). | | clientId | string | Yes | — | The client ID for application authentication. | | clientSecret | string | Yes | — | The client secret for application authentication. | | credentialStyle| string | Yes | — | Location of client credentials. Must be "body" (sent in POST request body) or "basic" (sent in HTTP Basic Auth headers). | | targetApiBaseUrl| string | Yes | — | The base target API URL where requests will be forwarded. | | listenPort | number | Yes | — | Local port the proxy binds to (e.g., 8787). Must be an integer between 1 and 65535. | | audience | string | No | "" | The resource audience identifier (required by Auth0). | | scope | string | No | "" | Optional space-separated list of scopes to request. | | targetTimeoutMs| number | No | 30000 | Connection timeout in milliseconds for forwarded requests to the target API. |


💻 CLI Commands

1. oauth-guard start

Starts the HTTP proxy server on the configured local port.

  • Command: oauth-guard start --config <path>
  • Flags:
    • -c, --config <path>: Path to the JSON configuration file.
    • -v, --verbose: Enables verbose logging. Prints full outbound headers (with redacted access tokens), request paths, and response latency.

2. oauth-guard status

A one-shot diagnostics tool to verify credentials and connectivity without starting the server.

  • Command: oauth-guard status --config <path>
  • Output: Displays endpoint reachability latency, credential authentication status, token lifetime remaining, and a redacted preview of the returned token.
[oauth-guard] [status] ℹ️ Checking token endpoint: https://dev-tenant.us.auth0.com/oauth/token
[oauth-guard] 🔄 Fetching new token from https://dev-tenant.us.auth0.com/oauth/token...
[oauth-guard] ✅ Token acquired, expires in 86400s

[oauth-guard] [status] ✅ Diagnostic Summary:
  • Token endpoint reachability : REACHABLE (took 452ms)
  • Authentication status       : SUCCESSFUL
  • Token lifetime / expiry     : 86400s remaining (23h 59m 59s)
  • Token confirmation          : eyJhbG*** [redacted]

🔒 Security Notes

[!IMPORTANT] Because oauth-guard handles active credentials and authentication tokens, please observe the following guidelines:

  1. Local-Only Binding: The proxy server binds and listens on localhost (127.0.0.1) only. Never expose the configured port to public networks or external interfaces.
  2. Git Safety: Add config.json to your local .gitignore immediately. Never commit real credentials to source control. Use config.example.json to share schemas with team members.
  3. Memory Caching: Credentials and access tokens are kept purely in-memory. They are never written to disk or serialized to local temporary folders.

⚠️ Limitations & Scope

  • Single Target API: Each instance of the proxy is dedicated to one targetApiBaseUrl. If you need to test multiple separate target APIs, start multiple proxy instances on separate local ports.
  • Flow Support: Supports Client Credentials grant type only. Authorization Code, Implicit, and Password grants are out of scope.
  • No Persistence: Restarting the proxy clears the cached token, meaning a fresh token will be acquired on the first request after launch.

📄 License

MIT License. See LICENSE for details.