// make-oauth-cli.js
import crypto from "crypto";
import http from "http";
import open from "open";
import readline from "readline";
import fetch from "node-fetch";
import { URLSearchParams } from "url";
// 🔧 Replace with your real client ID and registered redirect URI
const CLIENT_ID = "YOUR_CLIENT_ID";
const REDIRECT_URI = "http://localhost:7531/callback";
const AUTHORIZATION_ENDPOINT = "https://auth.make.com/oauth/authorize";
const TOKEN_ENDPOINT = "https://auth.make.com/oauth/token";
const SCOPES = [
"scenarios:read",
"scenarios:run",
"scenarios:write",
"teams:read"
];
// PKCE helper: create verifier and challenge
function generateCodeVerifier() {
const verifier = crypto.randomBytes(64).toString("hex");
const challenge = crypto
.createHash("sha256")
.update(verifier)
.digest("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
return { verifier, challenge };
}
async function getToken() {
const { verifier, challenge } = generateCodeVerifier();
// Step 1: Open browser to authorize
const state = crypto.randomBytes(16).toString("hex");
const authUrl = `${AUTHORIZATION_ENDPOINT}?response_type=code&client_id=${encodeURIComponent(
CLIENT_ID
)}&redirect_uri=${encodeURIComponent(
REDIRECT_URI
)}&code_challenge=${challenge}&code_challenge_method=S256&scope=${SCOPES.join(
"%20"
)}&state=${state}`;
console.log("Opening browser to authorize with Make.com...");
await open(authUrl);
// Step 2: Start HTTP server to receive callback
const code = await new Promise((resolve, reject) => {
const server = http.createServer((req, res) => {
if (!req.url.includes("/callback")) return;
const url = new URL(req.url, REDIRECT_URI);
if (url.searchParams.get("state") !== state) {
res.writeHead(400);
res.end("Invalid state");
reject(new Error("State mismatch"));
return;
}
const code = url.searchParams.get("code");
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Authorization complete! You can close this tab.");
server.close();
resolve(code);
});
server.listen(7531);
});
// Step 3: Exchange code for token
const tokenResponse = await fetch(TOKEN_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "authorization_code",
code: code,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
code_verifier: verifier,
}),
});
if (!tokenResponse.ok) {
console.error("Token exchange failed:", await tokenResponse.text());
process.exit(1);
}
const tokenData = await tokenResponse.json();
console.log("✅ Access Token:", tokenData.access_token);
console.log("🔄 Refresh Token:", tokenData.refresh_token);
console.log("🆔 ID Token:", tokenData.id_token);
}
getToken();