New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

uport

Package Overview
Dependencies
Maintainers
4
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

uport - npm Package Compare versions

Comparing version 0.6.2 to 0.7.0-alpha-1

lib/__tests__/__snapshots__/Credentials-test.js.snap

27

lib/Contract.js

@@ -6,7 +6,22 @@ 'use strict';

});
exports.Contract = exports.ContractFactory = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var arrayContainsArray = require('ethjs-util').arrayContainsArray;

@@ -18,4 +33,4 @@

var txObjectProperties = ['from', 'to', 'data', 'value', 'gasPrice', 'gas'];
if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) === 'object' && Array.isArray(args) === true && args.length > 0) {
if (_typeof(args[args.length - 1]) === 'object' && (Object.keys(args[args.length - 1]).length === 0 || arrayContainsArray(Object.keys(args[args.length - 1]), txObjectProperties, true))) {
if ((typeof args === 'undefined' ? 'undefined' : (0, _typeof3.default)(args)) === 'object' && Array.isArray(args) === true && args.length > 0) {
if ((0, _typeof3.default)(args[args.length - 1]) === 'object' && ((0, _keys2.default)(args[args.length - 1]).length === 0 || arrayContainsArray((0, _keys2.default)(args[args.length - 1]), txObjectProperties, true))) {
return true;

@@ -86,3 +101,3 @@ }

if (hasTransactionObject(methodArgs)) providedTxObject = methodArgs.pop();
var methodTxObject = Object.assign({}, providedTxObject, {
var methodTxObject = (0, _assign2.default)({}, providedTxObject, {
to: self.address

@@ -96,3 +111,3 @@ });

var extendArgs = methodArgs.slice(methodObject.inputs.length);
return extend.apply(undefined, [methodTxObject].concat(_toConsumableArray(extendArgs)));
return extend.apply(undefined, [methodTxObject].concat((0, _toConsumableArray3.default)(extendArgs)));
}

@@ -99,0 +114,0 @@ };

@@ -7,12 +7,40 @@ 'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _typeof2 = require('babel-runtime/helpers/typeof');
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _typeof3 = _interopRequireDefault(_typeof2);
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _keys = require('babel-runtime/core-js/object/keys');
var _JWT = require('./JWT');
var _keys2 = _interopRequireDefault(_keys);
var _jsontokens = require('jsontokens');
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _didJwt = require('did-jwt');
var _uportLite = require('uport-lite');

@@ -34,6 +62,19 @@

var _uportDidResolver = require('uport-did-resolver');
var _uportDidResolver2 = _interopRequireDefault(_uportDidResolver);
var _ethrDidResolver = require('ethr-did-resolver');
var _ethrDidResolver2 = _interopRequireDefault(_ethrDidResolver);
var _Digest = require('did-jwt/lib/Digest');
var _elliptic = require('elliptic');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var MNID = require('mnid');
var secp256k1 = new _elliptic.ec('secp256k1');
/**

@@ -45,2 +86,3 @@ * The Credentials class allows you to easily create the signed payloads used in uPort inlcuding

*/
var Credentials = function () {

@@ -51,71 +93,132 @@

*
* The following example is just for testing purposes. You should never store a private key in source code.
*
* @example
* import { Credentials, SimpleSigner } from 'uport'
* const networks = { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', registry: '0x0101.... }}
* const setttings = { networks, address: '5A8bRWU3F7j3REx3vkJ...', signer: new SimpleSigner(process.env.PRIVATE_KEY)}
* const credentials = new Credentials(settings)
* import { Credentials } from 'uport'
* const credentials = new Credentials({
* privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
* })
*
* The above example derives the public key used to generate the did, so only a private key is needed.
* Generating a public key from a private key is slow. It is recommended to configure the `did` option as well.
*
* @example
* import { Credentials } from 'uport'
* const credentials = new Credentials()
* const credentials = new Credentials({
* did: 'did:ethr:0xbc3ae59bc76f894822622cdef7a2018dbe353840',
* privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
* })
*
* It is recommended to store the address and private key in environment variables for your server application
*
* @example
* import { Credentials, SimpleSigner } from 'uport'
* const credentials = new Credentials({
* did: process.env.APPLICATION_DID,
* signer: SimpleSigner(process.env.PRIVATE_KEY)
* })
*
* Instead of a private key you can pass in a [Signer Functions](https://github.com/uport-project/did-jwt#signer-functions) to
* present UX or call a HSM.
* @example
* import { Credentials } from 'uport'
*
* function mySigner (data) {
* return new Promise((resolve, reject) => {
* const signature = /// sign it
* resolve(signature)
* })
* }
*
* const credentials = new Credentials({
* did: process.env.APPLICATION_DID,
* signer: mySigner
* })
*
* @param {Object} [settings] setttings
* @param {Object} settings.networks networks config object, ie. { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', address: '0x0101.... }}
* @param {UportLite} settings.registry a registry object from UportLite
* @param {SimpleSigner} settings.signer a signer object, see SimpleSigner.js
* @param {Address} settings.address your uPort address (may be the address of your application's uPort identity)
* @param {DID} settings.did Application [DID](https://w3c-ccg.github.io/did-spec/#decentralized-identifiers-dids) (unique identifier) for your application
* @param {String} settings.privateKey A hex encoded 32 byte private key
* @param {SimpleSigner} settings.signer a signer object, see [Signer Functions](https://github.com/uport-project/did-jwt#signer-functions)
* @param {Object} settings.ethrConfig Configuration object for ethr did resolver. See [ethr-did-resolver](https://github.com/uport-project/ethr-did-resolver)
* @param {Address} settings.address DEPRECATED your uPort address (may be the address of your application's uPort identity)
* @param {Object} settings.networks DEPRECATED networks config object, ie. { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', address: '0x0101.... }}
* @param {UportLite} settings.registry DEPRECATED a registry object from UportLite
* @return {Credentials} self
*/
function Credentials() {
var settings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this = this;
_classCallCheck(this, Credentials);
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
did = _ref.did,
address = _ref.address,
privateKey = _ref.privateKey,
signer = _ref.signer,
networks = _ref.networks,
registry = _ref.registry,
ethrConfig = _ref.ethrConfig;
this.settings = settings;
this.settings.networks = settings.networks ? configNetworks(settings.networks) : {};
if (!this.settings.registry) {
var registry = (0, _uportLite2.default)({ networks: this.settings.networks });
this.settings.registry = function (address) {
return new Promise(function (resolve, reject) {
registry(address, function (error, profile) {
if (error) return reject(error);
resolve(profile);
});
});
};
(0, _classCallCheck3.default)(this, Credentials);
if (signer) {
this.signer = signer;
} else if (privateKey) {
this.signer = (0, _didJwt.SimpleSigner)(privateKey);
}
if (did) {
this.did = did;
} else if (address) {
if (MNID.isMNID(address)) {
this.did = 'did:uport:' + address;
}
if (address.match('^0x[0-9a-fA-F]{40}$')) {
this.did = 'did:ethr:' + address;
}
} else if (privateKey) {
var kp = secp256k1.keyFromPrivate(privateKey);
var _address = (0, _Digest.toEthereumAddress)(kp.getPublic('hex'));
this.did = 'did:ethr:' + _address;
}
this.signJWT = function (payload, expiresIn) {
return (0, _didJwt.createJWT)(payload, { issuer: _this.did, signer: _this.signer, alg: _this.did.match('^did:uport:') ? 'ES256K' : 'ES256K-R', expiresIn: expiresIn });
};
(0, _uportDidResolver2.default)(registry || (0, _uportLite2.default)({ networks: networks ? configNetworks(networks) : {} }));
(0, _ethrDidResolver2.default)(ethrConfig || {});
}
/**
* Creates a signed request token (JWT) given a request params object.
*
* @example
* const req = { requested: ['name', 'country'],
* callbackUrl: 'https://myserver.com',
* notifications: true }
* credentials.createRequest(req).then(jwt => {
* ...
* })
requested: ['name','phone','identity_no'],
callbackUrl: 'https://....' // URL to send the response of the request to
notifications: true
*
* @param {Object} [params={}] request params object
* @param {Array} params.requested an array of attributes for which you are requesting credentials to be shared for
* @param {Array} params.verified an array of attributes for which you are requesting verified credentials to be shared for
* @param {Boolean} params.notifications boolean if you want to request the ability to send push notifications
* @param {String} params.callbackUrl the url which you want to receive the response of this request
* @param {String} params.network_id network id of Ethereum chain of identity eg. 0x4 for rinkeby
* @param {String} params.accountType Ethereum account type: "general", "segregated", "keypair", "devicekey" or "none"
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
* generate a DID and private key
*/
_createClass(Credentials, [{
key: 'createRequest',
value: function createRequest() {
(0, _createClass3.default)(Credentials, [{
key: 'requestDisclosure',
/**
* Creates a [Selective Disclosure Request JWT](https://github.com/uport-project/specs/blob/develop/messages/sharereq.md)
*
* @example
* const req = { requested: ['name', 'country'],
* callbackUrl: 'https://myserver.com',
* notifications: true }
* credentials.requestDisclosure(req).then(jwt => {
* ...
* })
*
* @param {Object} [params={}] request params object
* @param {Array} params.requested an array of attributes for which you are requesting credentials to be shared for
* @param {Array} params.verified an array of attributes for which you are requesting verified credentials to be shared for
* @param {Boolean} params.notifications boolean if you want to request the ability to send push notifications
* @param {String} params.callbackUrl the url which you want to receive the response of this request
* @param {String} params.network_id network id of Ethereum chain of identity eg. 0x4 for rinkeby
* @param {String} params.accountType Ethereum account type: "general", "segregated", "keypair", "devicekey" or "none"
* @param {Number} expiresIn Seconds until expiry
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
*/
value: function requestDisclosure() {
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var expiresIn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 600;

@@ -138,22 +241,174 @@ var payload = {};

}
if (params.accountType && ['general', 'segregated', 'keypair', 'devicekey', 'none'].indexOf(params.accountType) >= 0) {
payload.act = params.accountType;
if (params.accountType) {
if (['general', 'segregated', 'keypair', 'devicekey', 'none'].indexOf(params.accountType) >= 0) {
payload.act = params.accountType;
} else {
return _promise2.default.reject(new Error('Unsupported accountType ' + params.accountType));
}
}
if (params.exp) {
//checks for expiration on requests, if none is provided the default is 10 min
payload.exp = params.exp;
} else {
payload.exp = Math.floor(Date.now() / 1000) + 600;
}
return (0, _JWT.createJWT)(this.settings, _extends({}, payload, { type: 'shareReq' }));
return this.signJWT((0, _extends3.default)({}, payload, { type: 'shareReq' }), params.exp ? undefined : expiresIn);
}
/**
* Creates a [Selective Disclosure Request JWT](https://github.com/uport-project/specs/blob/develop/messages/sharereq.md)
*
* @example
* const req = { requested: ['name', 'country'],
* callbackUrl: 'https://myserver.com',
* notifications: true }
* credentials.createRequest(req).then(jwt => {
* ...
* })
*
* @param {Object} [params={}] request params object
* @param {Array} params.requested an array of attributes for which you are requesting credentials to be shared for
* @param {Array} params.verified an array of attributes for which you are requesting verified credentials to be shared for
* @param {Boolean} params.notifications boolean if you want to request the ability to send push notifications
* @param {String} params.callbackUrl the url which you want to receive the response of this request
* @param {String} params.network_id network id of Ethereum chain of identity eg. 0x4 for rinkeby
* @param {String} params.accountType Ethereum account type: "general", "segregated", "keypair", "devicekey" or "none"
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
* @deprecated
*/
}, {
key: 'createRequest',
value: function createRequest() {
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return this.requestDisclosure(params);
}
/**
* Receive signed response token from mobile app. Verifies and parses the given response token.
* Creates a [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md).
*
* This can either be used to share information about the signing identity or as the response to a
* [Selective Disclosure Flow](https://github.com/uport-project/specs/blob/develop/flows/selectivedisclosure.md), where it can be used to authenticate the identity.
*
* @example
* credentials.disclose({own: {name: 'Lourdes Valentina Gomez'}}).then(jwt => {
* ...
* })
*
* @param {Object} [params={}] request params object
* @param {JWT} params.req A selective disclosure Request JWT if this is returned as part of an authentication flow
* @param {Object} params.own An object of self attested claims about the signer (eg. name etc)
* @param {Array} params.verified An array of attestation JWT's to include
* @param {MNID} params.nad An ethereum address encoded as an [MNID](https://github.com/uport-project/mnid)
* @param {Array} params.capabilities An array of capability JWT's to include
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
*/
}, {
key: 'disclose',
value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var expiresIn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 600;
var verified;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!payload.req) {
_context.next = 5;
break;
}
_context.next = 3;
return (0, _didJwt.verifyJWT)(payload.req);
case 3:
verified = _context.sent;
if (verified.issuer) {
payload.aud = verified.issuer;
}
case 5:
return _context.abrupt('return', this.signJWT((0, _extends3.default)({}, payload, { type: 'shareResp' }), expiresIn));
case 6:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function disclose() {
return _ref2.apply(this, arguments);
}
return disclose;
}()
}, {
key: 'processDisclosurePayload',
value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(_ref3) {
var _this2 = this;
var doc = _ref3.doc,
payload = _ref3.payload;
var credentials, verified;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
credentials = (0, _extends3.default)({}, doc.uportProfile || {}, payload.own || {}, payload.capabilities && payload.capabilities.length === 1 ? { pushToken: payload.capabilities[0] } : {}, { address: payload.iss });
if (payload.nad) {
credentials.networkAddress = payload.nad;
}
if (payload.dad) {
credentials.deviceKey = payload.dad;
}
if (!payload.verified) {
_context2.next = 10;
break;
}
_context2.next = 6;
return _promise2.default.all(payload.verified.map(function (token) {
return (0, _didJwt.verifyJWT)(token, { audience: _this2.did });
}));
case 6:
verified = _context2.sent;
return _context2.abrupt('return', (0, _extends3.default)({}, credentials, { verified: verified.map(function (v) {
return (0, _extends3.default)({}, v.payload, { jwt: v.jwt });
}) }));
case 10:
return _context2.abrupt('return', credentials);
case 11:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function processDisclosurePayload(_x7) {
return _ref4.apply(this, arguments);
}
return processDisclosurePayload;
}()
/**
* Authenticates [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md) from mobile
* app as part of the [Selective Disclosure Flow](https://github.com/uport-project/specs/blob/develop/flows/selectivedisclosure.md).
*
* It Verifies and parses the given response token and verifies the challenge response flow.
*
* @example
* const resToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJyZXF1Z....'
* credentials.receive(resToken).then(res => {
* credentials.authenticate(resToken).then(res => {
* const credentials = res.verified
const name = res.name
* const name = res.name
* ...

@@ -168,50 +423,138 @@ * })

}, {
key: 'authenticate',
value: function () {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(token) {
var callbackUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var _ref6, payload, doc, challenge;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return (0, _didJwt.verifyJWT)(token, { audience: this.did, callbackUrl: callbackUrl, auth: true });
case 2:
_ref6 = _context3.sent;
payload = _ref6.payload;
doc = _ref6.doc;
if (!payload.req) {
_context3.next = 13;
break;
}
_context3.next = 8;
return (0, _didJwt.verifyJWT)(payload.req);
case 8:
challenge = _context3.sent;
if (!(challenge.payload.iss === this.did && challenge.payload.type === 'shareReq')) {
_context3.next = 11;
break;
}
return _context3.abrupt('return', this.processDisclosurePayload({ payload: payload, doc: doc }));
case 11:
_context3.next = 14;
break;
case 13:
throw new Error('Challenge was not included in response');
case 14:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
function authenticate(_x9) {
return _ref5.apply(this, arguments);
}
return authenticate;
}()
/**
* Receive signed response token from mobile app. Verifies and parses the given response token.
*
* @example
* const resToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJyZXF1Z....'
* credentials.receive(resToken).then(res => {
* const credentials = res.verified
const name = res.name
* ...
* })
*
* @param {String} token a response token
* @param {String} [callbackUrl=null] callbackUrl
* @return {Promise<Object, Error>} a promise which resolves with a parsed response or rejects with an error.
* @deprecated
*/
}, {
key: 'receive',
value: function receive(token) {
var _this = this;
var callbackUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
return (0, _JWT.verifyJWT)(this.settings, token, callbackUrl).then(function (_ref) {
var payload = _ref.payload,
profile = _ref.profile;
return this.authenticate(token, callbackUrl);
}
/**
* Verify and return profile from a [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md).
*
* The main difference between this and `authenticate()` is that it does not verify the challenge. This can be used to verify user profiles that have been shared
* through other methods such as QR codes and messages.
*
* @example
* const resToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJyZXF1Z....'
* credentials.verifyProfile(resToken).then(profile => {
* const credentials = profile.verified
const name = profile.name
* ...
* })
*
* @param {String} token a response token
* @return {Promise<Object, Error>} a promise which resolves with a parsed response or rejects with an error.
*/
function processPayload(settings) {
var credentials = _extends({}, profile, payload.own || {}, payload.capabilities && payload.capabilities.length === 1 ? { pushToken: payload.capabilities[0] } : {}, { address: payload.iss });
if (payload.nad) {
credentials.networkAddress = payload.nad;
}
if (payload.dad) {
credentials.deviceKey = payload.dad;
}
if (payload.verified) {
return Promise.all(payload.verified.map(function (token) {
return (0, _JWT.verifyJWT)(settings, token);
})).then(function (verified) {
return _extends({}, credentials, { verified: verified.map(function (v) {
return _extends({}, v.payload, { jwt: v.jwt });
}) });
});
} else {
return credentials;
}
}
}, {
key: 'verifyProfile',
value: function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(token) {
var _ref8, payload, doc;
if (_this.settings.signer) {
if (payload.req) {
return (0, _JWT.verifyJWT)(_this.settings, payload.req).then(function (challenge) {
if (challenge.payload.iss === _this.settings.address && challenge.payload.type === 'shareReq') {
return processPayload(_this.settings);
}
});
} else {
throw new Error('Challenge was not included in response');
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return (0, _didJwt.verifyJWT)(token, { audience: this.did });
case 2:
_ref8 = _context4.sent;
payload = _ref8.payload;
doc = _ref8.doc;
return _context4.abrupt('return', this.processDisclosurePayload({ payload: payload, doc: doc }));
case 6:
case 'end':
return _context4.stop();
}
}
} else {
return processPayload(_this.settings);
}
});
}
}, _callee4, this);
}));
function verifyProfile(_x11) {
return _ref7.apply(this, arguments);
}
return verifyProfile;
}()
/**

@@ -233,3 +576,3 @@ * Send a push notification to a user, consumes a token which allows you to send push notifications

var PUTUTU_URL = 'https://pututu.uport.space'; // TODO - change to .me
return new Promise(function (resolve, reject) {
return new _promise2.default(function (resolve, reject) {
var endpoint = '/api/v2/sns';

@@ -250,5 +593,5 @@ if (!token) {

}
var plaintext = padMessage(JSON.stringify(payload));
var plaintext = padMessage((0, _stringify2.default)(payload));
var enc = encryptMessage(plaintext, pubEncKey);
payload = { message: JSON.stringify(enc) };
payload = { message: (0, _stringify2.default)(enc) };
}

@@ -298,31 +641,38 @@

key: 'attest',
value: function attest(_ref2) {
var sub = _ref2.sub,
claim = _ref2.claim,
exp = _ref2.exp;
value: function attest(_ref9) {
var sub = _ref9.sub,
claim = _ref9.claim,
exp = _ref9.exp;
return (0, _JWT.createJWT)(this.settings, { sub: sub, claim: claim, exp: exp });
return this.signJWT({ sub: sub, claim: claim, exp: exp });
}
/**
* Look up a profile in the registry for a given uPort address. Address must be MNID encoded.
*
* @example
* credentials.lookup('5A8bRWU3F7j3REx3vkJ...').then(profile => {
* const name = profile.name
* const pubkey = profile.pubkey
* ...
* })
*
* @param {String} address a MNID encoded address
* @return {Promise<Object, Error>} a promise which resolves with parsed profile or rejects with an error
*/
// /**
// * Look up a profile in the registry for a given uPort address. Address must be MNID encoded.
// *
// * @example
// * credentials.lookup('5A8bRWU3F7j3REx3vkJ...').then(profile => {
// * const name = profile.name
// * const pubkey = profile.pubkey
// * ...
// * })
// *
// * @param {String} address a MNID encoded address
// * @return {Promise<Object, Error>} a promise which resolves with parsed profile or rejects with an error
// */
// lookup (address) {
// return this.settings.registry(address)
// }
}, {
key: 'lookup',
value: function lookup(address) {
return this.settings.registry(address);
}], [{
key: 'createIdentity',
value: function createIdentity() {
var kp = secp256k1.genKeyPair();
var publicKey = kp.getPublic('hex');
var privateKey = kp.getPrivate('hex');
var address = (0, _Digest.toEthereumAddress)(publicKey);
var did = 'did:ethr:' + address;
return { did: did, privateKey: privateKey };
}
}]);
return Credentials;

@@ -332,5 +682,5 @@ }();

var configNetworks = function configNetworks(nets) {
Object.keys(nets).forEach(function (key) {
(0, _keys2.default)(nets).forEach(function (key) {
var net = nets[key];
if ((typeof net === 'undefined' ? 'undefined' : _typeof(net)) === 'object') {
if ((typeof net === 'undefined' ? 'undefined' : (0, _typeof3.default)(net)) === 'object') {
['registry', 'rpcUrl'].forEach(function (key) {

@@ -337,0 +687,0 @@ if (!net.hasOwnProperty(key)) throw new Error('Malformed network config object, object must have \'' + key + '\' key specified.');

@@ -7,14 +7,8 @@ 'use strict';

var _SimpleSigner = require('./SimpleSigner');
var _didJwt = require('did-jwt');
var _SimpleSigner2 = _interopRequireDefault(_SimpleSigner);
var _Contract = require('./Contract');
var _JWT = require('./JWT');
var _JWT2 = _interopRequireDefault(_JWT);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
module.exports = { Credentials: _Credentials2.default, SimpleSigner: _SimpleSigner2.default, Contract: _Contract.Contract, ContractFactory: _Contract.ContractFactory, JWT: _JWT2.default };
module.exports = { Credentials: _Credentials2.default, SimpleSigner: _didJwt.SimpleSigner, Contract: _Contract.Contract, ContractFactory: _Contract.ContractFactory };
{
"name": "uport",
"version": "0.6.2",
"version": "0.7.0-alpha-1",
"description": "Library for interacting with uport profiles and attestations",

@@ -13,6 +13,7 @@ "main": "lib/index.js",

"scripts": {
"test": "jest",
"test": "./node_modules/.bin/jest",
"test:ci": "./node_modules/.bin/jest -u --coverage",
"build:es5": "./node_modules/.bin/babel src -d lib",
"build:browser": "./node_modules/.bin/webpack --config webpack.config.js",
"build": "yarn build:es5 && yarn test && yarn build:browser",
"build": "yarn build:es5 && yarn test:ci && yarn build:browser",
"build:docs:html": "./node_modules/.bin/jsdoc src/* README.md -d docs",

@@ -26,4 +27,6 @@ "build:docs:md": "./node_modules/jsdoc-to-markdown/bin/cli.js src/* > DOCS.md",

"dependencies": {
"did-jwt": "^0.0.7",
"did-resolver": "^0.0.4",
"ethjs-util": "^0.1.3",
"jsontokens": "^0.7.6",
"ethr-did-resolver": "^0.0.7",
"mnid": "^0.1.1",

@@ -33,24 +36,26 @@ "nets": "^3.2.0",

"tweetnacl-util": "^0.15.0",
"uport-lite": "^1.0.0"
"uport-did-resolver": "^0.0.2",
"uport-lite": "^1.0.2"
},
"jest": {
"coverageDirectory": "./coverage/",
"collectCoverage": true,
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/nock"
]
],
"testEnvironment": "node"
},
"devDependencies": {
"babel-cli": "^6.22.2",
"babel-jest": "^18.0.0",
"babel-loader": "^6.2.10",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-jest": "^22.4.3",
"babel-loader": "^7.1.4",
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
"babel-plugin-transform-object-rest-spread": "^6.22.0",
"babel-plugin-transform-es2015-modules-umd": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.22.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.22.0",
"babel-register": "^6.22.0",
"babel-preset-env": "^1.6.1",
"body-parser": "^1.17.1",
"express": "^4.15.2",
"jest": "^18.1.0",
"jest": "^22.4.3",
"jsdoc": "^3.4.3",

@@ -61,4 +66,5 @@ "jsdoc-to-markdown": "^1.3.7",

"nock": "^9.0.6",
"webpack": "^1.14.0"
"webpack": "^4.6.0",
"webpack-cli": "^2.0.15"
}
}
# uport-js
## Integrate uport in your javascript application
## Integrate uPort in your javascript application
Uport provides a simple way for your users to login to your website and provide private credentials such as identity information and contact details to you.
uPort provides a simple way for your users to login to your website and provide private credentials such as identity information and contact details to you.
You can also “attest” credentials they provide to you or that you yourself have about them. This can be shared back to your customers so you can help them build their digitial identity.
You can also “attest” credentials they provide to you or that you yourself have about them. This can be shared back to your customers so you can help them build their digital identity.
Uport.js provides a simple way for you to integrate uport.js into your javscript application. You can also interact with your uport users directly in the browser.
Uport.js provides a simple way for you to integrate uport.js into your javascript application. You can also interact with your uPort users directly in the browser.
We have an easy to use browser library [uport-connect](https://github.com/uport-project/uport-connect) which can help you do so.
## Setup your uport application identity
## Setup your uPort application identity
First make sure you have your uport app installed and you've setup your own uport identity.
First make sure you have your uPort app installed and you've setup your own uPort identity.
### What is a uport identity?
### What is a uPort identity?
A uport identity is a special kind of ethereum Smart Contract known as a proxy contract. It has an ethereum address, can hold value and can interact with any other Ethereum smart contracts.
An identity in uPort is really just someone or something that can sign data or transactions and also receive signed data about itself.
The identity is controlled by a Controller Contract, which is basically an access control layer. You can develop your own custom access control layers and replace them, while keeping the primary identity intact (or permanent as we like to call it).
An identity has an identifier in the form of an [MNID](https://github.com/uport-project/mnid), a signing key, and a public key stored on the [uPort Registry](https://github.com/uport-project/uport-registry).
Our default uport controller contract is controlled by a single device, but you can add multiple recovery contacts to help retain control if you lose that device. Feel free to replace the controller contract with your own contract.
An identity can:
### The uport registry
- Sign JWTs (JSON Web Tokens)
- [Authenticate themselves to a third party](messages/shareresp.md)
- [Disclose private information about themselves](messages/shareresp.md)
- [Receive requests for disclosure about themselves](messages/sharereq.md)
- [Receive and store signed third party verifications about themselves](flows/verification.md)
- [Sign Ethereum transactions](flows/tx.md)
A uport identity also optionally has a public profile stored on ipfs and linked to your identity through the uport registry. This profile consists of JSON using the [Schema.org](http://schema.org/) conventions.
When interacting privately with a user you will be interchanging signed JWT([JSON Web Token](https://jwt.io/)). To verify the signature of the JWT you and your users will be fetching your public key from the public profile.
For details on uPort's underlying architecture, read our [spec repo](https://github.com/uport-project/specs) or check out the [uPort identity contracts] (https://github.com/uport-project/uport-identity).
## Configure your application
In your application you must first configure your Uport object.
In your application you must first configure your uPort object.
```javascript
import { Credentials, SimpleSigner } from 'uport'
import { Credentials } from 'uport'
const signer = SimpleSigner(process.env.PRIVATE_KEY)
// For new ethereum based addresses
const credentials = new Credentials({
appName: 'App Name',
did: 'did:ethr:0x....',
privateKey: process.env.PRIVATE_KEY
})
// You can create a new identity
console.log(Credentials.createIdentity())
// For legacy application identity created on App Manager
const credentials = new Credentials({
appName: 'App Name',
address: 'MNID Encoded uPort Address For Your App',
signer: signer,
networks: networks
privateKey: process.env.PRIVATE_KEY
})
```
Going forward all uPort application ID addresses must be [MNID encoded](https://github.com/uport-project/mnid). MNID will encode the network with the address. Use of hex encoded addresses is deprecated. Using a hex encoded address will indicated you are on ropsten using our deprecated registry, if you require this use case then continue to pass a hex encoded address. If you are on ropsten but using our latest registry, pass a MNID encoded address with ropsten.
The networks object includes a set of networks for which JWTs will be verified over. JWT verification includes an on-chain lookup for the public key mapped to the issuers identity, the MIND encoding of the issuer's address defines the network and registry to use for lookup. If you are interested in verifying JWTs over additional networks, pass in a network configs object, defined as follows:
```javascript
const networks = { id: '0x2a' :
{ registry: '0x5f8e9351dc2d238fb878b6ae43aa740d62fc9758',
rpcUrl: 'https://kovan.infura.io' },
id: .... : { ... }
}
```
Look in [uport-lite](https://github.com/uport-project/uport-lite) for the default networks and registries which will be queried for JWT verification.
## Requesting information from your users

@@ -68,3 +71,3 @@

```javascript
credentials.createRequest().then(requestToken => {
credentials.requestDisclosure().then(requestToken => {
// send requestToken to browser

@@ -77,3 +80,3 @@ })

```javascript
credentials.createRequest({
credentials.requestDisclosure({
requested: ['name','phone','identity_no'],

@@ -89,3 +92,3 @@ callbackUrl: 'https://....' // URL to send the response of the request to

```javascript
credentials.createRequest({network_id: '0x4'}).then(requestToken => {
credentials.requestDisclosure({network_id: '0x4'}).then(requestToken => {
// send requestToken to browser

@@ -95,19 +98,9 @@ })

In your front end use [uport-connect](https://github.com/uport-project/uport-connect) to present it to your user either as a QR code or as a uport-button depending on whether they are on a desktop or mobile browser.
```javascript
const connect = new uportconnect.Connect('app name')
connect.showRequest(requestToken).then(response => {
// send response back to server
})
```
Back in your server code you receive the token:
```javascript
credentials.receive(responseToken).then(profile => {
credentials.authenticate(responseToken).then(profile => {
// Store user profile
})
```
For more information about the contents of the profile object see the uport-persona documentation.

@@ -177,3 +170,2 @@ ### Stateless Challenge/Response

```javascript
// Coming soon, not yet implemented
credentials.push(pushToken, `me.uport:add?attestation=${attestationjwt}`, message).then(response => {

@@ -209,11 +201,1 @@

## Creating Custom Signers for integrating with HSM
You can easily create custom signers that integrates into your existing signing infrastructure.
```javascript
function sign(data, callback) {
const signature = '' // send your data to your back end signer and return DER signed data
callback(null, signature)
}
```

@@ -1,3 +0,2 @@

import { createJWT, verifyJWT } from './JWT'
import { decodeToken } from 'jsontokens'
import { createJWT, verifyJWT, SimpleSigner } from 'did-jwt'
import UportLite from 'uport-lite'

@@ -7,3 +6,8 @@ import nets from 'nets'

import naclutil from 'tweetnacl-util'
const MNID = require('mnid')
import UportDIDResolver from 'uport-did-resolver'
import EthrDIDResolver from 'ethr-did-resolver'
import { toEthereumAddress } from 'did-jwt/lib/Digest'
import { ec as EC } from 'elliptic'
const secp256k1 = new EC('secp256k1')
/**

@@ -20,35 +24,99 @@ * The Credentials class allows you to easily create the signed payloads used in uPort inlcuding

*
* The following example is just for testing purposes. You should never store a private key in source code.
*
* @example
* import { Credentials, SimpleSigner } from 'uport'
* const networks = { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', registry: '0x0101.... }}
* const setttings = { networks, address: '5A8bRWU3F7j3REx3vkJ...', signer: new SimpleSigner(process.env.PRIVATE_KEY)}
* const credentials = new Credentials(settings)
* import { Credentials } from 'uport'
* const credentials = new Credentials({
* privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
* })
*
* The above example derives the public key used to generate the did, so only a private key is needed.
* Generating a public key from a private key is slow. It is recommended to configure the `did` option as well.
*
* @example
* import { Credentials } from 'uport'
* const credentials = new Credentials()
* const credentials = new Credentials({
* did: 'did:ethr:0xbc3ae59bc76f894822622cdef7a2018dbe353840',
* privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
* })
*
* It is recommended to store the address and private key in environment variables for your server application
*
* @example
* import { Credentials, SimpleSigner } from 'uport'
* const credentials = new Credentials({
* did: process.env.APPLICATION_DID,
* signer: SimpleSigner(process.env.PRIVATE_KEY)
* })
*
* Instead of a private key you can pass in a [Signer Functions](https://github.com/uport-project/did-jwt#signer-functions) to
* present UX or call a HSM.
* @example
* import { Credentials } from 'uport'
*
* function mySigner (data) {
* return new Promise((resolve, reject) => {
* const signature = /// sign it
* resolve(signature)
* })
* }
*
* const credentials = new Credentials({
* did: process.env.APPLICATION_DID,
* signer: mySigner
* })
*
* @param {Object} [settings] setttings
* @param {Object} settings.networks networks config object, ie. { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', address: '0x0101.... }}
* @param {UportLite} settings.registry a registry object from UportLite
* @param {SimpleSigner} settings.signer a signer object, see SimpleSigner.js
* @param {Address} settings.address your uPort address (may be the address of your application's uPort identity)
* @param {DID} settings.did Application [DID](https://w3c-ccg.github.io/did-spec/#decentralized-identifiers-dids) (unique identifier) for your application
* @param {String} settings.privateKey A hex encoded 32 byte private key
* @param {SimpleSigner} settings.signer a signer object, see [Signer Functions](https://github.com/uport-project/did-jwt#signer-functions)
* @param {Object} settings.ethrConfig Configuration object for ethr did resolver. See [ethr-did-resolver](https://github.com/uport-project/ethr-did-resolver)
* @param {Address} settings.address DEPRECATED your uPort address (may be the address of your application's uPort identity)
* @param {Object} settings.networks DEPRECATED networks config object, ie. { '0x94365e3b': { rpcUrl: 'https://private.chain/rpc', address: '0x0101.... }}
* @param {UportLite} settings.registry DEPRECATED a registry object from UportLite
* @return {Credentials} self
*/
constructor (settings = {}) {
this.settings = settings
this.settings.networks = settings.networks ? configNetworks(settings.networks) : {}
if (!this.settings.registry) {
const registry = UportLite({networks: this.settings.networks})
this.settings.registry = (address) => new Promise((resolve, reject) => {
registry(address, (error, profile) => {
if (error) return reject(error)
resolve(profile)
})
})
constructor ({did, address, privateKey, signer, networks, registry, ethrConfig} = {}) {
if (signer) {
this.signer = signer
} else if (privateKey) {
this.signer = SimpleSigner(privateKey)
}
if (did) {
this.did = did
} else if (address) {
if (MNID.isMNID(address)) {
this.did = `did:uport:${address}`
}
if (address.match('^0x[0-9a-fA-F]{40}$')) {
this.did = `did:ethr:${address}`
}
} else if (privateKey) {
const kp = secp256k1.keyFromPrivate(privateKey)
const address = toEthereumAddress(kp.getPublic('hex'))
this.did = `did:ethr:${address}`
}
this.signJWT = (payload, expiresIn) => createJWT(payload, {issuer: this.did, signer: this.signer, alg: this.did.match('^did:uport:') ? 'ES256K' : 'ES256K-R', expiresIn })
UportDIDResolver(registry || UportLite({networks: networks ? configNetworks(networks) : {}}))
EthrDIDResolver(ethrConfig || {})
}
/**
* generate a DID and private key
*/
static createIdentity () {
const kp = secp256k1.genKeyPair()
const publicKey = kp.getPublic('hex')
const privateKey = kp.getPrivate('hex')
const address = toEthereumAddress(publicKey)
const did = `did:ethr:${address}`
return {did, privateKey}
}
/**
* Creates a signed request token (JWT) given a request params object.
* Creates a [Selective Disclosure Request JWT](https://github.com/uport-project/specs/blob/develop/messages/sharereq.md)
*

@@ -59,11 +127,5 @@ * @example

* notifications: true }
* credentials.createRequest(req).then(jwt => {
* credentials.requestDisclosure(req).then(jwt => {
* ...
* })
requested: ['name','phone','identity_no'],
callbackUrl: 'https://....' // URL to send the response of the request to
notifications: true
*

@@ -77,5 +139,6 @@ * @param {Object} [params={}] request params object

* @param {String} params.accountType Ethereum account type: "general", "segregated", "keypair", "devicekey" or "none"
* @param {Number} expiresIn Seconds until expiry
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
*/
createRequest (params = {}) {
requestDisclosure (params = {}, expiresIn = 600) {
const payload = {}

@@ -97,15 +160,117 @@ if (params.requested) {

}
if (params.accountType
&& ['general', 'segregated', 'keypair', 'devicekey', 'none'].indexOf(params.accountType) >= 0) {
payload.act = params.accountType
if (params.accountType) {
if (['general', 'segregated', 'keypair', 'devicekey', 'none'].indexOf(params.accountType) >= 0) {
payload.act = params.accountType
} else {
return Promise.reject(new Error(`Unsupported accountType ${params.accountType}`))
}
}
if (params.exp) { //checks for expiration on requests, if none is provided the default is 10 min
if (params.exp) {
payload.exp = params.exp
}
return this.signJWT({...payload, type: 'shareReq'}, params.exp ? undefined : expiresIn)
}
/**
* Creates a [Selective Disclosure Request JWT](https://github.com/uport-project/specs/blob/develop/messages/sharereq.md)
*
* @example
* const req = { requested: ['name', 'country'],
* callbackUrl: 'https://myserver.com',
* notifications: true }
* credentials.createRequest(req).then(jwt => {
* ...
* })
*
* @param {Object} [params={}] request params object
* @param {Array} params.requested an array of attributes for which you are requesting credentials to be shared for
* @param {Array} params.verified an array of attributes for which you are requesting verified credentials to be shared for
* @param {Boolean} params.notifications boolean if you want to request the ability to send push notifications
* @param {String} params.callbackUrl the url which you want to receive the response of this request
* @param {String} params.network_id network id of Ethereum chain of identity eg. 0x4 for rinkeby
* @param {String} params.accountType Ethereum account type: "general", "segregated", "keypair", "devicekey" or "none"
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
* @deprecated
*/
createRequest (params = {}) {
return this.requestDisclosure(params)
}
/**
* Creates a [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md).
*
* This can either be used to share information about the signing identity or as the response to a
* [Selective Disclosure Flow](https://github.com/uport-project/specs/blob/develop/flows/selectivedisclosure.md), where it can be used to authenticate the identity.
*
* @example
* credentials.disclose({own: {name: 'Lourdes Valentina Gomez'}}).then(jwt => {
* ...
* })
*
* @param {Object} [params={}] request params object
* @param {JWT} params.req A selective disclosure Request JWT if this is returned as part of an authentication flow
* @param {Object} params.own An object of self attested claims about the signer (eg. name etc)
* @param {Array} params.verified An array of attestation JWT's to include
* @param {MNID} params.nad An ethereum address encoded as an [MNID](https://github.com/uport-project/mnid)
* @param {Array} params.capabilities An array of capability JWT's to include
* @return {Promise<Object, Error>} a promise which resolves with a signed JSON Web Token or rejects with an error
*/
async disclose (payload = {}, expiresIn = 600 ) {
if (payload.req) {
const verified = await verifyJWT(payload.req)
if (verified.issuer) {
payload.aud = verified.issuer
}
}
return this.signJWT({...payload, type: 'shareResp'}, expiresIn)
}
async processDisclosurePayload ({doc, payload}) {
const credentials = {...doc.uportProfile || {}, ...(payload.own || {}), ...(payload.capabilities && payload.capabilities.length === 1 ? {pushToken: payload.capabilities[0]} : {}), address: payload.iss}
if (payload.nad) {
credentials.networkAddress = payload.nad
}
if (payload.dad) {
credentials.deviceKey = payload.dad
}
if (payload.verified) {
const verified = await Promise.all(payload.verified.map(token => verifyJWT(token, {audience: this.did})))
return {...credentials, verified: verified.map(v => ({...v.payload, jwt: v.jwt}))}
} else {
return credentials
}
}
/**
* Authenticates [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md) from mobile
* app as part of the [Selective Disclosure Flow](https://github.com/uport-project/specs/blob/develop/flows/selectivedisclosure.md).
*
* It Verifies and parses the given response token and verifies the challenge response flow.
*
* @example
* const resToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJyZXF1Z....'
* credentials.authenticate(resToken).then(res => {
* const credentials = res.verified
* const name = res.name
* ...
* })
*
* @param {String} token a response token
* @param {String} [callbackUrl=null] callbackUrl
* @return {Promise<Object, Error>} a promise which resolves with a parsed response or rejects with an error.
*/
async authenticate (token, callbackUrl = null) {
const { payload, doc } = await verifyJWT(token, {audience: this.did, callbackUrl, auth: true})
if(payload.req) {
const challenge = await verifyJWT(payload.req)
if(challenge.payload.iss === this.did && challenge.payload.type === 'shareReq') {
return this.processDisclosurePayload({payload, doc})
}
} else {
payload.exp = Math.floor(Date.now() / 1000) + 600
throw new Error('Challenge was not included in response')
}
return createJWT(this.settings, {...payload, type: 'shareReq'})
}
/**
/**
* Receive signed response token from mobile app. Verifies and parses the given response token.

@@ -124,39 +289,30 @@ *

* @return {Promise<Object, Error>} a promise which resolves with a parsed response or rejects with an error.
* @deprecated
*/
receive (token, callbackUrl = null) {
return verifyJWT(this.settings, token, callbackUrl).then(({payload, profile}) => {
return this.authenticate(token, callbackUrl)
}
function processPayload(settings) {
const credentials = {...profile, ...(payload.own || {}), ...(payload.capabilities && payload.capabilities.length === 1 ? {pushToken: payload.capabilities[0]} : {}), address: payload.iss}
if (payload.nad) {
credentials.networkAddress = payload.nad
}
if (payload.dad) {
credentials.deviceKey = payload.dad
}
if (payload.verified) {
return Promise.all(payload.verified.map(token => verifyJWT(settings, token))).then(verified => {
return {...credentials, verified: verified.map(v => ({...v.payload, jwt: v.jwt}))}
})
} else {
return credentials
}
}
/**
* Verify and return profile from a [Selective Disclosure Response JWT](https://github.com/uport-project/specs/blob/develop/messages/shareresp.md).
*
* The main difference between this and `authenticate()` is that it does not verify the challenge. This can be used to verify user profiles that have been shared
* through other methods such as QR codes and messages.
*
* @example
* const resToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJyZXF1Z....'
* credentials.verifyProfile(resToken).then(profile => {
* const credentials = profile.verified
const name = profile.name
* ...
* })
*
* @param {String} token a response token
* @return {Promise<Object, Error>} a promise which resolves with a parsed response or rejects with an error.
*/
async verifyProfile (token) {
const { payload, doc } = await verifyJWT(token, {audience: this.did})
return this.processDisclosurePayload({ payload, doc })
}
if(this.settings.signer) {
if(payload.req) {
return verifyJWT(this.settings, payload.req).then((challenge) => {
if(challenge.payload.iss === this.settings.address && challenge.payload.type === 'shareReq') {
return processPayload(this.settings)
}
})
} else {
throw new Error('Challenge was not included in response')
}
} else {
return processPayload(this.settings)
}
})
}
/**

@@ -237,21 +393,21 @@ * Send a push notification to a user, consumes a token which allows you to send push notifications

attest ({sub, claim, exp}) {
return createJWT(this.settings, {sub: sub, claim, exp})
return this.signJWT({sub: sub, claim, exp})
}
/**
* Look up a profile in the registry for a given uPort address. Address must be MNID encoded.
*
* @example
* credentials.lookup('5A8bRWU3F7j3REx3vkJ...').then(profile => {
* const name = profile.name
* const pubkey = profile.pubkey
* ...
* })
*
* @param {String} address a MNID encoded address
* @return {Promise<Object, Error>} a promise which resolves with parsed profile or rejects with an error
*/
lookup (address) {
return this.settings.registry(address)
}
// /**
// * Look up a profile in the registry for a given uPort address. Address must be MNID encoded.
// *
// * @example
// * credentials.lookup('5A8bRWU3F7j3REx3vkJ...').then(profile => {
// * const name = profile.name
// * const pubkey = profile.pubkey
// * ...
// * })
// *
// * @param {String} address a MNID encoded address
// * @return {Promise<Object, Error>} a promise which resolves with parsed profile or rejects with an error
// */
// lookup (address) {
// return this.settings.registry(address)
// }
}

@@ -258,0 +414,0 @@

import Credentials from './Credentials'
import SimpleSigner from './SimpleSigner'
import { SimpleSigner } from 'did-jwt'
import { Contract, ContractFactory } from './Contract'
import JWT from './JWT'
module.exports = { Credentials, SimpleSigner, Contract, ContractFactory, JWT }
module.exports = { Credentials, SimpleSigner, Contract, ContractFactory }
var express = require('express');
var uport = require('../lib/index.js');
var jsontokens = require('jsontokens')
var decodeJWT = require('did-jwt').decodeJWT
var app = express();
var signer = uport.SimpleSigner('28cefd149967e661b38495d2b5ab3964ffa0055912512d7125896646102c025b')
var credentials = new uport.Credentials({
appName: 'Credential Tutorial',
address: '2od4Re9CL92phRUoAhv1LFcFkx2B9UAin92',
signer: signer
//networks: {'0x4': {'registry' : '0x2cc31912b2b0f3075a87b3640923d45a26cef3ee', 'rpcUrl' : 'https://rinkeby.infura.io'}}
// Note: we use Rinkeby by default, the above is the explicit format for selecting a network
did: 'did:ethr:0xbc3ae59bc76f894822622cdef7a2018dbe353840',
privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
})

@@ -20,3 +15,3 @@

credentials.attest({
sub: '2p13BzDJcWpUhSaHVhfaJ1UaWB7P6WnfSXK',
sub: 'did:uport:2omWsSGspY7zhxaG6uHyoGtcYxoGeeohQXz',
exp: 1552046024,

@@ -28,6 +23,6 @@ claim: {'My Title' : {'KeyOne' : 'ValueOne', 'KeyTwo' : 'Value2', 'Last Key' : 'Last Value'} }

console.log(att)
console.log(jsontokens.decodeToken(att))
var uri = 'me.uport:add?attestations=' + att
console.log(decodeJWT(att))
var uri = 'me.uport:add?attestations=' + att + '%26callback_type=post'
var qrurl = 'http://chart.apis.google.com/chart?cht=qr&chs=400x400&chl=' + uri
var mobileUrl = 'https://id.uport.me/add?attestations=' + att
var mobileUrl = 'https://id.uport.me/add?attestations=' + att + '&callback_type=post'
console.log(uri)

@@ -38,4 +33,4 @@ res.send('<div><img src=' + qrurl + '></img></div><div><a href=' + mobileUrl + '>Click here if on mobile</a></div>')

var server = app.listen(8081, function () {
var server = app.listen(8088, function () {
console.log("Tutorial app running...")
})
var express = require('express');
var uport = require('../lib/index.js');
var jsontokens = require('jsontokens')
var bodyParser = require('body-parser')
var signer = uport.SimpleSigner('5acea265dcbf01355956b36f82793a13caf1be650bb74ca7a40da74b412d44b5')
var credentials = new uport.Credentials({
appName: 'Credential Tutorial',
address: '2opiNrGSxTW6sFo6ervHZnEeEXGNGAoupFN',
signer: signer
// networks: {'0x4': {'registry' : '0x2cc31912b2b0f3075a87b3640923d45a26cef3ee', 'rpcUrl' : 'https://rinkeby.infura.io'}}
// Note: we use Rinkeby by default, the above is the explicit format for selecting a network
did: 'did:ethr:0xbc3ae59bc76f894822622cdef7a2018dbe353840',
privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
})

@@ -24,12 +17,12 @@

credentials.createRequest({
credentials.requestDisclosure({
verified: ['My Title'],
callbackUrl: 'http://192.168.1.14:8081/callback',
callbackUrl: 'http://192.168.44.162:8081/callback',
exp: Math.floor(new Date().getTime()/1000) + 300
}).then( function(requestToken) {
var uri = 'me.uport:me?requestToken=' + requestToken
var uri = 'me.uport:me?requestToken=' + requestToken + '%26callback_type=post'
var qrurl = 'http://chart.apis.google.com/chart?cht=qr&chs=400x400&chl=' + uri
var mobileUrl = 'https://id.uport.me/me?requestToken=' + requestToken
var mobileUrl = 'https://id.uport.me/me?requestToken=' + requestToken + '&callback_type=post'
console.log(uri)
res.send('<div><img src=' + qrurl + '></img></div><div><a href=' + mobileUrl + '>Click here if on mobile (Not implemented yet!)</a></div>');
res.send('<div><img src=' + qrurl + '></img></div><div><a href=' + mobileUrl + '>Click here if on mobile</a></div>');
})

@@ -44,3 +37,3 @@

credentials.receive(jwt).then( function(creds) {
credentials.authenticate(jwt).then( function(creds) {
console.log(creds)

@@ -61,5 +54,5 @@ if (creds.address == creds.verified[0].sub &&

var server = app.listen(8081, function () {
var server = app.listen(8088, function () {
console.log("Tutorial app running...")
})

@@ -13,15 +13,10 @@ # Server-side Credentials

In the file `createcredential.js` we have a simple node `express` server. In the setup phase we use the private key we got from the App Manager to create a `SimpleSigner` object. This object is what will be signing the credential.
In the file `createcredential.js` we have a simple node `express` server. In the setup phase we use the private key we got from the App Manager to create a `SimpleSigner` object.
```js
var signer = uport.SimpleSigner(<your key here>)
```
We then create a `Credentials` object using the privatreKey and the uPort identifier of our app that we got from the App Manager (or the default identity):
We then create a `Credentials` object using the signer and the uPort identifier of our app that we got from the App Manager (or the default identity):
```js
var credentials = new uport.Credentials({
appName: 'Credential Tutorial',
address: '2od4Re9CL92phRUoAhv1LFcFkx2B9UAin92',
signer: signer
did: 'did:ethr:0xbc3ae59bc76f894822622cdef7a2018dbe353840',
privateKey: '74894f8853f90e6e3d6dfdd343eb0eb70cca06e552ed8af80adadcc573b35da3'
})

@@ -34,3 +29,3 @@ ```

credentials.attest({
sub: '<uport Id of mobile app>',
sub: '<uport Id of identity in mobile app>',
exp: 1552046024,

@@ -44,3 +39,3 @@ claim: {'My Title' : {'KeyOne' : 'ValueOne', 'KeyTwo' : 'Value2', 'Last Key' : 'Last Value'}}

```js
me.uport:add?attestations=<JSON Web Token>
me.uport:add?attestations=<JSON Web Token>&callback_type=post
```

@@ -59,3 +54,3 @@

If you open your browser to `http://localhost:8081/` you should see the QR code with the credential, which you may scan with the uPort app.
If you open your browser to `http://localhost:8088/` you should see the QR code with the credential, which you may scan with the uPort app.

@@ -90,3 +85,3 @@ ## Requestor service

and go to `http://localhost:8081` in your browser.
and go to `http://localhost:8088` in your browser.

@@ -93,0 +88,0 @@ When the mobile app user approves the request to share her credential after scanning the code, the `/callback` route is called using `app.post('/callback')`. Here we fetch the response JWT using `req.body.access_token`.

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc