Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

did-jwt

Package Overview
Dependencies
Maintainers
6
Versions
142
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

did-jwt - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

2

lib/index.js

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

function r(r){return r&&"object"==typeof r&&"default"in r?r.default:r}var e=require("js-sha256"),t=require("js-sha3"),n=require("elliptic"),o=r(require("tweetnacl")),i=require("@stablelib/utf8"),a=require("buffer"),u=r(require("uport-base64url")),c=r(require("did-resolver"));function f(r){return a.Buffer.from(e.sha256.arrayBuffer(r))}function s(r){return"0x"+(e=a.Buffer.from(r.slice(2),"hex"),a.Buffer.from(t.keccak_256.arrayBuffer(e))).slice(-20).toString("hex");var e}var d=new n.ec("secp256k1");function l(r,e){return void 0===e&&(e=64),r.length===e?r:"0".repeat(e-r.length)+r}function h(r){return new Uint8Array(Array.prototype.slice.call(Buffer.from(r,"base64"),0))}var v=new n.ec("secp256k1");function p(r,e){void 0===e&&(e=!1);var t=u.toBuffer(r);if(t.length!==(e?65:64))throw new Error("wrong signature length");var n={r:t.slice(0,32).toString("hex"),s:t.slice(32,64).toString("hex")};return e&&(n.recoveryParam=t[64]),n}var w={ES256K:function(r,e,t){var n=f(r),o=p(e),i=t.find(function(r){return v.keyFromPublic(r.publicKeyHex,"hex").verify(n,o)});if(!i)throw new Error("Signature invalid for JWT");return i},"ES256K-R":function(r,e,t){var n=p(e,!0),o=f(r),i=v.recoverPubKey(o,n,n.recoveryParam),a=i.encode("hex"),u=i.encode("hex",!0),c=s(a),d=t.find(function(r){var e=r.publicKeyHex;return e===a||e===u||r.ethereumAddress===c});if(!d)throw new Error("Signature invalid for JWT");return d},Ed25519:function(r,e,t){var n=i.encode(r),a=h(u.toBase64(e)),c=t.find(function(r){return o.sign.detached.verify(n,a,h(r.publicKeyBase64))});if(!c)throw new Error("Signature invalid for JWT");return c}};function y(r){var e=w[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}function g(r){return"object"==typeof r&&"r"in r&&"s"in r}function m(r){return function(e,t){try{return Promise.resolve(t(e)).then(function(e){if(g(e))return function(t){var n=e.r,o=e.s,i=e.recoveryParam,c=a.Buffer.alloc(r?65:64);if(a.Buffer.from(n,"hex").copy(c,0),a.Buffer.from(o,"hex").copy(c,32),r){if(void 0===i)throw new Error("Signer did not return a recoveryParam");c[64]=i}return u.encode(c)}();throw new Error("expected a signer function that returns a signature object instead of string")})}catch(r){return Promise.reject(r)}}}y.toSignatureObject=p;var b={ES256K:m(),"ES256K-R":m(!0),Ed25519:function(r,e){try{return Promise.resolve(e(r)).then(function(r){if(g(r))throw new Error("expected a signer function that returns a string instead of signature object");return r})}catch(r){return Promise.reject(r)}}},E={ES256K:["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],"ES256K-R":["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],Ed25519:["ED25519SignatureVerification"]};function S(r){return u.encode(JSON.stringify(r))}function x(r){return r.match(/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/)}function P(r){if(r.match(/^did:/))return r;if(x(r))return"did:uport:"+r;throw new Error("Not a valid DID '"+r+"'")}function J(r){if(!r)throw new Error("no JWT passed into decodeJWT");var e=r.match(/^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/);if(e)return{header:JSON.parse(u.decode(e[1])),payload:JSON.parse(u.decode(e[2])),signature:e[3],data:e[1]+"."+e[2]};throw new Error("Incorrect format JWT")}exports.SimpleSigner=function(r){var e=d.keyFromPrivate(r);return function(r){try{var t=e.sign(f(r)),n=t.s,o=t.recoveryParam;return Promise.resolve({r:l(t.r.toString("hex")),s:l(n.toString("hex")),recoveryParam:o})}catch(r){return Promise.reject(r)}}},exports.NaclSigner=function(r){var e=h(r);return function(r){try{var t=i.encode(r),n=o.sign.detached(t,e),c=u.encode(a.Buffer.from(n));return Promise.resolve(c)}catch(r){return Promise.reject(r)}}},exports.verifyJWT=function(r,e){void 0===e&&(e={auth:null,audience:null,callbackUrl:null});try{var t=e.audience?P(e.audience):void 0,n=J(r),o=n.payload,i=n.header,a=n.signature,u=n.data;return Promise.resolve(function(r,e,t){try{var n=E[r];if(!n||0===n.length)throw new Error("No supported signature types for algorithm "+r);var o=P(e);return Promise.resolve(c(o)).then(function(e){if(!e)throw new Error("Unable to resolve DID document for "+o);var i=!t||(e.authentication||[]).map(function(r){return r.publicKey}),a=(e.publicKey||[]).filter(function(r){var e=r.type,o=r.id;return n.find(function(r){return r===e&&(!t||Array.isArray(i)&&i.indexOf(o)>=0)})});if(t&&(!a||0===a.length))throw new Error("DID document for "+o+" does not have public keys suitable for authenticationg user");if(!a||0===a.length)throw new Error("DID document for "+o+" does not have public keys for "+r);return{authenticators:a,issuer:o,doc:e}})}catch(r){return Promise.reject(r)}}(i.alg,o.iss,e.auth)).then(function(n){var c,f=n.doc,s=n.authenticators,d=n.issuer,l=y(i.alg)(u,a,s),h=Math.floor(Date.now()/1e3);if(l){var v=h+300;if(o.nbf){if(o.nbf>v)throw new Error("JWT not valid before nbf: "+o.nbf)}else if(o.iat&&o.iat>v)throw new Error("JWT not valid yet (issued in the future) iat: "+o.iat);if(o.exp&&o.exp<=h-300)throw new Error("JWT has expired: exp: "+o.exp+" < now: "+h);if(o.aud)if((c=o.aud)&&(c.match(/^did:/)||x(c))){if(!t)throw new Error("JWT audience is required but your app address has not been configured");if(t!==P(o.aud))throw new Error("JWT audience does not match your DID: aud: "+o.aud+" !== yours: "+t)}else{if(!e.callbackUrl)throw new Error("JWT audience matching your callback url is required but one wasn't passed in");if(o.aud!==e.callbackUrl)throw new Error("JWT audience does not match the callback url: aud: "+o.aud+" !== url: "+e.callbackUrl)}return{payload:o,doc:f,issuer:d,signer:l,jwt:r}}})}catch(r){return Promise.reject(r)}},exports.createJWT=function(r,e){var t=e.issuer,n=e.signer,o=e.alg,i=e.expiresIn;try{if(!n)throw new Error("No Signer functionality has been configured");if(!t)throw new Error("No issuing DID has been configured");var a={typ:"JWT",alg:o||"ES256K"},u={iat:Math.floor(Date.now()/1e3),exp:void 0};if(i&&r.nbf){if("number"!=typeof i)throw new Error("JWT expiresIn is not a number");u.exp=r.nbf+Math.floor(i)}var c=[S(a),S(Object.assign({},u,r,{iss:t}))].join("."),f=function(r){var e=b[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}(a.alg);return Promise.resolve(f(c,n)).then(function(r){return[c,r].join(".")})}catch(r){return Promise.reject(r)}},exports.decodeJWT=J,exports.toEthereumAddress=s;
function r(r){return r&&"object"==typeof r&&"default"in r?r.default:r}var e=require("js-sha256"),t=require("js-sha3"),n=require("elliptic"),o=r(require("tweetnacl")),i=require("@stablelib/utf8"),a=require("buffer"),u=r(require("uport-base64url")),c=require("did-resolver"),f=require("ethr-did-resolver"),s=r(require("https-did-resolver"));function d(r){return a.Buffer.from(e.sha256.arrayBuffer(r))}function l(r){return"0x"+(e=a.Buffer.from(r.slice(2),"hex"),a.Buffer.from(t.keccak_256.arrayBuffer(e))).slice(-20).toString("hex");var e}var h=new n.ec("secp256k1");function v(r,e){return void 0===e&&(e=64),r.length===e?r:"0".repeat(e-r.length)+r}function p(r){return new Uint8Array(Array.prototype.slice.call(Buffer.from(r,"base64"),0))}var w=new n.ec("secp256k1");function g(r,e){void 0===e&&(e=!1);var t=u.toBuffer(r);if(t.length!==(e?65:64))throw new Error("wrong signature length");var n={r:t.slice(0,32).toString("hex"),s:t.slice(32,64).toString("hex")};return e&&(n.recoveryParam=t[64]),n}var y={ES256K:function(r,e,t){var n=d(r),o=g(e),i=t.find(function(r){return w.keyFromPublic(r.publicKeyHex,"hex").verify(n,o)});if(!i)throw new Error("Signature invalid for JWT");return i},"ES256K-R":function(r,e,t){var n=g(e,!0),o=d(r),i=w.recoverPubKey(o,n,n.recoveryParam),a=i.encode("hex"),u=i.encode("hex",!0),c=l(a),f=t.find(function(r){var e=r.publicKeyHex;return e===a||e===u||r.ethereumAddress===c});if(!f)throw new Error("Signature invalid for JWT");return f},Ed25519:function(r,e,t){var n=i.encode(r),a=p(u.toBase64(e)),c=t.find(function(r){return o.sign.detached.verify(n,a,p(r.publicKeyBase64))});if(!c)throw new Error("Signature invalid for JWT");return c}};function m(r){var e=y[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}function b(r){return"object"==typeof r&&"r"in r&&"s"in r}function E(r){return function(e,t){try{return Promise.resolve(t(e)).then(function(e){if(b(e))return function(t){var n=e.r,o=e.s,i=e.recoveryParam,c=a.Buffer.alloc(r?65:64);if(a.Buffer.from(n,"hex").copy(c,0),a.Buffer.from(o,"hex").copy(c,32),r){if(void 0===i)throw new Error("Signer did not return a recoveryParam");c[64]=i}return u.encode(c)}();throw new Error("expected a signer function that returns a signature object instead of string")})}catch(r){return Promise.reject(r)}}}m.toSignatureObject=g;var S={ES256K:E(),"ES256K-R":E(!0),Ed25519:function(r,e){try{return Promise.resolve(e(r)).then(function(r){if(b(r))throw new Error("expected a signer function that returns a string instead of signature object");return r})}catch(r){return Promise.reject(r)}}},x={ES256K:["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],"ES256K-R":["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],Ed25519:["ED25519SignatureVerification"]},P=new c.Resolver(Object.assign({},f.getResolver(),s()));function J(r){return u.encode(JSON.stringify(r))}function k(r){return r.match(/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/)}function j(r){if(r.match(/^did:/))return r;if(k(r))return"did:uport:"+r;throw new Error("Not a valid DID '"+r+"'")}function K(r){if(!r)throw new Error("no JWT passed into decodeJWT");var e=r.match(/^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/);if(e)return{header:JSON.parse(u.decode(e[1])),payload:JSON.parse(u.decode(e[2])),signature:e[3],data:e[1]+"."+e[2]};throw new Error("Incorrect format JWT")}exports.SimpleSigner=function(r){var e=h.keyFromPrivate(r);return function(r){try{var t=e.sign(d(r)),n=t.s,o=t.recoveryParam;return Promise.resolve({r:v(t.r.toString("hex")),s:v(n.toString("hex")),recoveryParam:o})}catch(r){return Promise.reject(r)}}},exports.NaclSigner=function(r){var e=p(r);return function(r){try{var t=i.encode(r),n=o.sign.detached(t,e),c=u.encode(a.Buffer.from(n));return Promise.resolve(c)}catch(r){return Promise.reject(r)}}},exports.verifyJWT=function(r,e){void 0===e&&(e={auth:null,audience:null,callbackUrl:null});try{var t=e.audience?j(e.audience):void 0,n=K(r),o=n.payload,i=n.header,a=n.signature,u=n.data;return Promise.resolve(function(r,e,t){try{var n=x[r];if(!n||0===n.length)throw new Error("No supported signature types for algorithm "+r);var o=j(e);return Promise.resolve(P.resolve(o)).then(function(e){if(!e)throw new Error("Unable to resolve DID document for "+o);var i=!t||(e.authentication||[]).map(function(r){return r.publicKey}),a=(e.publicKey||[]).filter(function(r){var e=r.type,o=r.id;return n.find(function(r){return r===e&&(!t||Array.isArray(i)&&i.indexOf(o)>=0)})});if(t&&(!a||0===a.length))throw new Error("DID document for "+o+" does not have public keys suitable for authenticationg user");if(!a||0===a.length)throw new Error("DID document for "+o+" does not have public keys for "+r);return{authenticators:a,issuer:o,doc:e}})}catch(r){return Promise.reject(r)}}(i.alg,o.iss,e.auth)).then(function(n){var c,f=n.doc,s=n.authenticators,d=n.issuer,l=m(i.alg)(u,a,s),h=Math.floor(Date.now()/1e3);if(l){var v=h+300;if(o.nbf){if(o.nbf>v)throw new Error("JWT not valid before nbf: "+o.nbf)}else if(o.iat&&o.iat>v)throw new Error("JWT not valid yet (issued in the future) iat: "+o.iat);if(o.exp&&o.exp<=h-300)throw new Error("JWT has expired: exp: "+o.exp+" < now: "+h);if(o.aud)if((c=o.aud)&&(c.match(/^did:/)||k(c))){if(!t)throw new Error("JWT audience is required but your app address has not been configured");if(t!==j(o.aud))throw new Error("JWT audience does not match your DID: aud: "+o.aud+" !== yours: "+t)}else{if(!e.callbackUrl)throw new Error("JWT audience matching your callback url is required but one wasn't passed in");if(o.aud!==e.callbackUrl)throw new Error("JWT audience does not match the callback url: aud: "+o.aud+" !== url: "+e.callbackUrl)}return{payload:o,doc:f,issuer:d,signer:l,jwt:r}}})}catch(r){return Promise.reject(r)}},exports.createJWT=function(r,e){var t=e.issuer,n=e.signer,o=e.alg,i=e.expiresIn;try{if(!n)throw new Error("No Signer functionality has been configured");if(!t)throw new Error("No issuing DID has been configured");var a={typ:"JWT",alg:o||"ES256K"},u={iat:Math.floor(Date.now()/1e3),exp:void 0};if(i&&r.nbf){if("number"!=typeof i)throw new Error("JWT expiresIn is not a number");u.exp=r.nbf+Math.floor(i)}var c=[J(a),J(Object.assign({},u,r,{iss:t}))].join("."),f=function(r){var e=S[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}(a.alg);return Promise.resolve(f(c,n)).then(function(r){return[c,r].join(".")})}catch(r){return Promise.reject(r)}},exports.decodeJWT=K,exports.toEthereumAddress=l;
//# sourceMappingURL=index.js.map

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

!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("js-sha256"),require("js-sha3"),require("elliptic"),require("tweetnacl"),require("@stablelib/utf8"),require("buffer"),require("uport-base64url"),require("did-resolver")):"function"==typeof define&&define.amd?define(["exports","js-sha256","js-sha3","elliptic","tweetnacl","@stablelib/utf8","buffer","uport-base64url","did-resolver"],e):e(r.didJwt={},r.jsSha256,r.jsSha3,r.elliptic,r.tweetnacl,r.utf8,r.buffer,r.base64url,r.resolve)}(this,function(r,e,t,n,i,o,a,u,c){function f(r){return a.Buffer.from(e.sha256.arrayBuffer(r))}function s(r){return"0x"+(e=a.Buffer.from(r.slice(2),"hex"),a.Buffer.from(t.keccak_256.arrayBuffer(e))).slice(-20).toString("hex");var e}i=i&&i.hasOwnProperty("default")?i.default:i,u=u&&u.hasOwnProperty("default")?u.default:u,c=c&&c.hasOwnProperty("default")?c.default:c;var d=new n.ec("secp256k1");function l(r,e){return void 0===e&&(e=64),r.length===e?r:"0".repeat(e-r.length)+r}function h(r){return new Uint8Array(Array.prototype.slice.call(Buffer.from(r,"base64"),0))}var p=new n.ec("secp256k1");function w(r,e){void 0===e&&(e=!1);var t=u.toBuffer(r);if(t.length!==(e?65:64))throw new Error("wrong signature length");var n={r:t.slice(0,32).toString("hex"),s:t.slice(32,64).toString("hex")};return e&&(n.recoveryParam=t[64]),n}var v={ES256K:function(r,e,t){var n=f(r),i=w(e),o=t.find(function(r){return p.keyFromPublic(r.publicKeyHex,"hex").verify(n,i)});if(!o)throw new Error("Signature invalid for JWT");return o},"ES256K-R":function(r,e,t){var n=w(e,!0),i=f(r),o=p.recoverPubKey(i,n,n.recoveryParam),a=o.encode("hex"),u=o.encode("hex",!0),c=s(a),d=t.find(function(r){var e=r.publicKeyHex;return e===a||e===u||r.ethereumAddress===c});if(!d)throw new Error("Signature invalid for JWT");return d},Ed25519:function(r,e,t){var n=o.encode(r),a=h(u.toBase64(e)),c=t.find(function(r){return i.sign.detached.verify(n,a,h(r.publicKeyBase64))});if(!c)throw new Error("Signature invalid for JWT");return c}};function y(r){var e=v[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}function g(r){return"object"==typeof r&&"r"in r&&"s"in r}function m(r){return function(e,t){try{return Promise.resolve(t(e)).then(function(e){if(g(e))return function(t){var n=e.r,i=e.s,o=e.recoveryParam,c=a.Buffer.alloc(r?65:64);if(a.Buffer.from(n,"hex").copy(c,0),a.Buffer.from(i,"hex").copy(c,32),r){if(void 0===o)throw new Error("Signer did not return a recoveryParam");c[64]=o}return u.encode(c)}();throw new Error("expected a signer function that returns a signature object instead of string")})}catch(r){return Promise.reject(r)}}}y.toSignatureObject=w;var b={ES256K:m(),"ES256K-R":m(!0),Ed25519:function(r,e){try{return Promise.resolve(e(r)).then(function(r){if(g(r))throw new Error("expected a signer function that returns a string instead of signature object");return r})}catch(r){return Promise.reject(r)}}},E={ES256K:["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],"ES256K-R":["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],Ed25519:["ED25519SignatureVerification"]};function S(r){return u.encode(JSON.stringify(r))}function x(r){return r.match(/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/)}function P(r){if(r.match(/^did:/))return r;if(x(r))return"did:uport:"+r;throw new Error("Not a valid DID '"+r+"'")}function j(r){if(!r)throw new Error("no JWT passed into decodeJWT");var e=r.match(/^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/);if(e)return{header:JSON.parse(u.decode(e[1])),payload:JSON.parse(u.decode(e[2])),signature:e[3],data:e[1]+"."+e[2]};throw new Error("Incorrect format JWT")}r.SimpleSigner=function(r){var e=d.keyFromPrivate(r);return function(r){try{var t=e.sign(f(r)),n=t.s,i=t.recoveryParam;return Promise.resolve({r:l(t.r.toString("hex")),s:l(n.toString("hex")),recoveryParam:i})}catch(r){return Promise.reject(r)}}},r.NaclSigner=function(r){var e=h(r);return function(r){try{var t=o.encode(r),n=i.sign.detached(t,e),c=u.encode(a.Buffer.from(n));return Promise.resolve(c)}catch(r){return Promise.reject(r)}}},r.verifyJWT=function(r,e){void 0===e&&(e={auth:null,audience:null,callbackUrl:null});try{var t=e.audience?P(e.audience):void 0,n=j(r),i=n.payload,o=n.header,a=n.signature,u=n.data;return Promise.resolve(function(r,e,t){try{var n=E[r];if(!n||0===n.length)throw new Error("No supported signature types for algorithm "+r);var i=P(e);return Promise.resolve(c(i)).then(function(e){if(!e)throw new Error("Unable to resolve DID document for "+i);var o=!t||(e.authentication||[]).map(function(r){return r.publicKey}),a=(e.publicKey||[]).filter(function(r){var e=r.type,i=r.id;return n.find(function(r){return r===e&&(!t||Array.isArray(o)&&o.indexOf(i)>=0)})});if(t&&(!a||0===a.length))throw new Error("DID document for "+i+" does not have public keys suitable for authenticationg user");if(!a||0===a.length)throw new Error("DID document for "+i+" does not have public keys for "+r);return{authenticators:a,issuer:i,doc:e}})}catch(r){return Promise.reject(r)}}(o.alg,i.iss,e.auth)).then(function(n){var c,f=n.doc,s=n.authenticators,d=n.issuer,l=y(o.alg)(u,a,s),h=Math.floor(Date.now()/1e3);if(l){var p=h+300;if(i.nbf){if(i.nbf>p)throw new Error("JWT not valid before nbf: "+i.nbf)}else if(i.iat&&i.iat>p)throw new Error("JWT not valid yet (issued in the future) iat: "+i.iat);if(i.exp&&i.exp<=h-300)throw new Error("JWT has expired: exp: "+i.exp+" < now: "+h);if(i.aud)if((c=i.aud)&&(c.match(/^did:/)||x(c))){if(!t)throw new Error("JWT audience is required but your app address has not been configured");if(t!==P(i.aud))throw new Error("JWT audience does not match your DID: aud: "+i.aud+" !== yours: "+t)}else{if(!e.callbackUrl)throw new Error("JWT audience matching your callback url is required but one wasn't passed in");if(i.aud!==e.callbackUrl)throw new Error("JWT audience does not match the callback url: aud: "+i.aud+" !== url: "+e.callbackUrl)}return{payload:i,doc:f,issuer:d,signer:l,jwt:r}}})}catch(r){return Promise.reject(r)}},r.createJWT=function(r,e){var t=e.issuer,n=e.signer,i=e.alg,o=e.expiresIn;try{if(!n)throw new Error("No Signer functionality has been configured");if(!t)throw new Error("No issuing DID has been configured");var a={typ:"JWT",alg:i||"ES256K"},u={iat:Math.floor(Date.now()/1e3),exp:void 0};if(o&&r.nbf){if("number"!=typeof o)throw new Error("JWT expiresIn is not a number");u.exp=r.nbf+Math.floor(o)}var c=[S(a),S(Object.assign({},u,r,{iss:t}))].join("."),f=function(r){var e=b[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}(a.alg);return Promise.resolve(f(c,n)).then(function(r){return[c,r].join(".")})}catch(r){return Promise.reject(r)}},r.decodeJWT=j,r.toEthereumAddress=s});
!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("js-sha256"),require("js-sha3"),require("elliptic"),require("tweetnacl"),require("@stablelib/utf8"),require("buffer"),require("uport-base64url"),require("did-resolver"),require("ethr-did-resolver"),require("https-did-resolver")):"function"==typeof define&&define.amd?define(["exports","js-sha256","js-sha3","elliptic","tweetnacl","@stablelib/utf8","buffer","uport-base64url","did-resolver","ethr-did-resolver","https-did-resolver"],e):e(r.didJwt={},r.jsSha256,r.jsSha3,r.elliptic,r.tweetnacl,r.utf8,r.buffer,r.base64url,r.didResolver,r.ethrDidResolver,r.getHttpsDidResolver)}(this,function(r,e,t,n,i,o,a,u,c,f,s){function d(r){return a.Buffer.from(e.sha256.arrayBuffer(r))}function l(r){return"0x"+(e=a.Buffer.from(r.slice(2),"hex"),a.Buffer.from(t.keccak_256.arrayBuffer(e))).slice(-20).toString("hex");var e}i=i&&i.hasOwnProperty("default")?i.default:i,u=u&&u.hasOwnProperty("default")?u.default:u,s=s&&s.hasOwnProperty("default")?s.default:s;var h=new n.ec("secp256k1");function v(r,e){return void 0===e&&(e=64),r.length===e?r:"0".repeat(e-r.length)+r}function p(r){return new Uint8Array(Array.prototype.slice.call(Buffer.from(r,"base64"),0))}var w=new n.ec("secp256k1");function y(r,e){void 0===e&&(e=!1);var t=u.toBuffer(r);if(t.length!==(e?65:64))throw new Error("wrong signature length");var n={r:t.slice(0,32).toString("hex"),s:t.slice(32,64).toString("hex")};return e&&(n.recoveryParam=t[64]),n}var g={ES256K:function(r,e,t){var n=d(r),i=y(e),o=t.find(function(r){return w.keyFromPublic(r.publicKeyHex,"hex").verify(n,i)});if(!o)throw new Error("Signature invalid for JWT");return o},"ES256K-R":function(r,e,t){var n=y(e,!0),i=d(r),o=w.recoverPubKey(i,n,n.recoveryParam),a=o.encode("hex"),u=o.encode("hex",!0),c=l(a),f=t.find(function(r){var e=r.publicKeyHex;return e===a||e===u||r.ethereumAddress===c});if(!f)throw new Error("Signature invalid for JWT");return f},Ed25519:function(r,e,t){var n=o.encode(r),a=p(u.toBase64(e)),c=t.find(function(r){return i.sign.detached.verify(n,a,p(r.publicKeyBase64))});if(!c)throw new Error("Signature invalid for JWT");return c}};function b(r){var e=g[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}function m(r){return"object"==typeof r&&"r"in r&&"s"in r}function E(r){return function(e,t){try{return Promise.resolve(t(e)).then(function(e){if(m(e))return function(t){var n=e.r,i=e.s,o=e.recoveryParam,c=a.Buffer.alloc(r?65:64);if(a.Buffer.from(n,"hex").copy(c,0),a.Buffer.from(i,"hex").copy(c,32),r){if(void 0===o)throw new Error("Signer did not return a recoveryParam");c[64]=o}return u.encode(c)}();throw new Error("expected a signer function that returns a signature object instead of string")})}catch(r){return Promise.reject(r)}}}b.toSignatureObject=y;var S={ES256K:E(),"ES256K-R":E(!0),Ed25519:function(r,e){try{return Promise.resolve(e(r)).then(function(r){if(m(r))throw new Error("expected a signer function that returns a string instead of signature object");return r})}catch(r){return Promise.reject(r)}}},x={ES256K:["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],"ES256K-R":["Secp256k1VerificationKey2018","Secp256k1SignatureVerificationKey2018","EcdsaPublicKeySecp256k1"],Ed25519:["ED25519SignatureVerification"]},P=new c.Resolver(Object.assign({},f.getResolver(),s()));function j(r){return u.encode(JSON.stringify(r))}function J(r){return r.match(/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/)}function k(r){if(r.match(/^did:/))return r;if(J(r))return"did:uport:"+r;throw new Error("Not a valid DID '"+r+"'")}function K(r){if(!r)throw new Error("no JWT passed into decodeJWT");var e=r.match(/^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/);if(e)return{header:JSON.parse(u.decode(e[1])),payload:JSON.parse(u.decode(e[2])),signature:e[3],data:e[1]+"."+e[2]};throw new Error("Incorrect format JWT")}r.SimpleSigner=function(r){var e=h.keyFromPrivate(r);return function(r){try{var t=e.sign(d(r)),n=t.s,i=t.recoveryParam;return Promise.resolve({r:v(t.r.toString("hex")),s:v(n.toString("hex")),recoveryParam:i})}catch(r){return Promise.reject(r)}}},r.NaclSigner=function(r){var e=p(r);return function(r){try{var t=o.encode(r),n=i.sign.detached(t,e),c=u.encode(a.Buffer.from(n));return Promise.resolve(c)}catch(r){return Promise.reject(r)}}},r.verifyJWT=function(r,e){void 0===e&&(e={auth:null,audience:null,callbackUrl:null});try{var t=e.audience?k(e.audience):void 0,n=K(r),i=n.payload,o=n.header,a=n.signature,u=n.data;return Promise.resolve(function(r,e,t){try{var n=x[r];if(!n||0===n.length)throw new Error("No supported signature types for algorithm "+r);var i=k(e);return Promise.resolve(P.resolve(i)).then(function(e){if(!e)throw new Error("Unable to resolve DID document for "+i);var o=!t||(e.authentication||[]).map(function(r){return r.publicKey}),a=(e.publicKey||[]).filter(function(r){var e=r.type,i=r.id;return n.find(function(r){return r===e&&(!t||Array.isArray(o)&&o.indexOf(i)>=0)})});if(t&&(!a||0===a.length))throw new Error("DID document for "+i+" does not have public keys suitable for authenticationg user");if(!a||0===a.length)throw new Error("DID document for "+i+" does not have public keys for "+r);return{authenticators:a,issuer:i,doc:e}})}catch(r){return Promise.reject(r)}}(o.alg,i.iss,e.auth)).then(function(n){var c,f=n.doc,s=n.authenticators,d=n.issuer,l=b(o.alg)(u,a,s),h=Math.floor(Date.now()/1e3);if(l){var v=h+300;if(i.nbf){if(i.nbf>v)throw new Error("JWT not valid before nbf: "+i.nbf)}else if(i.iat&&i.iat>v)throw new Error("JWT not valid yet (issued in the future) iat: "+i.iat);if(i.exp&&i.exp<=h-300)throw new Error("JWT has expired: exp: "+i.exp+" < now: "+h);if(i.aud)if((c=i.aud)&&(c.match(/^did:/)||J(c))){if(!t)throw new Error("JWT audience is required but your app address has not been configured");if(t!==k(i.aud))throw new Error("JWT audience does not match your DID: aud: "+i.aud+" !== yours: "+t)}else{if(!e.callbackUrl)throw new Error("JWT audience matching your callback url is required but one wasn't passed in");if(i.aud!==e.callbackUrl)throw new Error("JWT audience does not match the callback url: aud: "+i.aud+" !== url: "+e.callbackUrl)}return{payload:i,doc:f,issuer:d,signer:l,jwt:r}}})}catch(r){return Promise.reject(r)}},r.createJWT=function(r,e){var t=e.issuer,n=e.signer,i=e.alg,o=e.expiresIn;try{if(!n)throw new Error("No Signer functionality has been configured");if(!t)throw new Error("No issuing DID has been configured");var a={typ:"JWT",alg:i||"ES256K"},u={iat:Math.floor(Date.now()/1e3),exp:void 0};if(o&&r.nbf){if("number"!=typeof o)throw new Error("JWT expiresIn is not a number");u.exp=r.nbf+Math.floor(o)}var c=[j(a),j(Object.assign({},u,r,{iss:t}))].join("."),f=function(r){var e=S[r];if(!e)throw new Error("Unsupported algorithm "+r);return e}(a.alg);return Promise.resolve(f(c,n)).then(function(r){return[c,r].join(".")})}catch(r){return Promise.reject(r)}},r.decodeJWT=K,r.toEthereumAddress=l});
//# sourceMappingURL=index.umd.js.map

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

import { DIDDocument, PublicKey } from 'did-resolver';
import { Resolver, DIDDocument, PublicKey } from 'did-resolver';
export interface EcdsaSignature {

@@ -52,2 +52,3 @@ r: string;

}
export declare const resolver: Resolver;
export declare const NBF_SKEW: number;

@@ -54,0 +55,0 @@ export declare function normalizeDID(mnidOrDid: string): string;

{
"name": "did-jwt",
"version": "1.0.0",
"version": "2.0.0",
"description": "Library for Signing and Verifying JWTs compatible uPort and DID standards",

@@ -78,3 +78,2 @@ "main": "lib/index.js",

"typescript": "^3.4.5",
"uport-did-resolver": "0.0.7",
"webpack": "^4.30.0",

@@ -87,4 +86,6 @@ "webpack-cli": "^3.3.1"

"buffer": "^5.2.1",
"did-resolver": "0.0.6",
"did-resolver": "^1.0.0",
"elliptic": "^6.4.0",
"ethr-did-resolver": "^1.0.1",
"https-did-resolver": "^1.0.0",
"js-sha256": "^0.9.0",

@@ -91,0 +92,0 @@ "js-sha3": "^0.8.0",

@@ -6,25 +6,20 @@ import {

resolveAuthenticator,
NBF_SKEW
NBF_SKEW,
resolver,
normalizeDID
} from '../JWT'
import { TokenVerifier } from 'jsontokens'
import registerResolver from 'uport-did-resolver'
import SimpleSigner from '../SimpleSigner'
import NaclSigner from '../NaclSigner'
import {
registerNaclDID,
loadIdentity,
verifyJWT as naclVerifyJWT
} from 'nacl-did'
import { verifyJWT as naclVerifyJWT } from 'nacl-did'
import MockDate from 'mockdate'
registerResolver()
registerNaclDID()
const originalResolve = resolver.resolve
const NOW = 1485321133
MockDate.set(NOW * 1000 + 123)
const audMnid = '2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqY'
const aud = `did:uport:${audMnid}`
const mnid = '2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX'
const did = `did:uport:${mnid}`
const audAddress = '0x20c769ec9c0996ba7737a4826c2aaff00b1b2040'
const aud = `did:ethr:${audAddress}`
const address = '0xf3beac30c498d9e26865f34fcaa57dbb935b0d74'
const did = `did:ethr:${address}`
const alg = 'ES256K'

@@ -58,68 +53,55 @@

const ethDidDoc = {
'@context': 'https://w3id.org/did/v1',
id: did,
publicKey: [
{
id: `${did}#keys-1`,
type: 'Secp256k1VerificationKey2018',
owner: did,
ethereumAddress: '0xf3beac30c498d9e26865f34fcaa57dbb935b0d74'
}
]
}
describe('createJWT()', () => {
describe('ES256K', () => {
it('creates a valid JWT', () => {
return createJWT(
it('creates a valid JWT', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer }
).then(jwt => {
return expect(verifier.verify(jwt)).toBeTruthy()
})
)
return expect(verifier.verify(jwt)).toBeTruthy()
})
it('creates a valid JWT using a MNID', () => {
return createJWT(
it('creates a valid JWT using a MNID', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: mnid, signer }
).then(jwt => {
return expect(verifier.verify(jwt)).toBeTruthy()
})
{ issuer: address, signer }
)
return expect(verifier.verify(jwt)).toBeTruthy()
})
it('creates a JWT with correct format', () => {
return createJWT(
it('creates a JWT with correct format', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer }
).then(jwt => {
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
)
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
it('creates a JWT with correct legacy format', () => {
return createJWT(
it('creates a JWT with correct legacy format', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: mnid, signer }
).then(jwt => {
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
{ issuer: address, signer }
)
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
it('creates a JWT with expiry in 10000 seconds', () => {
return createJWT(
{ requested: ['name', 'phone'], nbf: Math.floor(new Date().getTime() / 1000) },
it('creates a JWT with expiry in 10000 seconds', async () => {
const jwt = await createJWT(
{
requested: ['name', 'phone'],
nbf: Math.floor(new Date().getTime() / 1000)
},
{ issuer: did, signer, expiresIn: 10000 }
).then(jwt => {
const { payload } = decodeJWT(jwt)
return expect(payload.exp).toEqual(payload.nbf + 10000)
})
)
const { payload } = decodeJWT(jwt)
return expect(payload.exp).toEqual(payload.nbf + 10000)
})
it('ignores expiresIn if nbf is not set', async () => {
const { payload } = decodeJWT(await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer, expiresIn: 10000 }
))
const { payload } = decodeJWT(
await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer, expiresIn: 10000 }
)
)
return expect(payload.exp).toBeUndefined()

@@ -130,6 +112,8 @@ })

const timestamp = Math.floor(Date.now() / 1000)
const { payload } = decodeJWT(await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer }
))
const { payload } = decodeJWT(
await createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer }
)
)
return expect(payload.iat).toEqual(timestamp)

@@ -140,6 +124,8 @@ })

const timestamp = 2000000
const { payload } = decodeJWT(await createJWT(
{ requested: ['name', 'phone'], iat: timestamp },
{ issuer: did, signer }
))
const { payload } = decodeJWT(
await createJWT(
{ requested: ['name', 'phone'], iat: timestamp },
{ issuer: did, signer }
)
)
return expect(payload.iat).toEqual(timestamp)

@@ -149,16 +135,18 @@ })

it('does not set iat if value in payload is undefined', async () => {
const { payload } = decodeJWT(await createJWT(
{ requested: ['name', 'phone'], iat: undefined },
{ issuer: did, signer }
))
const { payload } = decodeJWT(
await createJWT(
{ requested: ['name', 'phone'], iat: undefined },
{ issuer: did, signer }
)
)
return expect(payload.iat).toBeUndefined()
})
it('throws an error if unsupported algorithm is passed in', () => {
return createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer, alg: 'BADALGO' }
).catch(error => {
return expect(error.message).toEqual('Unsupported algorithm BADALGO')
})
it('throws an error if unsupported algorithm is passed in', async () => {
expect(
createJWT(
{ requested: ['name', 'phone'] },
{ issuer: did, signer, alg: 'BADALGO' }
)
).rejects.toThrow('Unsupported algorithm BADALGO')
})

@@ -174,28 +162,28 @@ })

it('creates a valid JWT', () => {
return createJWT(
it('creates a valid JWT', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ alg, issuer: did, signer }
).then(jwt => {
return expect(naclVerifyJWT(jwt)).toBeTruthy()
})
)
return expect(naclVerifyJWT(jwt)).toBeTruthy()
})
it('creates a JWT with correct format', () => {
return createJWT(
it('creates a JWT with correct format', async () => {
const jwt = await createJWT(
{ requested: ['name', 'phone'] },
{ alg, issuer: did, signer }
).then(jwt => {
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
)
return expect(decodeJWT(jwt)).toMatchSnapshot()
})
it('creates a JWT with expiry in 10000 seconds', () => {
return createJWT(
{ requested: ['name', 'phone'], nbf: Math.floor(new Date().getTime() / 1000) },
it('creates a JWT with expiry in 10000 seconds', async () => {
const jwt = await createJWT(
{
requested: ['name', 'phone'],
nbf: Math.floor(new Date().getTime() / 1000)
},
{ alg, issuer: did, signer, expiresIn: 10000 }
).then(jwt => {
const { payload } = decodeJWT(jwt)
return expect(payload.exp).toEqual(payload.nbf + 10000)
})
)
const { payload } = decodeJWT(jwt)
return expect(payload.exp).toEqual(payload.nbf + 10000)
})

@@ -206,99 +194,42 @@ })

describe('verifyJWT()', () => {
registerResolver((id, cb) => {
if (mnid === id) cb(null, didDoc)
if (audMnid === id) cb(null, ethDidDoc)
beforeAll(() => {
resolver.resolve = jest.fn().mockReturnValue(didDoc)
})
afterAll(() => {
resolver.resolve = originalResolve
})
describe('pregenerated JWT', () => {
const incomingJwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6dXBvcnQ6Mm5RdGlRRzZDZ20xR1lUQmFhS0Fncjc2dVk3aVNleFVrcVg' +
'iLCJpYXQiOjE0ODUzMjExMzMsInJlcXVlc3RlZCI6WyJuYW1lIiwicGhvbmUiXX0.1hyeUGRBb-cgvjD5KKbpVJBF4TfDjYxrI8SWRJ-GyrJrN' +
'LAxt4MutKMFQyF1k_YkxbVozGJ_4XmgZqNaW4OvCw'
it('verifies the JWT and return correct payload', () => {
return verifyJWT(incomingJwt).then(({ payload }) => {
return expect(payload).toMatchSnapshot()
})
// tslint:disable-next-line: max-line-length
const incomingJwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzMjExMzMsImlzcyI6ImRpZDpldGhyOjB4OTBlNDVkNzViZDEyNDZlMDkyNDg3MjAxODY0N2RiYTk5NmE4ZTdiOSIsInJlcXVlc3RlZCI6WyJuYW1lIiwicGhvbmUiXX0.KIG2zUO8Quf3ucb9jIncZ1CmH0v-fAZlsKvesfsd9x4RzU0qrvinVd9d30DOeZOwdwEdXkET_wuPoOECwU0IKA'
it('verifies the JWT and return correct payload', async () => {
const { payload } = await verifyJWT(incomingJwt)
return expect(payload).toMatchSnapshot()
})
it('verifies the JWT and return correct profile', () => {
return verifyJWT(incomingJwt).then(({ doc }) => {
return expect(doc).toEqual(didDoc)
})
it('verifies the JWT and return correct profile', async () => {
const { doc } = await verifyJWT(incomingJwt)
return expect(doc).toEqual(didDoc)
})
it('verifies the JWT and return correct did for the iss', () => {
return verifyJWT(incomingJwt).then(({ issuer }) => {
return expect(issuer).toEqual(did)
})
})
it('verifies the JWT and return correct signer', () => {
return verifyJWT(incomingJwt).then(({ signer }) =>
expect(signer).toEqual(didDoc.publicKey[0])
it('verifies the JWT and return correct did for the iss', async () => {
const { issuer } = await verifyJWT(incomingJwt)
return expect(issuer).toEqual(
'did:ethr:0x90e45d75bd1246e0924872018647dba996a8e7b9'
)
})
it('verifies the JWT requiring authentication and return correct signer', () => {
return verifyJWT(incomingJwt, { auth: true }).then(({ signer }) =>
expect(signer).toEqual(didDoc.publicKey[0])
)
it('verifies the JWT and return correct signer', async () => {
const { signer } = await verifyJWT(incomingJwt)
return expect(signer).toEqual(didDoc.publicKey[0])
})
})
describe('nacl-did jwt', () => {
const privateKey =
'nlXR4aofRVuLqtn9+XVQNlX4s1nVQvp+TOhBBtYls1IG+sHyIkDP/WN+rWZHGIQp+v2pyct+rkM4asF/YRFQdQ=='
const did = 'did:nacl:BvrB8iJAz_1jfq1mRxiEKfr9qcnLfq5DOGrBf2ERUHU'
const naclId = loadIdentity({ privateKey, did })
const payload = { sub: aud, claim: { superChap: true } }
const incomingJwt = naclId.createJWT(payload)
const publicKey = {
id: `${did}#key1`,
type: 'ED25519SignatureVerification',
owner: did,
publicKeyBase64: 'BvrB8iJAz/1jfq1mRxiEKfr9qcnLfq5DOGrBf2ERUHU='
}
it('verifies the JWT and return correct payload', () => {
return verifyJWT(incomingJwt).then(({ payload }) => {
return expect(payload).toEqual(payload)
})
it('verifies the JWT requiring authentication and return correct signer', async () => {
const { signer } = await verifyJWT(incomingJwt, { auth: true })
return expect(signer).toEqual(didDoc.publicKey[0])
})
it('verifies the JWT and return correct profile', () => {
return verifyJWT(incomingJwt).then(({ doc }) => {
return expect(doc).toMatchSnapshot()
})
})
it('verifies the JWT and return correct did for the iss', () => {
return verifyJWT(incomingJwt).then(({ issuer }) => {
return expect(issuer).toEqual(naclId.did)
})
})
it('verifies the JWT and return correct signer', () => {
return verifyJWT(incomingJwt).then(({ signer }) =>
expect(signer).toEqual(publicKey)
)
})
it('verifies the JWT requiring authentication and return correct signer', () => {
return verifyJWT(incomingJwt, { auth: true }).then(({ signer }) =>
expect(signer).toEqual(publicKey)
)
})
})
describe('badJwt', () => {
const badJwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6dXBvcnQ6Mm5RdGlRRzZDZ20xR1lUQmFhS0Fncjc2dVk3aVNleFVrcVg' +
'iLCJpYXQiOjE0ODUzMjExMzMsInJlcXVlc3RlZCI6WyJuYW1lIiwicGhvbmUiXX0.1hyeUGRBb-cgvjD5KKbpVJBF4TfDjYxrI8SWRJ-GyrJrN' +
'LAxt4MutKMFQyF1k_YkxbVozGJ_4XmgZqNaW4OvCX'
it('rejects a JWT with bad signature', () => {
return verifyJWT(badJwt)
.catch(error =>
expect(error.message).toEqual('Signature invalid for JWT')
)
.then(p => expect(p).toBeFalsy())
// tslint:disable-next-line: max-line-length
const badJwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzMjExMzMsImlzcyI6ImRpZDpldGhyOjB4MjBjNzY5ZWM5YzA5OTZiYTc3MzdhNDgyNmMyYWFmZjAwYjFiMjA0MCIsInJlcXVlc3RlZCI6WyJuYW1lIiwicGhvbmUiXX0.TTpuw77fUbd_AY3GJcCumd6F6hxnkskMDJYNpJlI2DQi5MKKudXya9NlyM9e8-KFgTLe-WnXgq9EjWLvjpdiXA'
it('rejects a JWT with bad signature', async () => {
expect(verifyJWT(badJwt)).rejects.toThrowError(
/Signature invalid for JWT/
)
})

@@ -310,3 +241,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzMjExMzMsIm5iZiI6MTQ4NTI2MTEzMywiaXNzIjoiZGlkOnVwb3J0OjJuUXRpUUc2Q2dtMUdZVEJhYUtBZ3I3NnVZN2lTZXhVa3FYIn0.btzVz7fZsoSEDa7JyWo3cYWL63pkWTKTz8OUzepIesfSFeBozUjX2oq1xOJ2OyzuinnLGwtSqY303VoyALrafA'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzMjExMzMsIm5iZiI6MTQ4NTI2MTEzMywiaXNzIjoiZGlkOmV0aHI6MHhmM2JlYWMzMGM0OThkOWUyNjg2NWYzNGZjYWE1N2RiYjkzNWIwZDc0In0.FUasGkOYqGVxQ7S-QQvh4abGO6Dwr961UjjOxtRTyUDnl6q6ElqHqAK-WMDTmOir21pFPKLYZMtLZ4LTLpm3cQ'
// const jwt = await createJWT({nbf: PAST}, {issuer:did, signer})
expect(verifyJWT(jwt)).resolves.not.toThrow()

@@ -316,3 +248,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzODExMzMsIm5iZiI6MTQ4NTI2MTEzMywiaXNzIjoiZGlkOnVwb3J0OjJuUXRpUUc2Q2dtMUdZVEJhYUtBZ3I3NnVZN2lTZXhVa3FYIn0.ELsPnDC_YTTkT5hxw09UCLSjWVje9mDs1n_mpvlo2Wk5VJONSy-FDAzm5TunzzCeLixU04m6dD4w6Uk3-OVkww'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzODExMzMsIm5iZiI6MTQ4NTI2MTEzMywiaXNzIjoiZGlkOmV0aHI6MHhmM2JlYWMzMGM0OThkOWUyNjg2NWYzNGZjYWE1N2RiYjkzNWIwZDc0In0.8BPiSG2e6UBn1osnJ6PJYbPjtPMPaCeutTA9OCp-ZzI-QvvwPCVrrWqTu2YELbzUPwDIJCQ8v8N77xCEjIYSmQ'
// const jwt = await createJWT({nbf:PAST,iat:FUTURE},{issuer:did,signer})
expect(verifyJWT(jwt)).resolves.not.toThrow()

@@ -323,2 +256,3 @@ })

const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzMjExMzMsIm5iZiI6MTQ4NTM4MTEzMywiaXNzIjoiZGlkOnVwb3J0OjJuUXRpUUc2Q2dtMUdZVEJhYUtBZ3I3NnVZN2lTZXhVa3FYIn0.rcFuhVHtie3Y09pWxBSf1dnjaVh6FFQLHh-83N-uLty3M5ADJ-jVFFkyt_Eupl8Kr735-oPGn_D1Nj9rl4s_Kw'
// const jwt = await createJWT({nbf:FUTURE},{issuer:did,signer})
expect(verifyJWT(jwt)).rejects.toThrow()

@@ -328,3 +262,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUyNjExMzMsIm5iZiI6MTQ4NTM4MTEzMywiaXNzIjoiZGlkOnVwb3J0OjJuUXRpUUc2Q2dtMUdZVEJhYUtBZ3I3NnVZN2lTZXhVa3FYIn0.jiVI11IcKNOvnDrJBzojKtNAGaZbEcafcqW-wfP78g6-6RucjYPBi5qvKje35IOvITWvvpXpK48IW-17Srh02w'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUyNjExMzMsIm5iZiI6MTQ4NTM4MTEzMywiaXNzIjoiZGlkOmV0aHI6MHhmM2JlYWMzMGM0OThkOWUyNjg2NWYzNGZjYWE1N2RiYjkzNWIwZDc0In0.JjEn_huxI9SsBY_3PlD0ShpXvrRgUGFDKAgxJBc1Q5GToVpUTw007-o9BTt7JNi_G2XWmcu2aXXnDn0QFsRIrg'
// const jwt = await createJWT({nbf:FUTURE,iat:PAST},{issuer:did,signer})
expect(verifyJWT(jwt)).rejects.toThrow()

@@ -334,3 +269,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUyNjExMzMsImlzcyI6ImRpZDp1cG9ydDoyblF0aVFHNkNnbTFHWVRCYWFLQWdyNzZ1WTdpU2V4VWtxWCJ9.1VwGHDm7f9V-1Fa545uAwF9NfU3RI8yqRFW6XAHOg0FBeM7krC_rEf0PwqbKFO8MiIBELBwUhW_fT4oZsuggUA'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUyNjExMzMsImlzcyI6ImRpZDpldGhyOjB4ZjNiZWFjMzBjNDk4ZDllMjY4NjVmMzRmY2FhNTdkYmI5MzViMGQ3NCJ9.jkzN5kIVtuRU-Fjte8w5r-ttf9OfhdN38oFJd61CWdI5WnvU1dPCvnx1_kdk2D6Xg-uPqp1VXAb7KA2ZECivmg'
// const jwt = await createJWT({iat:PAST},{issuer:did,signer})
expect(verifyJWT(jwt)).resolves.not.toThrow()

@@ -340,3 +276,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzODExMzMsImlzcyI6ImRpZDp1cG9ydDoyblF0aVFHNkNnbTFHWVRCYWFLQWdyNzZ1WTdpU2V4VWtxWCJ9.jU0R8qP3aUX_3DiFt9tIONiq_P5OooFc-ypUwpqK4plGyw6WiI0FTGfZvq7pOarKrjmSojE9Sm_3ETfMpdQckg'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzODExMzMsImlzcyI6ImRpZDpldGhyOjB4ZjNiZWFjMzBjNDk4ZDllMjY4NjVmMzRmY2FhNTdkYmI5MzViMGQ3NCJ9.FJuHvf9Tby7b4I54Cm1nh8CvLg4QH2wt2K0WfyQaLqlr3NKKI5hAdLalgZksI25gLhNrZwQFnC-nzEOs9PI1SQ'
// const jwt = await createJWT({iat:FUTURE},{issuer:did,signer})
expect(verifyJWT(jwt)).rejects.toThrow()

@@ -346,3 +283,4 @@ })

// tslint:disable-next-line: max-line-length
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6dXBvcnQ6Mm5RdGlRRzZDZ20xR1lUQmFhS0Fncjc2dVk3aVNleFVrcVgifQ.5kGKU9ljebhTqvfVDu9MH7vGAqRH0GDTbZNGH45YmhUySgBTyI7u-MkkRit72eFvQAqBfzw6wNUbGf9FPC5AtQ'
const jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6ZXRocjoweGYzYmVhYzMwYzQ5OGQ5ZTI2ODY1ZjM0ZmNhYTU3ZGJiOTM1YjBkNzQifQ.KgnwgMMz-QSOtpba2QMGHMWJoLvhp-H4odjjX1QKnqj4-8dkcK12y7rj7Zq24-1d-1ne86aJCdWtx5VJv3rM7w'
// const jwt = await createJWT({iat:undefined},{issuer:did,signer})
expect(verifyJWT(jwt)).resolves.not.toThrow()

@@ -352,124 +290,85 @@ })

it('handles ES256K-R algorithm', () => {
return createJWT(
it('handles ES256K-R algorithm', async () => {
const jwt = await createJWT(
{ hello: 'world' },
{ issuer: did, signer, alg: 'ES256K-R' }
).then(jwt =>
verifyJWT(jwt).then(
({ payload }) => expect(payload).toMatchSnapshot(),
error => expect(error).toBeNull()
)
)
const { payload } = await verifyJWT(jwt)
return expect(payload).toMatchSnapshot()
})
it('handles ES256K-R algorithm with ethereum address', () => {
return createJWT(
it('handles ES256K-R algorithm with ethereum address', async () => {
const jwt = await createJWT(
{ hello: 'world' },
{ issuer: aud, signer, alg: 'ES256K-R' }
).then(jwt =>
verifyJWT(jwt).then(
({ payload }) => expect(payload).toMatchSnapshot(),
error => expect(error).toBeNull()
)
)
const { payload } = await verifyJWT(jwt)
return expect(payload).toMatchSnapshot()
})
it('accepts a valid exp', () => {
return createJWT(
{ exp: NOW },
{ issuer: did, signer }
).then(jwt =>
verifyJWT(jwt).then(({ payload }) => expect(payload).toBeDefined())
)
it('accepts a valid exp', async () => {
const jwt = await createJWT({ exp: NOW }, { issuer: did, signer })
const { payload } = await verifyJWT(jwt)
return expect(payload).toBeDefined()
})
it('rejects an expired JWT', () => {
return createJWT({ exp: NOW - NBF_SKEW - 1 }, { issuer: did, signer }).then(
jwt =>
verifyJWT(jwt)
.catch(error =>
expect(error.message).toEqual(
'JWT has expired: exp: 1485320832 < now: 1485321133'
)
)
.then(p => expect(p).toBeFalsy())
it('rejects an expired JWT', async () => {
const jwt = await createJWT(
{ exp: NOW - NBF_SKEW - 1 },
{ issuer: did, signer }
)
expect(verifyJWT(jwt))
.rejects
.toThrow(/JWT has expired/)
})
it('accepts a valid audience', () => {
return createJWT({ aud }, { issuer: did, signer }).then(jwt =>
verifyJWT(jwt, { audience: aud }).then(({ payload }) =>
expect(payload).toMatchSnapshot()
)
)
it('accepts a valid audience', async () => {
const jwt = await createJWT({ aud }, { issuer: did, signer })
const { payload } = await verifyJWT(jwt, { audience: aud })
return expect(payload).toMatchSnapshot()
})
it('accepts a valid MNID audience', () => {
return createJWT({ aud }, { issuer: did, signer }).then(jwt =>
verifyJWT(jwt, { audience: audMnid }).then(({ payload }) =>
expect(payload).toMatchSnapshot()
)
)
})
it('accepts a valid audience using callback_url', () => {
return createJWT(
it('accepts a valid audience using callback_url', async () => {
const jwt = await createJWT(
{ aud: 'http://pututu.uport.me/unique' },
{ issuer: did, signer }
).then(jwt =>
verifyJWT(jwt, { callbackUrl: 'http://pututu.uport.me/unique' }).then(
({ payload }) => expect(payload).toMatchSnapshot()
)
)
const { payload } = await verifyJWT(jwt, {
callbackUrl: 'http://pututu.uport.me/unique'
})
return expect(payload).toMatchSnapshot()
})
it('rejects invalid audience', () => {
return createJWT({ aud }, { issuer: did, signer }).then(jwt =>
verifyJWT(jwt, { audience: did })
.catch(error =>
expect(error.message).toEqual(
'JWT audience does not match your DID: aud: did:uport:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqY !== yours: did:uport:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX'
)
)
.then(p => expect(p).toBeFalsy())
)
it('rejects invalid audience', async () => {
const jwt = await createJWT({ aud }, { issuer: did, signer })
expect(verifyJWT(jwt, { audience: did }))
.rejects
.toThrow(/JWT audience does not match your DID/)
})
it('rejects an invalid audience using callback_url where callback is wrong', () => {
return createJWT(
it('rejects an invalid audience using callback_url where callback is wrong', async () => {
const jwt = await createJWT(
{ aud: 'http://pututu.uport.me/unique' },
{ issuer: did, signer }
).then(jwt =>
verifyJWT(jwt, { callbackUrl: 'http://pututu.uport.me/unique/1' }).catch(
error =>
expect(error.message).toEqual(
'JWT audience does not match the callback url: aud: http://pututu.uport.me/unique !== url: http://pututu.uport.me/unique/1'
)
)
)
expect(verifyJWT(jwt, { callbackUrl: 'http://pututu.uport.me/unique/1' }))
.rejects
.toThrow(/JWT audience does not match the callback url/)
})
it('rejects an invalid audience using callback_url where callback is missing', () => {
return createJWT(
it('rejects an invalid audience using callback_url where callback is missing', async () => {
const jwt = await createJWT(
{ aud: 'http://pututu.uport.me/unique' },
{ issuer: did, signer }
).then(jwt =>
verifyJWT(jwt).catch(error =>
expect(error.message).toEqual(
"JWT audience matching your callback url is required but one wasn't passed in"
)
)
)
expect(verifyJWT(jwt))
.rejects
.toThrow('JWT audience matching your callback url is required but one wasn\'t passed in')
})
it('rejects invalid audience as no address is present', () => {
return createJWT({ aud }, { issuer: did, signer }).then(jwt =>
verifyJWT(jwt)
.catch(error =>
expect(error.message).toEqual(
'JWT audience is required but your app address has not been configured'
)
)
.then(p => expect(p).toBeFalsy())
)
it('rejects invalid audience as no address is present', async () => {
const jwt = await createJWT({ aud }, { issuer: did, signer })
expect(verifyJWT(jwt))
.rejects
.toThrow('JWT audience is required but your app address has not been configured')
})

@@ -563,5 +462,9 @@ })

describe('DID', () => {
afterEach(() => {
resolver.resolve = originalResolve
})
describe('ES256K', () => {
it('finds public key', async () => {
registerResolver((mnid, cb) => cb(null, singleKey))
resolver.resolve = jest.fn().mockReturnValue(singleKey)
const authenticators = await resolveAuthenticator(alg, did)

@@ -576,3 +479,3 @@ return expect(authenticators).toEqual({

it('filters out irrelevant public keys', async () => {
registerResolver((mnid, cb) => cb(null, multipleKeys))
resolver.resolve = jest.fn().mockReturnValue(multipleKeys)
const authenticators = await resolveAuthenticator(alg, did)

@@ -587,3 +490,3 @@ return expect(authenticators).toEqual({

it('only list authenticators able to authenticate a user', async () => {
registerResolver((mnid, cb) => cb(null, multipleKeys))
resolver.resolve = jest.fn().mockReturnValue(multipleKeys)
const authenticators = await resolveAuthenticator(alg, did, true)

@@ -598,3 +501,3 @@ return expect(authenticators).toEqual({

it('errors if no suitable public keys exist', async () => {
registerResolver((mnid, cb) => cb(null, unsupportedFormat))
resolver.resolve = jest.fn().mockReturnValue(unsupportedFormat)
return expect(resolveAuthenticator(alg, did)).rejects.toEqual(

@@ -611,3 +514,3 @@ new Error(

it('filters out irrelevant public keys', async () => {
registerResolver((mnid, cb) => cb(null, multipleKeys))
resolver.resolve = jest.fn().mockReturnValue(multipleKeys)
const authenticators = await resolveAuthenticator(alg, did)

@@ -622,3 +525,3 @@ return expect(authenticators).toEqual({

it('only list authenticators able to authenticate a user', async () => {
registerResolver((mnid, cb) => cb(null, multipleKeys))
resolver.resolve = jest.fn().mockReturnValue(multipleKeys)
const authenticators = await resolveAuthenticator(alg, did, true)

@@ -633,3 +536,3 @@ return expect(authenticators).toEqual({

it('errors if no suitable public keys exist', async () => {
registerResolver((mnid, cb) => cb(null, unsupportedFormat))
resolver.resolve = jest.fn().mockReturnValue(unsupportedFormat)
return expect(resolveAuthenticator(alg, did)).rejects.toEqual(

@@ -644,3 +547,3 @@ new Error(

it('errors if no suitable public keys exist for authentication', async () => {
registerResolver((mnid, cb) => cb(null, singleKey))
resolver.resolve = jest.fn().mockReturnValue(singleKey)
return expect(resolveAuthenticator(alg, did, true)).rejects.toEqual(

@@ -654,3 +557,3 @@ new Error(

it('errors if no public keys exist', async () => {
registerResolver((mnid, cb) => cb(null, noPublicKey))
resolver.resolve = jest.fn().mockReturnValue(noPublicKey)
return expect(resolveAuthenticator(alg, did)).rejects.toEqual(

@@ -664,3 +567,3 @@ new Error(

it('errors if no DID document exists', async () => {
registerResolver((mnid, cb) => cb(null, null))
resolver.resolve = jest.fn().mockReturnValue(null)
return expect(resolveAuthenticator(alg, did)).rejects.toEqual(

@@ -672,3 +575,3 @@ new Error(`Unable to resolve DID document for ${did}`)

it('errors if no supported signature types exist', async () => {
registerResolver((mnid, cb) => cb(null, singleKey))
resolver.resolve = jest.fn().mockReturnValue(singleKey)
return expect(resolveAuthenticator('ESBAD', did)).rejects.toEqual(

@@ -680,13 +583,15 @@ new Error(`No supported signature types for algorithm ESBAD`)

describe('MNID', () => {
it('converts MNID to DID and finds public key', async () => {
registerResolver((mnid, cb) => cb(null, singleKey))
const authenticators = await resolveAuthenticator(alg, mnid)
return expect(authenticators).toEqual({
authenticators: [ecKey1],
issuer: did,
doc: singleKey
})
describe('normalizeDID', () => {
it('returns the value if it is already a did', () => {
expect(normalizeDID(did)).toEqual(did)
})
it('converts an mnid into a did', () => {
expect(normalizeDID('2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX')).toEqual(
'did:uport:2nQtiQG6Cgm1GYTBaaKAgr76uY7iSexUkqX'
)
})
it('throws if the value is neither a did nor an mnid', () => {
expect(() => normalizeDID('notadid!')).toThrow()
})
})
})
import VerifierAlgorithm from './VerifierAlgorithm'
import SignerAlgorithm from './SignerAlgorithm'
import base64url from 'uport-base64url'
import resolve, { DIDDocument, PublicKey } from 'did-resolver'
import { Resolver, DIDDocument, PublicKey } from 'did-resolver'
import { getResolver as getEthrDidResolver } from 'ethr-did-resolver'
import getHttpsDidResolver from 'https-did-resolver'

@@ -85,5 +87,9 @@ export interface EcdsaSignature {

const JOSE_HEADER = { typ: 'JWT' }
const defaultAlg = 'ES256K'
export const resolver = new Resolver({
...getEthrDidResolver(),
...getHttpsDidResolver()
})
function encodeSection(data: any): string {

@@ -300,3 +306,3 @@ return base64url.encode(JSON.stringify(data))

const issuer: string = normalizeDID(mnidOrDid)
const doc: DIDDocument = await resolve(issuer)
const doc: DIDDocument = await resolver.resolve(issuer)
if (!doc) throw new Error(`Unable to resolve DID document for ${issuer}`)

@@ -303,0 +309,0 @@ // is there some way to have authenticationKeys be a single type?

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

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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