UNPKG

@yubion-dev-team/yubion-fido2-server-sdk-js

Version:

This project is an SDK to use YubiOn FIDO2 Server Service from Node.js.

207 lines 8.16 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.AccessKeyAuthApiRequester = exports.DatetimeSignAuthApiRequester = exports.NonceSignAuthApiRequester = exports.SignAuthApiRequesterBase = exports.FssApiRequesterBase = void 0; exports.createApiRequester = createApiRequester; const yup = __importStar(require("yup")); const axiosBase = __importStar(require("axios")); const node_crypto_1 = require("node:crypto"); const fss_api_error_1 = require("../fss-api-error"); const set_cookie_parser_1 = require("set-cookie-parser"); function createApiRequester(config) { switch (config.apiAuthType) { case "NonceSignAuth": return new NonceSignAuthApiRequester(config); case "DatetimeSignAuth": return new DatetimeSignAuthApiRequester(config); case "AccessKeyAuth": return new AccessKeyAuthApiRequester(config); default: throw new Error("bad auth type."); } } class FssApiRequesterBase { axiosBase; config; constructor(config) { this.config = config; //If you wish to use a proxy server, use the environment variable `http_proxy` or `https_proxy`. this.axiosBase = axiosBase.create({ baseURL: config.endpoint, timeout: 60000, headers: { "Accept": "application/json", "Cache-Control": "no-cache", "Pragma": "no-cache", "Content-Type": "application/json", "User-Agent": config.agent, }, }); } async request(path, param, options) { return (await this.requestWithCookieResponse(path, param, options)).response; } async requestWithCookieResponse(path, param, options) { const schema = options?.schema; const withAuth = options?.withAuth === undefined ? true : options?.withAuth; const cookie = options?.cookie; let result; const body = Buffer.from(JSON.stringify(param)); const additionalHeaders = withAuth ? await this.getAdditionalHeaders(body) : {}; if (cookie) { additionalHeaders["cookie"] = cookie; } try { result = await this.axiosBase.post(path, body, { headers: additionalHeaders }); } catch (ex) { throw new fss_api_error_1.FssApiError("axios error", { cause: ex, appStatus: "COMMUNICATION_FAILED" }); } if (result.status !== 200) { throw new fss_api_error_1.FssApiError("bad server response code.", { appStatus: "COMMUNICATION_FAILED", appSubStatus: { info: { httpStatus: result.status, } } }); } let resData; try { if (typeof (result.data) === 'string') { resData = JSON.parse(result.data); } else { resData = result.data; } } catch (ex) { throw new fss_api_error_1.FssApiError("bad json response.", { cause: ex, appStatus: "COMMUNICATION_FAILED" }); } if (resData.appStatus != "OK") { throw new fss_api_error_1.FssApiError("server response:" + resData.appStatus, { appStatus: resData.appStatus, appSubStatus: resData.appSubStatus }); } let response; if (schema) { response = schema.cast(resData.data); } else { response = resData.data; } let respCookie = undefined; if (result.headers["set-cookie"]) { respCookie = (0, set_cookie_parser_1.parse)(result.headers["set-cookie"], { map: false }).map(c => c.name + "=" + c.value).join("; "); } const ret = { cookie: respCookie, response, }; return ret; } async getAdditionalHeaders(body) { return { "X-Fss-Rp-Id": this.config.rpId, "X-Fss-Api-Auth-Id": this.config.apiAuthId, }; } } exports.FssApiRequesterBase = FssApiRequesterBase; const keyPrm = { name: "ECDSA", namedCurve: "P-256", }; class SignAuthApiRequesterBase extends FssApiRequesterBase { privateKey; constructor(config) { super(config); } async getPrivateKey() { if (!this.privateKey) { this.privateKey = await crypto.subtle.importKey("pkcs8", Buffer.from(this.config.secretKey, "base64url"), keyPrm, true, ["sign"]); } return this.privateKey; } async getAdditionalHeaders(body) { const key = await this.getPrivateKey(); const headers = await super.getAdditionalHeaders(body); const signTargetInfo = await this.getSignInfo(body); const bodyHash = await (0, node_crypto_1.createHash)("SHA-256").update(body).digest(); const signTarget = Buffer.concat([signTargetInfo.signTargetPrefix, bodyHash]); const signature = await crypto.subtle.sign({ ...keyPrm, hash: "SHA-256" }, key, signTarget); headers["X-Fss-Auth-Signature"] = Buffer.from(signature).toString("base64url"); headers["X-Fss-Auth-Body-Hash"] = bodyHash.toString("base64url"); Object.keys(signTargetInfo.additionalHeaders).forEach((x) => headers[x] = signTargetInfo.additionalHeaders[x]); return headers; } } exports.SignAuthApiRequesterBase = SignAuthApiRequesterBase; class NonceSignAuthApiRequester extends SignAuthApiRequesterBase { constructor(config) { super(config); } async getSignInfo(body) { const nonceResp = await this.request("getNonce", {}, { schema: yup.object().shape({ nonce: yup.string() }), withAuth: false }); return { signTargetPrefix: Buffer.from(nonceResp.nonce, "utf-8"), additionalHeaders: { "X-Fss-Auth-Nonce": nonceResp.nonce, } }; } } exports.NonceSignAuthApiRequester = NonceSignAuthApiRequester; class DatetimeSignAuthApiRequester extends SignAuthApiRequesterBase { constructor(config) { super(config); } async getSignInfo(body) { const now = (new Date()).toISOString(); return { signTargetPrefix: Buffer.from(now, "utf-8"), additionalHeaders: { "X-Fss-Auth-Request-Time": now, } }; } } exports.DatetimeSignAuthApiRequester = DatetimeSignAuthApiRequester; class AccessKeyAuthApiRequester extends FssApiRequesterBase { constructor(config) { super(config); } async getAdditionalHeaders(body) { const headers = await super.getAdditionalHeaders(body); return { ...headers, "X-Fss-Auth-Access-Key": this.config.secretKey, }; } } exports.AccessKeyAuthApiRequester = AccessKeyAuthApiRequester; //# sourceMappingURL=fss-api-requester.js.map