44 lines
1.3 KiB
JavaScript
44 lines
1.3 KiB
JavaScript
/**
|
|
* PKCE (Proof Key for Code Exchange) utilities.
|
|
* Uses the Web Crypto API — no external dependencies needed.
|
|
*/
|
|
|
|
/**
|
|
* Generate a cryptographically random code verifier (43-128 chars, base64url).
|
|
*/
|
|
export function generateCodeVerifier() {
|
|
const array = new Uint8Array(48) // 48 bytes → 64-char base64url string
|
|
crypto.getRandomValues(array)
|
|
return base64urlEncode(array)
|
|
}
|
|
|
|
/**
|
|
* Derive the code challenge from the verifier (S256 method).
|
|
* @param {string} verifier
|
|
* @returns {Promise<string>}
|
|
*/
|
|
export async function generateCodeChallenge(verifier) {
|
|
const encoder = new TextEncoder()
|
|
const data = encoder.encode(verifier)
|
|
const digest = await crypto.subtle.digest('SHA-256', data)
|
|
return base64urlEncode(new Uint8Array(digest))
|
|
}
|
|
|
|
/**
|
|
* Generate a random state parameter to prevent CSRF.
|
|
*/
|
|
export function generateState() {
|
|
const array = new Uint8Array(16)
|
|
crypto.getRandomValues(array)
|
|
return base64urlEncode(array)
|
|
}
|
|
|
|
// ── Internal helpers ──────────────────────────────────────────────────────────
|
|
|
|
function base64urlEncode(buffer) {
|
|
return btoa(String.fromCharCode(...buffer))
|
|
.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=+$/, '')
|
|
}
|