89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
require('dotenv').config();
|
|
const http = require('http');
|
|
const { URL } = require('url');
|
|
const fetch = require('node-fetch');
|
|
const open = (...args) => import('open').then(m => m.default(...args));
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const {
|
|
GITHUB_CLIENT_ID,
|
|
GITHUB_CLIENT_SECRET,
|
|
GITHUB_OAUTH_SCOPES = 'repo,user',
|
|
} = process.env;
|
|
|
|
if (!GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET) {
|
|
console.error('Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET in .env');
|
|
process.exit(1);
|
|
}
|
|
|
|
const PORT = 9876;
|
|
const REDIRECT_URI = `http://localhost:${PORT}/`;
|
|
const STATE = String(Math.random()).slice(2);
|
|
|
|
function appendEnv(key, value) {
|
|
const envPath = path.resolve(process.cwd(), '.env');
|
|
const line = `\n${key}=${value}\n`;
|
|
fs.appendFileSync(envPath, line, { encoding: 'utf8' });
|
|
console.log(`${key} appended to .env`);
|
|
}
|
|
|
|
async function exchangeCodeForToken(code) {
|
|
const tokenUrl = 'https://github.com/login/oauth/access_token';
|
|
const res = await fetch(tokenUrl, {
|
|
method: 'POST',
|
|
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
client_id: GITHUB_CLIENT_ID,
|
|
client_secret: GITHUB_CLIENT_SECRET,
|
|
code,
|
|
redirect_uri: REDIRECT_URI,
|
|
state: STATE,
|
|
}),
|
|
});
|
|
if (!res.ok) throw new Error(`Token exchange failed: ${res.status}`);
|
|
const data = await res.json();
|
|
if (data.error) throw new Error(`Token error: ${data.error_description || data.error}`);
|
|
return data.access_token;
|
|
}
|
|
|
|
const server = http.createServer(async (req, res) => {
|
|
try {
|
|
const reqUrl = new URL(req.url, `http://localhost:${PORT}`);
|
|
const code = reqUrl.searchParams.get('code');
|
|
const state = reqUrl.searchParams.get('state');
|
|
|
|
if (!code || state !== STATE) {
|
|
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
res.end('Invalid request');
|
|
return;
|
|
}
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
res.end('Authorization received. You can close this window.');
|
|
|
|
console.log('Received code, exchanging for token...');
|
|
const token = await exchangeCodeForToken(code);
|
|
console.log('Access token received:', token);
|
|
|
|
// Append token to .env (BE CAREFUL)
|
|
appendEnv('GITHUB_ACCESS_TOKEN', token);
|
|
} catch (err) {
|
|
console.error('Error handling OAuth callback:', err);
|
|
} finally {
|
|
server.close();
|
|
}
|
|
});
|
|
|
|
server.listen(PORT, async () => {
|
|
const authUrl =
|
|
`https://github.com/login/oauth/authorize` +
|
|
`?client_id=${encodeURIComponent(GITHUB_CLIENT_ID)}` +
|
|
`&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
|
|
`&scope=${encodeURIComponent(GITHUB_OAUTH_SCOPES)}` +
|
|
`&state=${encodeURIComponent(STATE)}`;
|
|
|
|
console.log('Opening browser for GitHub authorization...');
|
|
await open(authUrl);
|
|
console.log(`Listening for OAuth callback at ${REDIRECT_URI}`);
|
|
});
|