MCPcopy
hub / github.com/afar1/fieldtheory-cli / exchangeCodeForToken

Function exchangeCodeForToken

src/xauth.ts:39–77  ·  view source on GitHub ↗
(code: string, verifier: string)

Source from the content-addressed store, hash-verified

37}
38
39async function exchangeCodeForToken(code: string, verifier: string): Promise<XOAuthTokenSet> {
40 const cfg = loadXApiConfig();
41 if (!cfg.callbackUrl) {
42 throw new Error('Missing X_CALLBACK_URL in .env.local');
43 }
44
45 const basic = Buffer.from(`${cfg.clientId}:${cfg.clientSecret}`).toString('base64');
46 const body = new URLSearchParams({
47 grant_type: 'authorization_code',
48 code,
49 redirect_uri: cfg.callbackUrl,
50 code_verifier: verifier,
51 client_id: cfg.clientId,
52 });
53
54 const response = await fetch('https://api.x.com/2/oauth2/token', {
55 method: 'POST',
56 headers: {
57 Authorization: `Basic ${basic}`,
58 'Content-Type': 'application/x-www-form-urlencoded',
59 },
60 body,
61 });
62
63 const text = await response.text();
64 const parsed = JSON.parse(text);
65 if (!response.ok) {
66 throw new Error(`Token exchange failed (HTTP ${response.status}). Check your X API credentials.`);
67 }
68
69 return {
70 access_token: parsed.access_token,
71 refresh_token: parsed.refresh_token,
72 expires_in: parsed.expires_in,
73 scope: parsed.scope,
74 token_type: parsed.token_type,
75 obtained_at: new Date().toISOString(),
76 };
77}
78
79export async function saveTwitterOAuthToken(token: XOAuthTokenSet): Promise<string> {
80 ensureDataDir();

Callers 1

runTwitterOAuthFlowFunction · 0.85

Calls 1

loadXApiConfigFunction · 0.85

Tested by

no test coverage detected