Skip to content

Instantly share code, notes, and snippets.

@strefethen
Last active May 21, 2023 04:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save strefethen/dea0043ec21e0758233ad24e362e8e0a to your computer and use it in GitHub Desktop.
Save strefethen/dea0043ec21e0758233ad24e362e8e0a to your computer and use it in GitHub Desktop.
TypeScript code demonstrating authenticating to and calling a MassDOT API
// Usage:
// 1. Request API access here: https://www.mass.gov/service-details/highway-data-for-developers
// 2. When your account details arrive create 3 environment vars
// MASSDOT_USERNAME
// MASSDOT_PASSWORD
// MASSDOT_SECRET_KEY
// 3. ts-node massdot.ts
import dotenv from "dotenv";
import fetch, { RequestInit } from 'node-fetch';
import crypto from 'crypto';
// This file demostrates how to call the MassDot API using the credentials in the .env file.
// Swagger doc is available here: https://data-api.massgotime.com/index.html
// To call the MassDOT APIs you must first request a token from /auth-token then
// follow a six (!!) step process as described in the /auth-token docs and illustrated below.
dotenv.config({ path: ".env" });
function log(s) {
// Uncomment for debug output
// console.log(s);
}
log(`Username: ${process.env.MASSDOT_USERNAME}`);
log(`Password: ${process.env.MASSDOT_PASSWORD}`);
log(`Secret: ${process.env.MASSDOT_SECRET_KEY}`);
const basic = `${process.env.MASSDOT_USERNAME}:${process.env.MASSDOT_PASSWORD}`;
log(`Basic string: ${basic}`);
const authBasic = `Basic ${Buffer.from(basic).toString("base64")}`;
log(`Base64: ${authBasic}`);
log(authBasic);
const fetchOptions: RequestInit = {
method: "GET",
timeout: 5000,
headers: {
Authorization: authBasic,
Accept: "application/json",
}
}
fetch("https://data-api.massgotime.com/auth-token", fetchOptions)
.then((res) => res.ok ? res.json() : Promise.reject(res))
.then((data) => {
// Step 1: Concatenate the user's secret key with the token provided herein, separated by a colon. ('SecretKey:token')
let step1 = `${process.env.MASSDOT_SECRET_KEY}:${data.token}`;
log(`Step 1: ${step1}`);
// Step 2: Create a SHA256 hash of the concatenated string. (i.e. SHA256(secretKey:token))
let step2 = crypto.createHash('sha256').update(step1);
log(`Step 2: create SHA256 hash of ${step1}`);
// Step 3: Convert the generated hash to a hexadecimal string representation
let step3 = step2.digest('hex');
log(`Step 3: ${step3}`);
// Step 4: Concatenate the user's username with the hexadecimal hash, separated by a colon. ('username:hexadecimalHash')
let step4 = `${process.env.MASSDOT_USERNAME}:${step3}`;
log(`Step 4: ${step4}`);
// Step 5: Create the base-64 string representation of the concatenation. (Base64('username:hexadecimalHash'))
let step5 = Buffer.from(step4).toString("base64");
log(`Bearer ${step5}`);
// Step 6: The result is the signature required for Bearer type authorization. (Authorization Bearer 'generated signature')
fetchOptions.headers["Authorization"] = `Bearer ${step5}`;
fetch("https://data-api.massgotime.com/v1/inventory/signs", fetchOptions)
.then((res) => res.ok ? res.json() : Promise.reject(res))
.then((data) => {
console.log(JSON.stringify(data, null, 2));
}).catch((err) => {
log(`Error: ${err}`);
});
}).catch((err) => {
console.error(err);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment