75 lines
3.0 KiB
TypeScript
75 lines
3.0 KiB
TypeScript
/**
|
|
* Who do these credentials say I am?
|
|
*
|
|
* pkgx pnpm run twilio:whoami
|
|
*
|
|
* Fetches the Account resource with the configured SID and token, which
|
|
* separates "wrong credential pair" from "credentials fine, problem is
|
|
* elsewhere" in one call. Sends nothing and costs nothing.
|
|
*/
|
|
import { smsConfig } from "../src/env.js";
|
|
|
|
const config = smsConfig();
|
|
const sid = config.twilioAccountSid;
|
|
const token = config.twilioAuthToken;
|
|
|
|
if (sid === undefined || token === undefined) {
|
|
console.error("Set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN first.");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`Account SID: ${sid} (${sid.length} chars, prefix ${sid.slice(0, 2)})`);
|
|
console.log(`Auth token: ${token.length} chars, ends ...${token.slice(-4)}`);
|
|
|
|
const response = await fetch(
|
|
`https://api.twilio.com/2010-04-01/Accounts/${encodeURIComponent(sid)}.json`,
|
|
{
|
|
headers: {
|
|
Authorization: "Basic " + Buffer.from(`${sid}:${token}`).toString("base64"),
|
|
},
|
|
}
|
|
);
|
|
const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;
|
|
|
|
console.log(`\nHTTP ${response.status}`);
|
|
|
|
// Test credentials authenticate fine and are then refused most resources.
|
|
// That refusal is itself proof the pair is valid, so report it as a pass.
|
|
if (response.status === 403 && body.code === 20008) {
|
|
console.log(` code: ${String(body.code)}`);
|
|
console.log(` message: ${String(body.message)}`);
|
|
console.log(
|
|
"\nThese are valid Twilio Test Credentials. The pair authenticated; the\n" +
|
|
"Accounts resource is simply not one that test credentials may read, so\n" +
|
|
"this 403 is the expected answer and not a misconfiguration.\n\n" +
|
|
"What they can do: create Messages with From=+15005550006. Nothing is\n" +
|
|
"delivered and nothing is billed. The +1500555000x magic To numbers force\n" +
|
|
"specific failures; a real To number is accepted by some accounts and\n" +
|
|
"answered with 20404 on others, so treat the magic numbers as the reliable\n" +
|
|
"path and use live credentials for a text that actually arrives.\n\n" +
|
|
"To see account details here, run this with the live pair from the Twilio\n" +
|
|
"Console dashboard instead."
|
|
);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (response.ok) {
|
|
console.log(` friendly_name: ${String(body.friendly_name)}`);
|
|
console.log(` status: ${String(body.status)}`);
|
|
console.log(` type: ${String(body.type)}`);
|
|
console.log(
|
|
"\nThe pair is valid and this is the account the send would bill. " +
|
|
'"type: Trial" can only send to verified numbers.'
|
|
);
|
|
} else {
|
|
console.log(` code: ${String(body.code)}`);
|
|
console.log(` message: ${String(body.message)}`);
|
|
console.log(
|
|
"\n401/20003 means the SID and token are not a matching pair. Test\n" +
|
|
"credentials are a matched pair of their own: Twilio Console -> Account ->\n" +
|
|
"API keys & tokens -> Test credentials. Take BOTH values from that block;\n" +
|
|
"the SID in the dashboard header belongs to the live pair."
|
|
);
|
|
}
|
|
process.exit(response.ok ? 0 : 1);
|