Skip to content

feat(cli-auth): add @clerk/cli-auth package#8642

Open
nicolas-angelo wants to merge 1 commit into
mainfrom
feat/cli-auth
Open

feat(cli-auth): add @clerk/cli-auth package#8642
nicolas-angelo wants to merge 1 commit into
mainfrom
feat/cli-auth

Conversation

@nicolas-angelo
Copy link
Copy Markdown

@nicolas-angelo nicolas-angelo commented May 26, 2026

Summary

Adds @clerk/cli-auth to the monorepo — an SDK for adding OAuth 2.0 + PKCE localhost-callback authentication to Node.js CLIs that use Clerk.

This builds on clerk/cli-auth-example, a reference implementation for the pattern, and promotes it into an official @clerk/cli-auth package.

From the reference repo (clerk/cli-auth-example)

  • ClerkCliAuth class with login(), getAccessToken(), whoami(), logout()
  • PKCE + localhost callback HTTP server (S256, random port, state check, timeout)
  • Three credential store backends: OS keychain (with file fallback), chmod 0600 JSON file, in-memory
  • Token endpoint helpers: exchangeCodeForTokens, refreshAccessToken, fetchUserInfo
import { ClerkCliAuth } from '@clerk/cli-auth';

const auth = new ClerkCliAuth({
  clientId: process.env.CLERK_OAUTH_CLIENT_ID!,
  issuer: process.env.CLERK_ISSUER!,
  scopes: ['profile', 'email', 'openid', 'offline_access'],
  storage: 'keychain',
  keychainService: 'my-app-cli',
});

// Opens a browser, runs the localhost callback, exchanges the code, stores tokens
const { tokens, user } = await auth.login();

// Returns the cached access token; auto-refreshes when within 30s of expiry
const token = await auth.getAccessToken();

// Returns cached user info, or fetches /oauth/userinfo if not cached
const me = await auth.whoami();

// Clears stored tokens (see Token revocation below)
await auth.logout();

Additional changes

API key auth

Added support for Clerk API Key auth alongside OAuth. Verification routes through a consumer-provided backend endpoint where server-side verification (e.g. clerk.apiKeys.verify(token)) can be used.

const auth = new ClerkCliAuth({
  // ...
  apiKeys: {
    verifyEndpoint: 'https://myapp.com/api/verify-key',
    envVar: 'MYAPP_API_KEY',
  },
});

const user = await auth.verifyApiKey('ak_...');

Token resolution

resolveToken() returns { token, kind }, giving CLIs the available credential along with its type (oauth or api_key) so they can route to the right verification path. Checks, in order: (1) a token passed via CLI args, (2) the API key env var named by apiKeys.envVar in the config, (3) the cached OAuth access token. Throws if none are available.

const { token, kind } = await auth.resolveToken({ tokenFromArg: argv.token });
if (kind === 'api_key') {
  // verify via backend endpoint
} else {
  // use as OAuth bearer
}

Token revocation

logout() now hits /oauth/token/revoke at the issuer by default, so the refresh token is invalidated remotely instead of just being dropped locally. Opt out with logout({ revoke: false }).

await auth.logout(); // revokes token first, then clears local store
await auth.logout({ revoke: false }); // local cleanup only

Other

  • Richer UserInfo interface
  • Extended OAuthScope type literal union (user:org:read, public_metadata)
  • Tests for the new revoke pathway (cascade from refresh to access token, opt-out, graceful failure when the issuer endpoint errors)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment May 26, 2026 1:15pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 26, 2026

🦋 Changeset detected

Latest commit: c9fbffe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clerk/cli-auth Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

const DEFAULT_SCOPES: OAuthScope[] = ['profile', 'email', 'openid', 'offline_access'];

function normalizeIssuer(issuer: string): string {
const normalized = issuer.trim().replace(/\/+$/, '');
}

function endpoint(issuer: string, path: string): string {
return `${issuer.replace(/\/+$/, '')}${path}`;
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request introduces @clerk/cli-auth, a new reusable package for adding OAuth 2.0 + PKCE authentication to Node.js CLI applications. The package includes a localhost callback server for browser-based sign-in, configurable credential storage backends (OS keychain with file fallback, file, or in-memory), automatic token refresh and revocation, userinfo lookup, and optional API key verification. All public types, error codes, and helper functions are properly exported, and the implementation is comprehensively tested with Vitest.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a new @clerk/cli-auth package to the monorepo. It is clear, specific, and directly reflects the primary objective of the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description provides comprehensive details about the new @clerk/cli-auth package, its features, OAuth flow, credential storage, API key auth support, and token resolution/revocation mechanisms, directly aligned with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nicolas-angelo nicolas-angelo requested a review from Railly May 26, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants