UNPKG

3box

Version:
382 lines (306 loc) 13 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var _require = require('./index'), fetchText = _require.fetchText, getMessageConsent = _require.getMessageConsent; var didJWT = require('did-jwt'); var _require2 = require('@ethersproject/wallet'), verifyMessage = _require2.verifyMessage; var config = require('../config.js'); var utils = require('./index'); var _require3 = require('did-resolver'), Resolver = _require3.Resolver; var get3IdResolver = require('3id-resolver').getResolver; var getMuportResolver = require('muport-did-resolver').getResolver; var getHttpsResolver = require('https-did-resolver')["default"]; var PROFILE_SERVER_URL = config.profile_server_url; // Mocks ipfs obj for 3id resolve, to resolve through api, until ipfs instance is available var ipfs = { dag: { get: function () { var _get = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(cid) { var req; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: req = "".concat(PROFILE_SERVER_URL, "/did-doc?cid=").concat(encodeURIComponent(cid)); return _context.abrupt("return", utils.fetchJson(req)); case 2: case "end": return _context.stop(); } } }, _callee); })); function get(_x) { return _get.apply(this, arguments); } return get; }() } }; var resolver = new Resolver(_objectSpread(_objectSpread(_objectSpread({}, get3IdResolver(ipfs, { pin: false })), getMuportResolver()), getHttpsResolver())); module.exports = { /** * Verifies that the gist contains the given 3ID and returns the users github username. * Throws an error otherwise. * * @param {String} did The 3ID of the user (or array of equivalent dids) * @param {Object} gistUrl URL of the proof * @return {Object} Object containing username, and proof */ verifyGithub: function () { var _verifyGithub = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(did, gistUrl) { var dids, gistFileContent, includeDid, username; return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: dids = typeof did === 'string' ? [did] : did; if (!(!gistUrl || gistUrl.trim() === '')) { _context2.next = 3; break; } return _context2.abrupt("return", null); case 3: _context2.next = 5; return fetchText(gistUrl); case 5: gistFileContent = _context2.sent; includeDid = dids.reduce(function (acc, val) { return acc || gistFileContent.indexOf(val) !== -1; }, false); if (includeDid) { _context2.next = 9; break; } throw new Error('Gist File provided does not contain the correct DID of the user'); case 9: username = gistUrl.split('/')[3]; return _context2.abrupt("return", { username: username, proof: gistUrl }); case 11: case "end": return _context2.stop(); } } }, _callee2); })); function verifyGithub(_x2, _x3) { return _verifyGithub.apply(this, arguments); } return verifyGithub; }(), /** * Verifies that the tweet contains the given 3ID and returns the users twitter username. * Throws an error otherwise. * * @param {String} did The 3ID of the user (or array of equivalent dids) * @param {String} claim A did-JWT with claim * @return {Object} Object containing username, proof, and the verifier */ verifyTwitter: function () { var _verifyTwitter = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(did, claim) { var dids, verified, claimData; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: dids = typeof did === 'string' ? [did] : did; if (claim) { _context3.next = 3; break; } return _context3.abrupt("return", null); case 3: _context3.next = 5; return didJWT.verifyJWT(claim, { resolver: resolver }); case 5: verified = _context3.sent; if (dids.includes(verified.payload.sub)) { _context3.next = 8; break; } throw new Error('Verification not valid for given user'); case 8: claimData = verified.payload.claim; if (!(!claimData.twitter_handle || !claimData.twitter_proof)) { _context3.next = 11; break; } throw new Error('The claim for your twitter is not correct'); case 11: return _context3.abrupt("return", { username: claimData.twitter_handle, proof: claimData.twitter_proof, verifiedBy: verified.payload.iss }); case 12: case "end": return _context3.stop(); } } }, _callee3); })); function verifyTwitter(_x4, _x5) { return _verifyTwitter.apply(this, arguments); } return verifyTwitter; }(), /** * Verifies that the code entered by the user is the same one that was sent via email. * Throws an error otherwise. * * @param {String} did The 3ID of the user (or array of equivalent dids) * @param {String} claim A did-JWT with claim * @return {Object} Object containing username, proof, and the verifier */ verifyEmail: function () { var _verifyEmail = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(did, claim) { var dids, verified, claimData; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: dids = typeof did === 'string' ? [did] : did; if (claim) { _context4.next = 3; break; } return _context4.abrupt("return", null); case 3: _context4.next = 5; return didJWT.verifyJWT(claim, { resolver: resolver }); case 5: verified = _context4.sent; if (dids.includes(verified.payload.sub)) { _context4.next = 8; break; } throw new Error('Verification not valid for given user'); case 8: claimData = verified.payload.claim; if (claimData.email_address) { _context4.next = 11; break; } throw new Error('The claim for your email address is not correct'); case 11: return _context4.abrupt("return", { email_address: claimData.email_address, verifiedBy: verified.payload.iss }); case 12: case "end": return _context4.stop(); } } }, _callee4); })); function verifyEmail(_x6, _x7) { return _verifyEmail.apply(this, arguments); } return verifyEmail; }(), /** * Verifies that the proof for a did is correct * * @param {String} claim A did-JWT with claim * @return {String} The DID of the user */ verifyDID: function () { var _verifyDID = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(claim) { var verified, muport, res, muportDID; return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: _context5.next = 2; return didJWT.verifyJWT(claim, { resolver: resolver }); case 2: verified = _context5.sent; muport = verified.payload.muport; res = {}; if (!muport) { _context5.next = 10; break; } _context5.next = 8; return didJWT.verifyJWT(muport, { resolver: resolver }); case 8: muportDID = _context5.sent.payload.iss; res.muport = muportDID; case 10: res.did = verified.payload.iss; return _context5.abrupt("return", res); case 12: case "end": return _context5.stop(); } } }, _callee5); })); function verifyDID(_x8) { return _verifyDID.apply(this, arguments); } return verifyDID; }(), /** * Verifies that the proof for an ethereum address is correct * * @param {Object} ethProof The claim generated by getLinkConsent * @param {string} ethProof.consent_msg * @param {string} ethProof.consent_signature * @param {string} ethProof.linked_did * @param {String} did The box' did * @return {String} The ethereum address used to sign the message */ verifyEthereum: function () { var _verifyEthereum = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(ethProof, did) { var dids, consentMsg, consentSig, expected; return _regenerator["default"].wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: dids = typeof did === 'string' ? [did] : did; // TODO - is this function needed? Can it be removed in // favour of proofs that are in the rootstore? consentMsg = ethProof.version ? ethProof.message : ethProof['consent_msg']; consentSig = ethProof.version ? ethProof.signature : ethProof['consent_signature']; // Make sure the message matches our expectation expected = getMessageConsent(did); if (!(consentMsg !== expected)) { _context6.next = 6; break; } throw new Error("Invalid consent message, got: \"".concat(consentMsg, "\", expected: \"").concat(expected, "\"")); case 6: return _context6.abrupt("return", verifyMessage(consentMsg, consentSig)); case 7: case "end": return _context6.stop(); } } }, _callee6); })); function verifyEthereum(_x9, _x10) { return _verifyEthereum.apply(this, arguments); } return verifyEthereum; }() };