AppView in a box as a Vite plugin thing
hatk.dev
1// Browser crypto utilities for OAuth (DPoP, PKCE, JWT)
2
3export function base64UrlEncode(buffer) {
4 const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer)
5 let binary = ''
6 for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])
7 return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
8}
9
10export function randomString(byteLength = 32) {
11 return base64UrlEncode(crypto.getRandomValues(new Uint8Array(byteLength)))
12}
13
14export async function sha256(data) {
15 return new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(data)))
16}
17
18export async function sha256Base64Url(data) {
19 return base64UrlEncode(await sha256(data))
20}
21
22export async function signJwt(header, payload, privateKey) {
23 const enc = new TextEncoder()
24 const h = base64UrlEncode(enc.encode(JSON.stringify(header)))
25 const p = base64UrlEncode(enc.encode(JSON.stringify(payload)))
26 const input = `${h}.${p}`
27 const sig = await crypto.subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, privateKey, enc.encode(input))
28 return `${input}.${base64UrlEncode(sig)}`
29}