Files
hyperframes/packages/cli/src/auth/pkce.ts
T

44 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* PKCE (Proof Key for Code Exchange, RFC 7636) helpers.
*
* The flow:
* 1. Generate a high-entropy `code_verifier` (43128 URL-safe chars).
* 2. Send `code_challenge = base64url(SHA-256(code_verifier))` to
* `/v1/oauth/authorize`.
* 3. After the user consents, exchange the returned `code` + the
* original `code_verifier` at `/v1/oauth/token`. The server hashes
* the verifier and rejects the exchange if it doesn't match the
* challenge that opened the flow.
*
* PKCE removes the need for a client secret — perfect for a CLI that
* can't keep one.
*/
import { createHash, randomBytes } from "node:crypto";
const VERIFIER_BYTES = 64; // 64 random bytes → 86 base64url chars (well within 43-128)
export interface PkcePair {
/** Sent on the exchange; kept secret by the CLI between the two HTTP hops. */
verifier: string;
/** Sent on the authorize URL. */
challenge: string;
/** Always "S256" for HeyGen's backend (`code_challenge_method`). */
method: "S256";
}
export function generatePkcePair(): PkcePair {
const verifier = base64UrlEncode(randomBytes(VERIFIER_BYTES));
const challenge = base64UrlEncode(createHash("sha256").update(verifier).digest());
return { verifier, challenge, method: "S256" };
}
/** OAuth `state` parameter — a CSRF token bound to this flow. */
export function generateState(): string {
return base64UrlEncode(randomBytes(32));
}
function base64UrlEncode(buf: Buffer): string {
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}