UNPKG

fsl-js-sdk

Version:
235 lines (234 loc) 13 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var request_1 = require("../api/request"); var browser_1 = require("@simplewebauthn/browser"); var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; // Use a lookup table to find the index. var lookup = new Uint8Array(256); for (var i = 0; i < chars.length; i++) { lookup[chars.charCodeAt(i)] = i; } var WebAuthn = /** @class */ (function () { function WebAuthn() { this.registerPath = 'account/webauthn/register'; this.loginPath = 'account/webauthn/login'; this.callbackPath = 'account/webauthn/callback'; this.base64ToBuffer = function (base64string) { if (base64string) { var bufferLength = (base64string.length * 0.75) | 0; var len = base64string.length; var i = void 0; var p = 0; var encoded1 = void 0; var encoded2 = void 0; var encoded3 = void 0; var encoded4 = void 0; var bytes = new Uint8Array(bufferLength); for (i = 0; i < len; i += 4) { encoded1 = lookup[base64string.charCodeAt(i)]; encoded2 = lookup[base64string.charCodeAt(i + 1)]; encoded3 = lookup[base64string.charCodeAt(i + 2)]; encoded4 = lookup[base64string.charCodeAt(i + 3)]; bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); } return bytes.buffer; } }; this.initUrl(); } WebAuthn.prototype.initUrl = function () { if (window.ApiPath) { var last = window.ApiPath.charAt(window.ApiPath.length - 1); if (last !== '/') { this.registerPath = '/' + this.registerPath; this.loginPath = '/' + this.loginPath; this.callbackPath = '/' + this.callbackPath; } this.registerPath = window.ApiPath + this.registerPath; this.loginPath = window.ApiPath + this.loginPath; this.callbackPath = window.ApiPath + this.callbackPath; } else { this.registerPath = '/account/webauthn/register'; this.loginPath = 'account/webauthn/login'; this.callbackPath = 'account/webauthn/callback'; } }; WebAuthn.prototype.register = function (opt) { return __awaiter(this, void 0, void 0, function () { var self, responseData, i, credential, callbackUrl, callbackResponse, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: self = this; if (!self.registerPath) { // eslint-disable-next-line prefer-promise-reject-errors return [2 /*return*/, Promise.reject('Register path missing from the initial configuration!')]; } _a.label = 1; case 1: _a.trys.push([1, 5, , 6]); return [4 /*yield*/, request_1.request.post(self.registerPath)]; case 2: responseData = _a.sent(); responseData.challenge = this.base64ToBuffer(responseData.challenge); responseData.user.id = this.base64ToBuffer(responseData.user.id); if (responseData.excludeCredentials) { for (i = 0; i < responseData.excludeCredentials.length; i++) { responseData.excludeCredentials[i].id = this.base64ToBuffer(responseData.excludeCredentials[i].id); } } return [4 /*yield*/, navigator.credentials.create({ publicKey: __assign(__assign({}, responseData), { rp: { name: location.hostname } }), signal: browser_1.WebAuthnAbortService.createNewAbortSignal(), })]; case 3: credential = _a.sent(); callbackUrl = (opt === null || opt === void 0 ? void 0 : opt.platform) ? "".concat(self.callbackPath, "?platformCode=").concat(opt.platform, "&withToken=1") : self.callbackPath; return [4 /*yield*/, request_1.request.post(callbackUrl, { credential: { id: credential.id, rawId: (0, browser_1.bufferToBase64URLString)(credential.rawId), response: { attestationObject: (0, browser_1.bufferToBase64URLString)(credential.response.attestationObject), clientDataJSON: (0, browser_1.bufferToBase64URLString)(credential.response.clientDataJSON), }, type: credential.type, }, challenge: (0, browser_1.bufferToBase64URLString)(responseData.challenge), })]; case 4: callbackResponse = _a.sent(); return [2 /*return*/, typeof callbackResponse === 'object' ? __assign(__assign({}, callbackResponse), { credentialId: credential.id }) : { tokenPwd: callbackResponse, credentialId: credential.id, }]; case 5: error_1 = _a.sent(); return [2 /*return*/, error_1]; case 6: return [2 /*return*/]; } }); }); }; WebAuthn.prototype.login = function (opt) { return __awaiter(this, void 0, void 0, function () { var self, responseData, i, credential, callbackUrl, callbackResponse, error_2; return __generator(this, function (_a) { switch (_a.label) { case 0: self = this; if (!self.loginPath) { // eslint-disable-next-line prefer-promise-reject-errors return [2 /*return*/, Promise.reject('Login path missing from the initial configuration!')]; } _a.label = 1; case 1: _a.trys.push([1, 5, , 6]); return [4 /*yield*/, request_1.request.post(self.loginPath)]; case 2: responseData = _a.sent(); responseData.challenge = this.base64ToBuffer(responseData.challenge); if (opt.credentialId) { responseData.allowCredentials = [ { id: this.base64ToBuffer(opt.credentialId), type: 'public-key', }, ]; } else if (responseData.allowCredentials) { for (i = 0; i < responseData.allowCredentials.length; i++) { responseData.allowCredentials[i].id = this.base64ToBuffer(responseData.allowCredentials[i].id); } } return [4 /*yield*/, navigator.credentials.get({ publicKey: responseData, mediation: opt.mediation, signal: browser_1.WebAuthnAbortService.createNewAbortSignal(), })]; case 3: credential = _a.sent(); callbackUrl = opt.platform ? "".concat(self.callbackPath, "?platformCode=").concat(opt.platform) : self.callbackPath; return [4 /*yield*/, request_1.request.post(callbackUrl, { credential: { id: credential.id, rawId: (0, browser_1.bufferToBase64URLString)(credential.rawId), response: { clientDataJSON: (0, browser_1.bufferToBase64URLString)(credential.response.clientDataJSON), authenticatorData: (0, browser_1.bufferToBase64URLString)(credential.response.authenticatorData), signature: (0, browser_1.bufferToBase64URLString)(credential.response.signature), userHandle: (0, browser_1.bufferToBase64URLString)(credential.response.userHandle), }, type: credential.type, }, challenge: (0, browser_1.bufferToBase64URLString)(responseData.challenge), })]; case 4: callbackResponse = _a.sent(); return [2 /*return*/, __assign(__assign({}, callbackResponse), { credentialId: credential.id })]; case 5: error_2 = _a.sent(); return [2 /*return*/, error_2]; case 6: return [2 /*return*/]; } }); }); }; return WebAuthn; }()); exports.default = WebAuthn;