@baqhub/sdk
Version:
The official JavaScript SDK for the BAQ federated app platform.
79 lines (78 loc) • 2.68 kB
JavaScript
import { Constants } from "../../constants.js";
import * as IO from "../../helpers/io.js";
import { sign } from "../../helpers/signature.js";
import { Str } from "../../helpers/string.js";
import { RHttpSignatureHeader, } from "./httpSignatureHeader.js";
//
// Model.
//
var HttpSignaturePrefix;
(function (HttpSignaturePrefix) {
HttpSignaturePrefix["REQUEST"] = "baq.request";
HttpSignaturePrefix["RESPONSE"] = "baq.response";
})(HttpSignaturePrefix || (HttpSignaturePrefix = {}));
const RHttpSignaturePrefix = IO.weakEnumeration(HttpSignaturePrefix);
//
// I/O.
//
function signatureToHeader(signature) {
const pairs = [
["id", signature.id],
["ts", signature.timestamp.toString()],
["nonce", signature.nonce],
["headers", signature.headers.map(RHttpSignatureHeader.encode).join(",")],
["signature", IO.base64Bytes.encode(signature.signature)],
];
const pairsString = pairs.map(([k, v]) => `${k}="${v}"`).join(" ");
return `${Constants.httpSignaturePrefix} ${pairsString}`;
}
//
// Sign and Validate.
//
function buildSignatureString(prefix, signature, input) {
const prefixString = RHttpSignaturePrefix.encode(prefix);
const headersString = signature.headers
.map(header => {
const headerKey = RHttpSignatureHeader.encode(header);
const headerValue = input.headerValues.get(header) || "";
return `${headerKey}=${headerValue}\n`;
})
.join("");
return [
prefixString,
signature.timestamp,
signature.nonce,
input.authorizationId || "",
input.method,
input.pathAndQuery,
input.host,
input.port,
headersString,
].join("\n");
}
function httpSign(prefix, appRecordId, privateKey, input) {
const initialSignature = {
id: appRecordId,
timestamp: Date.now(),
nonce: Str.random(8),
headers: [...input.headerValues.keys()],
signature: new Uint8Array(0),
};
const signatureString = buildSignatureString(prefix, initialSignature, input);
const signatureBytes = sign(privateKey, IO.decode(IO.utf8Bytes, signatureString));
return {
...initialSignature,
signature: signatureBytes,
};
}
function signatureForRequest(appRecordId, privateKey, input) {
return httpSign(HttpSignaturePrefix.REQUEST, appRecordId, privateKey, input);
}
function signatureForResponse(appRecordId, privateKey, input) {
return httpSign(HttpSignaturePrefix.RESPONSE, appRecordId, privateKey, input);
}
export const HttpSignature = {
request: signatureForRequest,
response: signatureForResponse,
toHeader: signatureToHeader,
};