3box
Version:
Interact with user data
382 lines (306 loc) • 13 kB
JavaScript
;
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;
}()
};