Last active
May 21, 2023 04:59
-
-
Save strefethen/dea0043ec21e0758233ad24e362e8e0a to your computer and use it in GitHub Desktop.
TypeScript code demonstrating authenticating to and calling a MassDOT API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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