import type { PKCEChallenge } from "./types.ts"; export class PKCEUtils { static generateCodeVerifier(): string { const array = new Uint8Array(32); crypto.getRandomValues(array); return btoa(String.fromCharCode.apply(null, Array.from(array))) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } static async generateCodeChallenge(verifier: string): Promise { const encoder = new TextEncoder(); const data = encoder.encode(verifier); const digest = await crypto.subtle.digest("SHA-256", data); return btoa( String.fromCharCode.apply(null, Array.from(new Uint8Array(digest))) ) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } static async generatePKCEChallenge(): Promise { const codeVerifier = this.generateCodeVerifier(); const codeChallenge = await this.generateCodeChallenge(codeVerifier); return { codeVerifier, codeChallenge, codeChallengeMethod: "S256", }; } static generateState(): string { const array = new Uint8Array(16); crypto.getRandomValues(array); return btoa(String.fromCharCode.apply(null, Array.from(array))) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } }