this repo has no description
1/** 2 * OAuth flow helpers for e2e tests 3 */ 4 5import { randomBytes } from 'node:crypto'; 6import { DpopClient } from './dpop.js'; 7 8const BASE = 'http://localhost:8787'; 9 10/** 11 * Get an OAuth token with a specific scope via full PAR -> authorize -> token flow 12 * @param {string} scope - The scope to request 13 * @param {string} did - The DID to authenticate as 14 * @param {string} password - The password for authentication 15 * @returns {Promise<{accessToken: string, refreshToken: string, dpop: DpopClient}>} 16 */ 17export async function getOAuthTokenWithScope(scope, did, password) { 18 const dpop = await DpopClient.create(); 19 const clientId = 'http://localhost:3000'; 20 const redirectUri = 'http://localhost:3000/callback'; 21 const codeVerifier = randomBytes(32).toString('base64url'); 22 const challengeBuffer = await crypto.subtle.digest( 23 'SHA-256', 24 new TextEncoder().encode(codeVerifier), 25 ); 26 const codeChallenge = Buffer.from(challengeBuffer).toString('base64url'); 27 28 // PAR request 29 const parProof = await dpop.createProof('POST', `${BASE}/oauth/par`); 30 const parRes = await fetch(`${BASE}/oauth/par`, { 31 method: 'POST', 32 headers: { 33 'Content-Type': 'application/x-www-form-urlencoded', 34 DPoP: parProof, 35 }, 36 body: new URLSearchParams({ 37 client_id: clientId, 38 redirect_uri: redirectUri, 39 response_type: 'code', 40 scope: scope, 41 code_challenge: codeChallenge, 42 code_challenge_method: 'S256', 43 login_hint: did, 44 }).toString(), 45 }); 46 const parData = await parRes.json(); 47 48 // Authorize 49 const authRes = await fetch(`${BASE}/oauth/authorize`, { 50 method: 'POST', 51 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 52 body: new URLSearchParams({ 53 request_uri: parData.request_uri, 54 client_id: clientId, 55 password: password, 56 }).toString(), 57 redirect: 'manual', 58 }); 59 const location = authRes.headers.get('location'); 60 const authCode = new URL(location).searchParams.get('code'); 61 62 // Token exchange 63 const tokenProof = await dpop.createProof('POST', `${BASE}/oauth/token`); 64 const tokenRes = await fetch(`${BASE}/oauth/token`, { 65 method: 'POST', 66 headers: { 67 'Content-Type': 'application/x-www-form-urlencoded', 68 DPoP: tokenProof, 69 }, 70 body: new URLSearchParams({ 71 grant_type: 'authorization_code', 72 code: authCode, 73 client_id: clientId, 74 redirect_uri: redirectUri, 75 code_verifier: codeVerifier, 76 }).toString(), 77 }); 78 const tokenData = await tokenRes.json(); 79 80 return { 81 accessToken: tokenData.access_token, 82 refreshToken: tokenData.refresh_token, 83 dpop, 84 }; 85}