diff --git a/.gitignore b/.gitignore index 71f07fb0..f40ae4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,6 @@ unused # Folder to ignore for development with es6 lib -docs/tokenfiles/*.json +docs/token-files/*.json src/testing/browser/blockstack-proofs.js diff --git a/docs/token-files/balloonDog.json b/docs/token-files/balloonDog.json deleted file mode 100644 index 8d57ac9c..00000000 --- a/docs/token-files/balloonDog.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiI2ZDJmYzM1My0yNDE5LTQ0MjktYmVmMi03NDAzNTNmYTA1MjUiLCJpYXQiOiIyMDE3LTAyLTI2VDIwOjE3OjI4LjUwNloiLCJleHAiOiIyMDE4LTAyLTI2VDIwOjE3OjI4LjUwNloiLCJzdWJqZWN0Ijp7InB1YmxpY0tleSI6IjAzODVmMzNmYTk0MjVhOTQwZjg1YmE0NjNmN2I2ZjIyYjE1NjcxNjNkMmZlNjAzNGNlMDkzY2NiOGUyOTgwZWRhYSJ9LCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDM4NWYzM2ZhOTQyNWE5NDBmODViYTQ2M2Y3YjZmMjJiMTU2NzE2M2QyZmU2MDM0Y2UwOTNjY2I4ZTI5ODBlZGFhIn0sImNsYWltIjp7IkBjb250ZXh0IjoiaHR0cDovL3NjaGVtYS5vcmcvIiwiQHR5cGUiOiJDcmVhdGl2ZVdvcmsiLCJuYW1lIjoiQmFsbG9vbiBEb2ciLCJjcmVhdG9yIjpbeyJAdHlwZSI6IlBlcnNvbiIsIkBpZCI6InRoZXJlYWxqZWZma29vbnMuaWQiLCJuYW1lIjoiSmVmZiBLb29ucyJ9XSwiZGF0ZUNyZWF0ZWQiOiIxOTk0LTA1LTA5VDAwOjAwOjAwLTA0MDAiLCJkYXRlUHVibGlzaGVkIjoiMjAxNS0xMi0xMFQxNDo0NDoyNi0wNTAwIn19.vfd6vt3ARA38UJMN34EtF0Nl6buH9HMfYpHgpzVxWhIcO1dKpM4nSQvZTGKcUki0k7vh9CHpjv33K53rjes8gA", - "decodedToken": { - "header": { - "typ": "JWT", - "alg": "ES256K" - }, - "payload": { - "jti": "6d2fc353-2419-4429-bef2-740353fa0525", - "iat": "2017-02-26T20:17:28.506Z", - "exp": "2018-02-26T20:17:28.506Z", - "subject": { - "publicKey": "0385f33fa9425a940f85ba463f7b6f22b1567163d2fe6034ce093ccb8e2980edaa" - }, - "issuer": { - "publicKey": "0385f33fa9425a940f85ba463f7b6f22b1567163d2fe6034ce093ccb8e2980edaa" - }, - "claim": { - "@context": "http://schema.org/", - "@type": "CreativeWork", - "name": "Balloon Dog", - "creator": [ - { - "@type": "Person", - "@id": "therealjeffkoons.id", - "name": "Jeff Koons" - } - ], - "dateCreated": "1994-05-09T00:00:00-0400", - "datePublished": "2015-12-10T14:44:26-0500" - } - }, - "signature": "vfd6vt3ARA38UJMN34EtF0Nl6buH9HMfYpHgpzVxWhIcO1dKpM4nSQvZTGKcUki0k7vh9CHpjv33K53rjes8gA" - } - } -] \ No newline at end of file diff --git a/docs/token-files/google.json b/docs/token-files/google.json deleted file mode 100644 index e8d6b8a7..00000000 --- a/docs/token-files/google.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiJjZjY2MmNkNi0xNDI1LTQ3YzktOWE1ZS1kMWFlYzExNTQwNzAiLCJpYXQiOiIyMDE3LTAyLTI2VDIwOjE3OjI4LjQzOFoiLCJleHAiOiIyMDE4LTAyLTI2VDIwOjE3OjI4LjQzOFoiLCJzdWJqZWN0Ijp7InB1YmxpY0tleSI6IjAzZmQyYzkxMTM1NjAxNTg1YTUxMGMzMTE0Zjg5OTk2NTQxMDcwNWEwNDc0NjU3MjEwOTdiYTU4NTg2ZTQ5NDEzNiJ9LCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDNmZDJjOTExMzU2MDE1ODVhNTEwYzMxMTRmODk5OTY1NDEwNzA1YTA0NzQ2NTcyMTA5N2JhNTg1ODZlNDk0MTM2In0sImNsYWltIjp7IkBjb250ZXh0IjoiaHR0cDovL3NjaGVtYS5vcmcvIiwiQHR5cGUiOiJPcmdhbml6YXRpb24iLCJuYW1lIjoiR29vZ2xlIiwibGVnYWxOYW1lIjoiR29vZ2xlIEluYy4iLCJlbWFpbCI6ImhlbGxvQGdvb2dsZS5vcmciLCJhZGRyZXNzIjp7IkB0eXBlIjoiUG9zdGFsQWRkcmVzcyIsImFkZHJlc3NMb2NhbGl0eSI6Ik1vdW50YWluIFZpZXcsIENBIiwicG9zdGFsQ29kZSI6Ijk0MDQzIiwic3RyZWV0QWRkcmVzcyI6IjE2MDAgQW1waGl0aGVhdHJlIFBhcmt3YXkifSwiZW1wbG95ZWUiOlt7IkB0eXBlIjoiUGVyc29uIiwiQGlkIjoibGFycnlwYWdlLmlkIiwibmFtZSI6IkxhcnJ5IFBhZ2UifSx7IkB0eXBlIjoiUGVyc29uIiwiQGlkIjoic2VyZ2V5YnJpbi5pZCIsIm5hbWUiOiJTZXJnZXkgQnJpbiJ9XSwiaW1hZ2UiOlt7IkB0eXBlIjoiSW1hZ2VPYmplY3QiLCJuYW1lIjoibG9nbyIsImNvbnRlbnRVcmwiOiJodHRwczovL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzJ4L2dvb2dsZWxvZ29fY29sb3JfMjcyeDkyZHAucG5nIn1dLCJwYXJlbnRPcmdhbml6YXRpb24iOnsiQHR5cGUiOiJPcmdhbml6YXRpb24iLCJAaWQiOiJhbHBoYWJldC5pZCIsIm5hbWUiOiJBbHBoYWJldCBJbmMuIn19fQ.hrF-bxIIAQ3zw2KjddH88cjv_ao0ua5XQPddBrCnT5xnwwQ0lvsrAM3uRq9ib98Bldd0N6YBBzL668g2Ao09Fw", - "decodedToken": { - "header": { - "typ": "JWT", - "alg": "ES256K" - }, - "payload": { - "jti": "cf662cd6-1425-47c9-9a5e-d1aec1154070", - "iat": "2017-02-26T20:17:28.438Z", - "exp": "2018-02-26T20:17:28.438Z", - "subject": { - "publicKey": "03fd2c91135601585a510c3114f899965410705a047465721097ba58586e494136" - }, - "issuer": { - "publicKey": "03fd2c91135601585a510c3114f899965410705a047465721097ba58586e494136" - }, - "claim": { - "@context": "http://schema.org/", - "@type": "Organization", - "name": "Google", - "legalName": "Google Inc.", - "email": "hello@google.org", - "address": { - "@type": "PostalAddress", - "addressLocality": "Mountain View, CA", - "postalCode": "94043", - "streetAddress": "1600 Amphitheatre Parkway" - }, - "employee": [ - { - "@type": "Person", - "@id": "larrypage.id", - "name": "Larry Page" - }, - { - "@type": "Person", - "@id": "sergeybrin.id", - "name": "Sergey Brin" - } - ], - "image": [ - { - "@type": "ImageObject", - "name": "logo", - "contentUrl": "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" - } - ], - "parentOrganization": { - "@type": "Organization", - "@id": "alphabet.id", - "name": "Alphabet Inc." - } - } - }, - "signature": "hrF-bxIIAQ3zw2KjddH88cjv_ao0ua5XQPddBrCnT5xnwwQ0lvsrAM3uRq9ib98Bldd0N6YBBzL668g2Ao09Fw" - } - } -] \ No newline at end of file diff --git a/docs/token-files/naval-4-tokens.json b/docs/token-files/naval-4-tokens.json deleted file mode 100644 index 9b20debc..00000000 --- a/docs/token-files/naval-4-tokens.json +++ /dev/null @@ -1,106 +0,0 @@ -[ - { - "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiIyNThkMTI4NS0yZDhjLTRhOTEtYjQ2OC0zMDRjODVkYTUxYzgiLCJpYXQiOiIyMDE3LTAyLTI2VDIwOjE3OjI4LjU5NFoiLCJleHAiOiIyMDE4LTAyLTI2VDIwOjE3OjI4LjU5NFoiLCJzdWJqZWN0Ijp7InB1YmxpY0tleSI6IjAyZDY2Y2UwOWI4ZWNkZTYyYjQ2NzcxMTEyMTYyZGY5YzlmNzU3MDJmYjdlZTU0NmZkMjYxZGQxYmZjZTU2NTk2MyJ9LCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDJkNjZjZTA5YjhlY2RlNjJiNDY3NzExMTIxNjJkZjljOWY3NTcwMmZiN2VlNTQ2ZmQyNjFkZDFiZmNlNTY1OTYzIn0sImNsYWltIjp7IkB0eXBlIjoiUGVyc29uIiwiQGNvbnRleHQiOiJodHRwOi8vc2NoZW1hLm9yZy8iLCJuYW1lIjoiTmF2YWwgUmF2aWthbnQiLCJnaXZlbk5hbWUiOiJOYXZhbCIsImZhbWlseU5hbWUiOiJSYXZpa2FudCIsImRlc2NyaXB0aW9uIjoiQ28tZm91bmRlciBvZiBBbmdlbExpc3QiLCJpbWFnZSI6W3siQHR5cGUiOiJJbWFnZU9iamVjdCIsIm5hbWUiOiJhdmF0YXIiLCJjb250ZW50VXJsIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzM2OTY2MTczMjgvNjY3ODc0YzU5MzY3NjRkOTNkNTZjY2M3NmEyYmNjMTMuanBlZyJ9LHsiQHR5cGUiOiJJbWFnZU9iamVjdCIsIm5hbWUiOiJiYWNrZ3JvdW5kIiwiY29udGVudFVybCI6Imh0dHBzOi8vcGJzLnR3aW1nLmNvbS9wcm9maWxlX2Jhbm5lcnMvNzQ1MjczLzEzNTU3MDU3Nzcvd2ViX3JldGluYSJ9XSwid2Vic2l0ZSI6W3siQHR5cGUiOiJXZWJTaXRlIiwidXJsIjoiYW5nZWwuY28ifV0sImFjY291bnQiOlt7IkB0eXBlIjoiQWNjb3VudCIsInNlcnZpY2UiOiJmYWNlYm9vayIsImlkZW50aWZpZXIiOiJuYXZhbHIiLCJwcm9vZlR5cGUiOiJodHRwIiwicHJvb2ZVcmwiOiJodHRwczovL2ZhY2Vib29rLmNvbS9uYXZhbHIvcG9zdHMvMTAxNTIxOTA3MzQwNzcyNjEifSx7IkB0eXBlIjoiQWNjb3VudCIsInNlcnZpY2UiOiJ0d2l0dGVyIiwiaWRlbnRpZmllciI6Im5hdmFsIiwicHJvb2ZUeXBlIjoiaHR0cCIsInByb29mVXJsIjoiaHR0cHM6Ly90d2l0dGVyLmNvbS9uYXZhbC9zdGF0dXMvNDg2NjA5MjY2MjEyNDk5NDU2In0seyJAdHlwZSI6IkFjY291bnQiLCJzZXJ2aWNlIjoiZ2l0aHViIiwiaWRlbnRpZmllciI6Im5hdmFsciIsInByb29mVHlwZSI6Imh0dHAiLCJwcm9vZlVybCI6Imh0dHBzOi8vZ2lzdC5naXRodWIuY29tL25hdmFsci9mMzFhNzQwNTRmODU5ZWMwYWM2YSJ9LHsiQHR5cGUiOiJBY2NvdW50Iiwic2VydmljZSI6ImJpdGNvaW4iLCJyb2xlIjoicGF5bWVudCIsImlkZW50aWZpZXIiOiIxOTE5VXJoWXloczQ3MXBzOENGY0ozRFJwV1NkYThxdFNrIiwicHJvb2ZUeXBlIjoic2lnbmF0dXJlIiwicHJvb2ZNZXNzYWdlIjoiVmVyaWZ5aW5nIHRoYXQgK25hdmFsIGlzIG15IGJsb2NrY2hhaW4gSUQuIiwicHJvb2ZTaWduYXR1cmUiOiJJQ3VSQStEcTVEbjhBaVk5UCttY0x6R3lpYlBnRzBlYzlDcGh0TWs1MTJ1UGRCNWVBbmNEU0hoUVpZLzdreWN2bDZQTEZFdVIrajNPTS9LMlZleTErRVU9In1dLCJ3b3Jrc0ZvciI6W3siQHR5cGUiOiJPcmdhbml6YXRpb24iLCJAaWQiOiJhbmdlbGxpc3QuaWQifV0sImtub3dzIjpbeyJAdHlwZSI6IlBlcnNvbiIsIkBpZCI6Im11bmVlYi5pZCJ9LHsiQHR5cGUiOiJQZXJzb24iLCJAaWQiOiJyeWFuLmlkIn1dLCJiaXJ0aERhdGUiOiIxOTczLTAxLTAxIiwidGF4SUQiOiIwMDAtMDAtMDAwMCIsImFkZHJlc3MiOnsiQHR5cGUiOiJQb3N0YWxBZGRyZXNzIiwic3RyZWV0QWRkcmVzcyI6IjE2IE1haWRlbiBMbiIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28sIENBIiwicG9zdGFsQ29kZSI6Ijk0MTA4IiwiYWRkcmVzc0NvdW50cnkiOiJVbml0ZWQgU3RhdGVzIn19fQ.YLlbAJW9dWKMxTQcNFa1wOWgrOTUjJbCMlVnMd2teNa1GHZsC_CdwKzOHl_QZkCdBJ3MT0slgxr2OE6m6PlC_w", - "decodedToken": { - "header": { - "typ": "JWT", - "alg": "ES256K" - }, - "payload": { - "jti": "258d1285-2d8c-4a91-b468-304c85da51c8", - "iat": "2017-02-26T20:17:28.594Z", - "exp": "2018-02-26T20:17:28.594Z", - "subject": { - "publicKey": "02d66ce09b8ecde62b46771112162df9c9f75702fb7ee546fd261dd1bfce565963" - }, - "issuer": { - "publicKey": "02d66ce09b8ecde62b46771112162df9c9f75702fb7ee546fd261dd1bfce565963" - }, - "claim": { - "@type": "Person", - "@context": "http://schema.org/", - "name": "Naval Ravikant", - "givenName": "Naval", - "familyName": "Ravikant", - "description": "Co-founder of AngelList", - "image": [ - { - "@type": "ImageObject", - "name": "avatar", - "contentUrl": "https://pbs.twimg.com/profile_images/3696617328/667874c5936764d93d56ccc76a2bcc13.jpeg" - }, - { - "@type": "ImageObject", - "name": "background", - "contentUrl": "https://pbs.twimg.com/profile_banners/745273/1355705777/web_retina" - } - ], - "website": [ - { - "@type": "WebSite", - "url": "angel.co" - } - ], - "account": [ - { - "@type": "Account", - "service": "facebook", - "identifier": "navalr", - "proofType": "http", - "proofUrl": "https://facebook.com/navalr/posts/10152190734077261" - }, - { - "@type": "Account", - "service": "twitter", - "identifier": "naval", - "proofType": "http", - "proofUrl": "https://twitter.com/naval/status/486609266212499456" - }, - { - "@type": "Account", - "service": "github", - "identifier": "navalr", - "proofType": "http", - "proofUrl": "https://gist.github.com/navalr/f31a74054f859ec0ac6a" - }, - { - "@type": "Account", - "service": "bitcoin", - "role": "payment", - "identifier": "1919UrhYyhs471ps8CFcJ3DRpWSda8qtSk", - "proofType": "signature", - "proofMessage": "Verifying that +naval is my blockchain ID.", - "proofSignature": "ICuRA+Dq5Dn8AiY9P+mcLzGyibPgG0ec9CphtMk512uPdB5eAncDSHhQZY/7kycvl6PLFEuR+j3OM/K2Vey1+EU=" - } - ], - "worksFor": [ - { - "@type": "Organization", - "@id": "angellist.id" - } - ], - "knows": [ - { - "@type": "Person", - "@id": "muneeb.id" - }, - { - "@type": "Person", - "@id": "ryan.id" - } - ], - "birthDate": "1973-01-01", - "taxID": "000-00-0000", - "address": { - "@type": "PostalAddress", - "streetAddress": "16 Maiden Ln", - "addressLocality": "San Francisco, CA", - "postalCode": "94108", - "addressCountry": "United States" - } - } - }, - "signature": "YLlbAJW9dWKMxTQcNFa1wOWgrOTUjJbCMlVnMd2teNa1GHZsC_CdwKzOHl_QZkCdBJ3MT0slgxr2OE6m6PlC_w" - } - } -] \ No newline at end of file diff --git a/docs/token-files/naval.json b/docs/token-files/naval.json deleted file mode 100644 index 4e3cd022..00000000 --- a/docs/token-files/naval.json +++ /dev/null @@ -1,106 +0,0 @@ -[ - { - "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiJmMjY2NzI2MS1jOTZlLTRjOGQtYmIwNy0xMTI2MzdmYWY5M2QiLCJpYXQiOiIyMDE3LTAyLTI2VDIwOjE3OjI4LjM2OVoiLCJleHAiOiIyMDE4LTAyLTI2VDIwOjE3OjI4LjM2OVoiLCJzdWJqZWN0Ijp7InB1YmxpY0tleSI6IjAzZDRiNzIzNWQ4OWYxNmM0ZmY3NGFmYzRhOGY2ZTI1ZmFkNjI1ZjY3MWQxNDk0YjI4NDc0YTM0ZDFmZWI2NmYzMyJ9LCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDNkNGI3MjM1ZDg5ZjE2YzRmZjc0YWZjNGE4ZjZlMjVmYWQ2MjVmNjcxZDE0OTRiMjg0NzRhMzRkMWZlYjY2ZjMzIn0sImNsYWltIjp7IkBjb250ZXh0IjoiaHR0cDovL3NjaGVtYS5vcmcvIiwiQHR5cGUiOiJQZXJzb24iLCJuYW1lIjoiTmF2YWwgUmF2aWthbnQiLCJnaXZlbk5hbWUiOiJOYXZhbCIsImZhbWlseU5hbWUiOiJSYXZpa2FudCIsImRlc2NyaXB0aW9uIjoiQ28tZm91bmRlciBvZiBBbmdlbExpc3QiLCJpbWFnZSI6W3siQHR5cGUiOiJJbWFnZU9iamVjdCIsIm5hbWUiOiJhdmF0YXIiLCJjb250ZW50VXJsIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzM2OTY2MTczMjgvNjY3ODc0YzU5MzY3NjRkOTNkNTZjY2M3NmEyYmNjMTMuanBlZyJ9LHsiQHR5cGUiOiJJbWFnZU9iamVjdCIsIm5hbWUiOiJiYWNrZ3JvdW5kIiwiY29udGVudFVybCI6Imh0dHBzOi8vcGJzLnR3aW1nLmNvbS9wcm9maWxlX2Jhbm5lcnMvNzQ1MjczLzEzNTU3MDU3Nzcvd2ViX3JldGluYSJ9XSwid2Vic2l0ZSI6W3siQHR5cGUiOiJXZWJTaXRlIiwidXJsIjoiYW5nZWwuY28ifV0sImFjY291bnQiOlt7IkB0eXBlIjoiQWNjb3VudCIsInNlcnZpY2UiOiJmYWNlYm9vayIsImlkZW50aWZpZXIiOiJuYXZhbHIiLCJwcm9vZlR5cGUiOiJodHRwIiwicHJvb2ZVcmwiOiJodHRwczovL2ZhY2Vib29rLmNvbS9uYXZhbHIvcG9zdHMvMTAxNTIxOTA3MzQwNzcyNjEifSx7IkB0eXBlIjoiQWNjb3VudCIsInNlcnZpY2UiOiJ0d2l0dGVyIiwiaWRlbnRpZmllciI6Im5hdmFsIiwicHJvb2ZUeXBlIjoiaHR0cCIsInByb29mVXJsIjoiaHR0cHM6Ly90d2l0dGVyLmNvbS9uYXZhbC9zdGF0dXMvNDg2NjA5MjY2MjEyNDk5NDU2In0seyJAdHlwZSI6IkFjY291bnQiLCJzZXJ2aWNlIjoiZ2l0aHViIiwiaWRlbnRpZmllciI6Im5hdmFsciIsInByb29mVHlwZSI6Imh0dHAiLCJwcm9vZlVybCI6Imh0dHBzOi8vZ2lzdC5naXRodWIuY29tL25hdmFsci9mMzFhNzQwNTRmODU5ZWMwYWM2YSJ9LHsiQHR5cGUiOiJBY2NvdW50Iiwic2VydmljZSI6ImJpdGNvaW4iLCJyb2xlIjoicGF5bWVudCIsImlkZW50aWZpZXIiOiIxOTE5VXJoWXloczQ3MXBzOENGY0ozRFJwV1NkYThxdFNrIiwicHJvb2ZUeXBlIjoic2lnbmF0dXJlIiwicHJvb2ZNZXNzYWdlIjoiVmVyaWZ5aW5nIHRoYXQgK25hdmFsIGlzIG15IGJsb2NrY2hhaW4gSUQuIiwicHJvb2ZTaWduYXR1cmUiOiJJQ3VSQStEcTVEbjhBaVk5UCttY0x6R3lpYlBnRzBlYzlDcGh0TWs1MTJ1UGRCNWVBbmNEU0hoUVpZLzdreWN2bDZQTEZFdVIrajNPTS9LMlZleTErRVU9In1dLCJ3b3Jrc0ZvciI6W3siQHR5cGUiOiJPcmdhbml6YXRpb24iLCJAaWQiOiJhbmdlbGxpc3QuaWQifV0sImtub3dzIjpbeyJAdHlwZSI6IlBlcnNvbiIsIkBpZCI6Im11bmVlYi5pZCJ9LHsiQHR5cGUiOiJQZXJzb24iLCJAaWQiOiJyeWFuLmlkIn1dLCJiaXJ0aERhdGUiOiIxOTczLTAxLTAxIiwidGF4SUQiOiIwMDAtMDAtMDAwMCIsImFkZHJlc3MiOnsiQHR5cGUiOiJQb3N0YWxBZGRyZXNzIiwic3RyZWV0QWRkcmVzcyI6IjE2IE1haWRlbiBMbiIsImFkZHJlc3NMb2NhbGl0eSI6IlNhbiBGcmFuY2lzY28sIENBIiwicG9zdGFsQ29kZSI6Ijk0MTA4IiwiYWRkcmVzc0NvdW50cnkiOiJVbml0ZWQgU3RhdGVzIn19fQ.yVrQR9sNuyjHcknnbBa5BwILYc4caT8fod6BO6nTnn_cfk8qRINHd4FkV4WC2GssE52OtRElM3DByR5BQi7bbQ", - "decodedToken": { - "header": { - "typ": "JWT", - "alg": "ES256K" - }, - "payload": { - "jti": "f2667261-c96e-4c8d-bb07-112637faf93d", - "iat": "2017-02-26T20:17:28.369Z", - "exp": "2018-02-26T20:17:28.369Z", - "subject": { - "publicKey": "03d4b7235d89f16c4ff74afc4a8f6e25fad625f671d1494b28474a34d1feb66f33" - }, - "issuer": { - "publicKey": "03d4b7235d89f16c4ff74afc4a8f6e25fad625f671d1494b28474a34d1feb66f33" - }, - "claim": { - "@context": "http://schema.org/", - "@type": "Person", - "name": "Naval Ravikant", - "givenName": "Naval", - "familyName": "Ravikant", - "description": "Co-founder of AngelList", - "image": [ - { - "@type": "ImageObject", - "name": "avatar", - "contentUrl": "https://pbs.twimg.com/profile_images/3696617328/667874c5936764d93d56ccc76a2bcc13.jpeg" - }, - { - "@type": "ImageObject", - "name": "background", - "contentUrl": "https://pbs.twimg.com/profile_banners/745273/1355705777/web_retina" - } - ], - "website": [ - { - "@type": "WebSite", - "url": "angel.co" - } - ], - "account": [ - { - "@type": "Account", - "service": "facebook", - "identifier": "navalr", - "proofType": "http", - "proofUrl": "https://facebook.com/navalr/posts/10152190734077261" - }, - { - "@type": "Account", - "service": "twitter", - "identifier": "naval", - "proofType": "http", - "proofUrl": "https://twitter.com/naval/status/486609266212499456" - }, - { - "@type": "Account", - "service": "github", - "identifier": "navalr", - "proofType": "http", - "proofUrl": "https://gist.github.com/navalr/f31a74054f859ec0ac6a" - }, - { - "@type": "Account", - "service": "bitcoin", - "role": "payment", - "identifier": "1919UrhYyhs471ps8CFcJ3DRpWSda8qtSk", - "proofType": "signature", - "proofMessage": "Verifying that +naval is my blockchain ID.", - "proofSignature": "ICuRA+Dq5Dn8AiY9P+mcLzGyibPgG0ec9CphtMk512uPdB5eAncDSHhQZY/7kycvl6PLFEuR+j3OM/K2Vey1+EU=" - } - ], - "worksFor": [ - { - "@type": "Organization", - "@id": "angellist.id" - } - ], - "knows": [ - { - "@type": "Person", - "@id": "muneeb.id" - }, - { - "@type": "Person", - "@id": "ryan.id" - } - ], - "birthDate": "1973-01-01", - "taxID": "000-00-0000", - "address": { - "@type": "PostalAddress", - "streetAddress": "16 Maiden Ln", - "addressLocality": "San Francisco, CA", - "postalCode": "94108", - "addressCountry": "United States" - } - } - }, - "signature": "yVrQR9sNuyjHcknnbBa5BwILYc4caT8fod6BO6nTnn_cfk8qRINHd4FkV4WC2GssE52OtRElM3DByR5BQi7bbQ" - } - } -] \ No newline at end of file diff --git a/docs/token-files/ryan.json b/docs/token-files/ryan.json deleted file mode 100644 index c1179406..00000000 --- a/docs/token-files/ryan.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "decodedToken": { - "header": { - "alg": "ES256K", - "typ": "JWT" - }, - "payload": { - "issuedAt": "2016-12-21T02:20:24.575047", - "claim": { - "image": [ - { - "contentUrl": "https://s3.amazonaws.com/kd4/ryan", - "name": "avatar", - "@type": "ImageObject" - }, - { - "contentUrl": "https://s3.amazonaws.com/dx3/ryan", - "name": "cover", - "@type": "ImageObject" - } - ], - "@type": "Person", - "website": [ - { - "url": "http://shea.io", - "@type": "WebSite" - } - ], - "description": "Co-founder of Blockstack Inc.", - "address": { - "addressLocality": "New York", - "@type": "PostalAddress" - }, - "account": [ - { - "identifier": "1LFS37yRSibwbf8CnXeCn5t1GKeTEZMmu9", - "role": "payment", - "@type": "Account", - "service": "bitcoin" - }, - { - "contentUrl": "https://s3.amazonaws.com/pk9/ryan", - "identifier": "1E4329E6634C75730D4D88C0638F2769D55B9837", - "@type": "Account", - "service": "pgp" - }, - { - "identifier": "f2250123a6af138c86b30f3233b338961dc8fbc3", - "proofType": "http", - "proofUrl": "https://www.facebook.com/msrobot0/posts/10153644446452759", - "service": "openbazaar", - "@type": "Account" - }, - { - "identifier": "ryaneshea", - "proofType": "http", - "proofUrl": "https://twitter.com/ryaneshea/status/765575388735082496", - "service": "twitter", - "@type": "Account" - }, - { - "identifier": "shea256", - "proofType": "http", - "proofUrl": "https://gist.github.com/shea256/a6dc1f3182f28bb2285feaef07a14340", - "service": "github", - "@type": "Account" - }, - { - "identifier": "ryaneshea", - "proofType": "http", - "proofUrl": "https://www.facebook.com/ryaneshea/posts/10154182997407713", - "service": "facebook", - "@type": "Account" - } - ], - "name": "Ryan Shea" - }, - "expiresAt": "2017-12-21T02:20:24.575047", - "subject": { - "publicKey": "0312ccf3255cb005e42c186aa3d2302083b306a52c1f0cb47b1119639f134e6695" - }, - "issuer": { - "publicKey": "0312ccf3255cb005e42c186aa3d2302083b306a52c1f0cb47b1119639f134e6695" - } - }, - "signature": "YVoNsoJCTMcXIwqa9D5kinkUrnyppsYus7Z-8cn7o9hA6_IG9zkoZGSvsIzfqqjG1mV8JNV1Nh04CZl1qrt1YQ" - }, - "token": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJpc3N1ZWRBdCI6IjIwMTYtMTItMjFUMDI6MjA6MjQuNTc1MDQ3IiwiY2xhaW0iOnsiaW1hZ2UiOlt7ImNvbnRlbnRVcmwiOiJodHRwczovL3MzLmFtYXpvbmF3cy5jb20va2Q0L3J5YW4iLCJuYW1lIjoiYXZhdGFyIiwiQHR5cGUiOiJJbWFnZU9iamVjdCJ9LHsiY29udGVudFVybCI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9keDMvcnlhbiIsIm5hbWUiOiJjb3ZlciIsIkB0eXBlIjoiSW1hZ2VPYmplY3QifV0sIkB0eXBlIjoiUGVyc29uIiwid2Vic2l0ZSI6W3sidXJsIjoiaHR0cDovL3NoZWEuaW8iLCJAdHlwZSI6IldlYlNpdGUifV0sImFjY291bnQiOlt7ImlkZW50aWZpZXIiOiIxTEZTMzd5UlNpYndiZjhDblhlQ241dDFHS2VURVpNbXU5Iiwicm9sZSI6InBheW1lbnQiLCJAdHlwZSI6IkFjY291bnQiLCJzZXJ2aWNlIjoiYml0Y29pbiJ9LHsiY29udGVudFVybCI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9wazkvcnlhbiIsImlkZW50aWZpZXIiOiIxRTQzMjlFNjYzNEM3NTczMEQ0RDg4QzA2MzhGMjc2OUQ1NUI5ODM3IiwiQHR5cGUiOiJBY2NvdW50Iiwic2VydmljZSI6InBncCJ9LHsicHJvb2ZUeXBlIjoiaHR0cCIsImlkZW50aWZpZXIiOiJmMjI1MDEyM2E2YWYxMzhjODZiMzBmMzIzM2IzMzg5NjFkYzhmYmMzIiwicHJvb2ZVcmwiOiJodHRwczovL3d3dy5mYWNlYm9vay5jb20vbXNyb2JvdDAvcG9zdHMvMTAxNTM2NDQ0NDY0NTI3NTkiLCJzZXJ2aWNlIjoib3BlbmJhemFhciIsIkB0eXBlIjoiQWNjb3VudCJ9LHsicHJvb2ZUeXBlIjoiaHR0cCIsImlkZW50aWZpZXIiOiJyeWFuZXNoZWEiLCJwcm9vZlVybCI6Imh0dHBzOi8vdHdpdHRlci5jb20vcnlhbmVzaGVhL3N0YXR1cy83NjU1NzUzODg3MzUwODI0OTYiLCJzZXJ2aWNlIjoidHdpdHRlciIsIkB0eXBlIjoiQWNjb3VudCJ9LHsicHJvb2ZUeXBlIjoiaHR0cCIsImlkZW50aWZpZXIiOiJzaGVhMjU2IiwicHJvb2ZVcmwiOiJodHRwczovL2dpc3QuZ2l0aHViLmNvbS9zaGVhMjU2L2E2ZGMxZjMxODJmMjhiYjIyODVmZWFlZjA3YTE0MzQwIiwic2VydmljZSI6ImdpdGh1YiIsIkB0eXBlIjoiQWNjb3VudCJ9LHsicHJvb2ZUeXBlIjoiaHR0cCIsImlkZW50aWZpZXIiOiJyeWFuZXNoZWEiLCJwcm9vZlVybCI6Imh0dHBzOi8vd3d3LmZhY2Vib29rLmNvbS9yeWFuZXNoZWEvcG9zdHMvMTAxNTQxODI5OTc0MDc3MTMiLCJzZXJ2aWNlIjoiZmFjZWJvb2siLCJAdHlwZSI6IkFjY291bnQifV0sImFkZHJlc3MiOnsiYWRkcmVzc0xvY2FsaXR5IjoiTmV3IFlvcmsiLCJAdHlwZSI6IlBvc3RhbEFkZHJlc3MifSwiZGVzY3JpcHRpb24iOiJDby1mb3VuZGVyIG9mIEJsb2Nrc3RhY2sgSW5jLiIsIm5hbWUiOiJSeWFuIFNoZWEifSwiZXhwaXJlc0F0IjoiMjAxNy0xMi0yMVQwMjoyMDoyNC41NzUwNDciLCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDMxMmNjZjMyNTVjYjAwNWU0MmMxODZhYTNkMjMwMjA4M2IzMDZhNTJjMWYwY2I0N2IxMTE5NjM5ZjEzNGU2Njk1In0sInN1YmplY3QiOnsicHVibGljS2V5IjoiMDMxMmNjZjMyNTVjYjAwNWU0MmMxODZhYTNkMjMwMjA4M2IzMDZhNTJjMWYwY2I0N2IxMTE5NjM5ZjEzNGU2Njk1In19.YVoNsoJCTMcXIwqa9D5kinkUrnyppsYus7Z-8cn7o9hA6_IG9zkoZGSvsIzfqqjG1mV8JNV1Nh04CZl1qrt1YQ", - "parentPublicKey": "0312ccf3255cb005e42c186aa3d2302083b306a52c1f0cb47b1119639f134e6695", - "encrypted": false - } -] \ No newline at end of file diff --git a/docs/token-files/ryan_apr20.json b/docs/token-files/ryan_apr20.json deleted file mode 100644 index 22609400..00000000 --- a/docs/token-files/ryan_apr20.json +++ /dev/null @@ -1,43 +0,0 @@ -[ - { - "decodedToken": { - "header": { - "alg": "ES256K", - "typ": "JWT" - }, - "payload": { - "issuedAt": "2016-04-20T12:25:14.453734", - "claim": { - "account": [], - "accounts": [], - "@type": "Person", - "image": [ - { - "contentUrl": "https://s3.amazonaws.com/97p/rv1.jpeg", - "@type": "ImageObject", - "name": "cover" - }, - { - "contentUrl": "https://s3.amazonaws.com/kd4/ryan_apr20", - "@type": "ImageObject", - "name": "avatar" - } - ], - "name": "Ryan Shea" - }, - "expiresAt": "2017-04-20T12:25:14.453734", - "subject": { - "publicKey": "02413d7c51118104cfe1b41e540b6c2acaaf91f1e2e22316df7448fb6070d582ec" - }, - "issuer": { - "publicKey": "02413d7c51118104cfe1b41e540b6c2acaaf91f1e2e22316df7448fb6070d582ec" - } - }, - "signature": "Xj3z975ccW6oxbrlm_YsdGNreuzERRxPoj0DyyJ9vygMYfUjsTQGcxsejmkSPYafTFd6TNIbNBTquutOKZvmBA" - }, - "token": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJpc3N1ZWRBdCI6IjIwMTYtMDQtMjBUMTI6MjU6MTQuNDUzNzM0IiwiY2xhaW0iOnsiYWNjb3VudCI6W10sImFjY291bnRzIjpbXSwiQHR5cGUiOiJQZXJzb24iLCJpbWFnZSI6W3siY29udGVudFVybCI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS85N3AvcnYxLmpwZWciLCJAdHlwZSI6IkltYWdlT2JqZWN0IiwibmFtZSI6ImNvdmVyIn0seyJjb250ZW50VXJsIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL2tkNC9yeWFuX2FwcjIwIiwiQHR5cGUiOiJJbWFnZU9iamVjdCIsIm5hbWUiOiJhdmF0YXIifV0sIm5hbWUiOiJSeWFuIFNoZWEifSwiZXhwaXJlc0F0IjoiMjAxNy0wNC0yMFQxMjoyNToxNC40NTM3MzQiLCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDI0MTNkN2M1MTExODEwNGNmZTFiNDFlNTQwYjZjMmFjYWFmOTFmMWUyZTIyMzE2ZGY3NDQ4ZmI2MDcwZDU4MmVjIn0sInN1YmplY3QiOnsicHVibGljS2V5IjoiMDI0MTNkN2M1MTExODEwNGNmZTFiNDFlNTQwYjZjMmFjYWFmOTFmMWUyZTIyMzE2ZGY3NDQ4ZmI2MDcwZDU4MmVjIn19.Xj3z975ccW6oxbrlm_YsdGNreuzERRxPoj0DyyJ9vygMYfUjsTQGcxsejmkSPYafTFd6TNIbNBTquutOKZvmBA", - "parentPublicKey": "02413d7c51118104cfe1b41e540b6c2acaaf91f1e2e22316df7448fb6070d582ec", - "publicKey": "02413d7c51118104cfe1b41e540b6c2acaaf91f1e2e22316df7448fb6070d582ec", - "encrypted": false - } -] \ No newline at end of file diff --git a/package-auth.json b/package-auth.json deleted file mode 100644 index caef9ac4..00000000 --- a/package-auth.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "blockstack-auth", - "version": "0.2.6", - "description": "Blockstack Auth Library", - "main": "lib/index", - "scripts": { - "compile": "babel --presets es2015 src -d lib", - "test": "npm run compile; node lib/test/unitTests.js", - "prepublish": "npm run compile", - "browserify-test": "npm run compile; node lib/test/browserifyTests.js", - "browserify-app": "npm run compile; browserify lib/test/browserifyApp.js -o lib/test/bundle.js", - "release": "npm version patch && npm publish" - }, - "repository": { - "type": "git", - "url": "https://github.com/blockstack/blockstack-auth-js.git" - }, - "keywords": [ - "blockchain", - "id", - "auth", - "authentication", - "bitcoin", - "blockchain auth", - "blockchain authentication", - "blockchainid", - "blockchain id", - "bitcoin auth", - "bitcoin authentication", - "bitcoin login", - "blockchain login", - "authorization", - "login", - "signin", - "sso", - "crypto", - "cryptography", - "token", - "blockstack", - "blockstack auth" - ], - "author": { - "name": "Blockstack Inc.", - "email": "admin@blockstack.com", - "url": "https://blockstack.com" - }, - "license": "MIT", - "bugs": { - "url": "https://github.com/blockstack/blockstack-auth-js/issues" - }, - "homepage": "https://github.com/blockstack/blockstack-auth-js#readme", - "dependencies": { - "base64url": "^1.0.4", - "elliptic": "^5.1.0", - "elliptic-curve": "^0.1.0", - "hasprop": "0.0.3", - "jsontokens": "^0.6.5", - "key-encoder": "^1.1.3", - "keychain-manager": "^1.1.2", - "node-uuid": "^1.4.3", - "promise": "^7.0.4", - "query-string": "^4.2.3", - "request": "^2.79.0" - }, - "devDependencies": { - "babel-cli": "^6.14.0", - "babel-preset-es2015": "^6.14.0", - "browserify": "^13.1.1", - "onename-api": "^1.0.1", - "phantomjs-prebuilt": "^2.1.13", - "tape": "^4.2.0", - "tape-run": "^2.1.4" - } -} diff --git a/package.json b/package.json index 5caff001..65908e4b 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "elliptic-curve": "^0.1.0", "hasprop": "0.0.4", "isomorphic-fetch": "^2.2.1", - "jsontokens": "^0.6.2", + "jsontokens": "^0.7.3", "key-encoder": "^1.1.6", "promise": "^7.1.1", "query-string": "^4.3.2", diff --git a/src/auth.js b/src/auth.js new file mode 100644 index 00000000..1d673888 --- /dev/null +++ b/src/auth.js @@ -0,0 +1,142 @@ +'use strict' + +import queryString from 'query-string' +import base64url from 'base64url' +import request from 'request' +import { TokenSigner, decodeToken, createUnsecuredToken } from 'jsontokens' +import { secp256k1 } from 'elliptic-curve' +import { makeUUID4, nextMonth, nextHour } from './utils' +import { makeDIDFromPublicKey, makeDIDFromAddress } from './decentralizedIDs' + +export function makeAuthRequest(privateKey, + appManifest, + scopes=[], + expiresAt=nextHour()) { + let token = null + + /* Create the payload */ + let payload = { + jti: makeUUID4(), + iat: new Date().getTime(), + exp: nextHour(), + iss: null, + manifest: appManifest, + scopes: scopes + } + + if (privateKey === null) { + /* Create an unsecured token and return it */ + token = createUnsecuredToken(payload) + } else { + /* Convert the private key to a public key to an issuer */ + const publicKey = secp256k1.getPublicKey(privateKey) + const issuer = makeDIDFromPublicKey(publicKey) + payload.iss = issuer + /* Sign and return the token */ + const tokenSigner = new TokenSigner('ES256k', privateKey) + token = tokenSigner.sign(payload) + } + + return token +} + +export function verifyAuthRequest(token) { + const decodedToken = decodeToken(token) + const payload = decodedToken.payload + + const publicKey = payload.iss + const tokenVerifier = new TokenVerifier('ES256k', publicKey) + const verified = tokenVerifier.verify(token) + + return false +} + +export function makeAuthResponse(privateKey, + profile={}, + username=null, + expiresAt=nextMonth()) { + /* Convert the private key to a public key to an issuer */ + const publicKey = secp256k1.getPublicKey(privateKey) + const issuer = makeDIDFromPublicKey(publicKey) + /* Create the payload */ + const payload = { + jti: makeUUID4(), + iat: new Date().getTime(), + exp: nextMonth(), + iss: issuer, + profile: profile, + username: username + } + /* Sign and return the token */ + const tokenSigner = new TokenSigner('ES256k', privateKey) + return tokenSigner.sign(payload) +} + +const BLOCKSTACK_HANDLER = "web+blockstack" + +export class Authenticator { + constructor(currentHostURL=window.location.origin) { + this.storageLabel = 'blockstack' + this.currentHost = currentHostURL + this.signingKey = null + + this.identityProviderURL = "http://localhost:8888/auth" + } + + isUserLoggedIn() { + return window.localStorage.getItem(this.storageLabel) ? true : false + } + + requestLogin() { + const authRequest = makeAuthRequest(this.signingKey, this.currentHost) + + setTimeout(function() { + window.location = this.identityProviderURL + "?authRequest=" + authRequest + }, 200) + + window.location = BLOCKSTACK_HANDLER + ":" + authRequest + } + + getAuthResponseToken() { + const queryDict = queryString.parse(location.search) + return queryDict.authResponse + } + + isLoginPending() { + return this.getAuthResponseToken() ? true : false + } + + completeLogin(callbackFunction) { + const authResponseToken = this.getAuthResponseToken() + const decodedToken = decodeToken(authResponseToken) + const username = decodedToken.payload.username + const profile = decodedToken.payload.profile + + const session = { + username: username, + profile: profile, + authResponseToken: authResponseToken + } + window.localStorage.setItem(this.storageLabel, JSON.stringify(session)) + callbackFunction(session) + } + + loadSession(callbackFunction) { + const session = JSON.parse(localStorage.getItem(this.storageLabel)) + callbackFunction(session) + } + + logout() { + window.localStorage.removeItem(this.storageLabel) + window.location = this.currentHost + } +} + +/* + request(requestURL, (error, response, body) => { + if (!error && response.statusCode == 200) { + const profile = JSON.parse(body)[username].profile + + } + }) +*/ \ No newline at end of file diff --git a/src/authAgent.js b/src/authAgent.js deleted file mode 100644 index b47d955f..00000000 --- a/src/authAgent.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict' - -import queryString from 'query-string' -import base64url from 'base64url' -import request from 'request' -import { decodeToken } from 'jsontokens' - -export class AuthAgent { - constructor(identityProviderURL, nameResolverURL, - currentHostURL=window.location.origin) { - this.storageLabel = 'blockstack' - this.identityProviderURL = identityProviderURL - this.nameResolverURL = nameResolverURL - this.currentHost = currentHostURL - } - - static getUsernameFromToken(authResponseToken) { - var decodedToken = decodeToken(authResponseToken) - var decodedBlockstackID = decodedToken.payload.issuer.username - return decodedBlockstackID.split('.')[0] - } - - isUserLoggedIn() { - return window.localStorage.getItem(this.storageLabel) ? true : false - } - - requestLogin() { - const payload = { - appURI: this.currentHost, - issuedAt: new Date().getTime() - } - const authRequest = base64url.encode(JSON.stringify(payload)) - - setTimeout(function() { - window.location = this.identityProviderURL + "?authRequest=" + authRequest - }, 200) - - window.location = "web+blockstack:" + authRequest - } - - getAuthResponseToken() { - const queryDict = queryString.parse(location.search) - return queryDict.authResponse - } - - isLoginPending() { - return this.getAuthResponseToken() ? true : false - } - - completeLogin(callbackFunction) { - const authResponseToken = this.getAuthResponseToken() - const username = AuthAgent.getUsernameFromToken(authResponseToken) - const requestURL = this.nameResolverURL + username - request(requestURL, (error, response, body) => { - if (!error && response.statusCode == 200) { - const profile = JSON.parse(body)[username].profile - const session = { - username: username, - profile: profile, - authResponseToken: authResponseToken - } - window.localStorage.setItem(this.storageLabel, JSON.stringify(session)) - callbackFunction(session) - } - }) - } - - loadSession(callbackFunction) { - const session = JSON.parse(localStorage.getItem(this.storageLabel)) - callbackFunction(session) - } - - logout() { - window.localStorage.removeItem(this.storageLabel) - window.location = this.currentHost - } -} \ No newline at end of file diff --git a/src/authRequest.js b/src/authRequest.js deleted file mode 100644 index 70c9082a..00000000 --- a/src/authRequest.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' - -import KeyEncoder from 'key-encoder' -import { TokenSigner, decodeToken, createUnsignedToken } from 'jsontokens' -import { secp256k1 } from 'elliptic-curve' -import base64url from 'base64url' -import { generateUUID4 } from './utils' - -export function createRequestPayload(issuer, provisions=null) { - let unsignedRequest = { - issuer: issuer, - issuedAt: new Date().getTime() - } - if (provisions) { - unsignedRequest.provisions = provisions - } - return unsignedRequest -} - -export function createUnsignedRequest(issuer) { - const header = { typ: 'JWT' } - const payload = createRequestPayload(issuer) - const unsignedToken = createUnsignedToken(header, payload) + '.0' - return unsignedToken -} - -export class AuthRequest { - constructor(privateKey) { - this.privateKey = privateKey - this.keyEncoder = new KeyEncoder('secp256k1') - this.publicKey = secp256k1.getPublicKey(privateKey) - this.tokenSigner = new TokenSigner('ES256k', privateKey) - this.issuer = { publicKey: this.publicKey } - this.provisions = [ - { action: 'sign', data: generateUUID4() }, - { action: 'disclose', scope: 'username' } - ] - } - - setIssuer(issuer) { - const newIssuer = this.issuer - for (let attrname in issuer) { - newIssuer[attrname] = issuer[attrname] - } - this.issuer = newIssuer - } - - setProvisions(provisions) { - this.provisions = provisions - } - - payload() { - return { - issuer: this.issuer, - issuedAt: new Date().getTime(), - provisions: this.provisions - } - } - - sign() { - return this.tokenSigner.sign(this.payload()) - } -} diff --git a/src/authResponse.js b/src/authResponse.js deleted file mode 100644 index 4391fadd..00000000 --- a/src/authResponse.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict' - -import KeyEncoder from 'key-encoder' -import { TokenSigner, decodeToken } from 'jsontokens' -import { secp256k1 } from 'elliptic-curve' - -export class AuthResponse { - constructor(privateKey) { - this.privateKey = privateKey - this.keyEncoder = new KeyEncoder('secp256k1') - this.publicKey = secp256k1.getPublicKey(privateKey) - this.tokenSigner = new TokenSigner('ES256k', privateKey) - this.issuer = { publicKey: this.publicKey } - } - - satisfyProvisions(provisions, username, privateData) { - provisions.forEach((provision) => { - switch(provision.action) { - case 'disclose': - if (provision.scope === 'username' && username) { - provision.data = username - } - break; - case 'sign': - if (provision.data) { - const signature = secp256k1.signMessage( - provision.data, this.privateKey) - provision.signature = signature - } - break; - case 'write': - break; - default: - break; - } - }) - - this.provisions = provisions - } - - setIssuer(username, publicKeychain, chainPath) { - if (username && publicKeychain && chainPath) { - this.issuer = { - publicKey: this.publicKey, - username: username, - publicKeychain: publicKeychain, - chainPath: chainPath - } - } else if (username) { - this.issuer = { - publicKey: this.publicKey, - username: username - } - } else if (username || publicKeychain || chainPath) { - throw 'Either all or none of the following must be provided: username, publicKeychain, chainPath' - } else { - throw 'Cannot set issuer without the following: username, publicKeychain, chainPath' - } - } - - payload() { - return { - issuer: this.issuer, - issuedAt: new Date().getTime(), - provisions: this.provisions - } - } - - sign() { - return this.tokenSigner.sign(this.payload()) - } -} diff --git a/src/decentralizedIDs.js b/src/decentralizedIDs.js new file mode 100644 index 00000000..f0993321 --- /dev/null +++ b/src/decentralizedIDs.js @@ -0,0 +1,29 @@ +'use strict' + +export function makeDIDFromPublicKey(publicKey) { + return `did:ecdsa-pub:${publicKey}` +} + +export function makeDIDFromAddress(address) { + return `did:btc-addr:${address}` +} + +export function getPublicKeyOrAddressFromDID(did) { + const didParts = did.split(':') + + if (didParts.length !== 3) { + throw new InvalidDIDError('Decentralized IDs must have 3 parts') + } + + if (didParts[0].toLowerCase() !== 'did') { + throw new InvalidDIDError('Decentralized IDs must start with "did"') + } + + if (didParts[1].toLowerCase() === 'ecdsa-pub') { + return didParts[2] + } else if (didParts[1].toLowerCase() === 'btc-addr') { + return didParts[2] + } else { + throw new InvalidDIDError('Decentralized ID format not supported') + } +} \ No newline at end of file diff --git a/src/errors.js b/src/errors.js new file mode 100644 index 00000000..7f571bff --- /dev/null +++ b/src/errors.js @@ -0,0 +1,9 @@ +'use strict' + +export class InvalidDIDError extends Error { + constructor(message) { + super() + this.name = 'InvalidDIDError' + this.message = (message || '') + } +} \ No newline at end of file diff --git a/src/index.es6 b/src/index.es6 index 6b2f536b..cb8cfd6c 100644 --- a/src/index.es6 +++ b/src/index.es6 @@ -1,9 +1,37 @@ 'use strict' +export { + makeAuthRequest, + makeAuthResponse, + Authenticator +} from './auth' + +export { + makeDIDFromPublicKey, + makeDIDFromAddress, + getPublicKeyOrAddressFromDID +} from './decentralizedIDs' + +export { + privateKeyToPublicKey +} from './keyUtils' + export { Profile } from './profile' +export { + validateProofs +} from './profileProofs' + +export { + Person, + Organization, + CreativeWork, + getPersonFromLegacyFormat, + resolveZoneFileToPerson +} from './profileSchemas' + export { signProfileToken, wrapProfileToken, @@ -12,20 +40,16 @@ export { } from './profileTokens' export { - Person, - Organization, - CreativeWork, - resolveZoneFileToPerson -} from './profileSchemas' - -export { - validateProofs, + services, containsValidProofStatement -} from './profileProofs' +} from './services' export { + nextYear, + nextMonth, + nextHour, getEntropy, - privateKeyToPublicKey + makeUUID4 } from './utils' export { @@ -33,12 +57,3 @@ export { getTokenFileUrlFromZoneFile } from './zoneFiles' -export { - AuthAgent -} from './authAgent' -export { - AuthRequest -} from './authRequest' -export { - AuthResponse -} from './authResponse' diff --git a/src/keyUtils.js b/src/keyUtils.js new file mode 100644 index 00000000..5778ad01 --- /dev/null +++ b/src/keyUtils.js @@ -0,0 +1,12 @@ +'use strict' + +import BigInteger from 'bigi' +import { ECPair as ECKeyPair } from 'bitcoinjs-lib' + +export function privateKeyToPublicKey(privateKey) { + const privateKeyBuffer = new Buffer(privateKey, 'hex') + const privateKeyBigInteger = BigInteger.fromBuffer(privateKeyBuffer) + const keyPair = new ECKeyPair(privateKeyBigInteger, null, {}) + const publicKey = keyPair.getPublicKeyBuffer().toString('hex') + return publicKey +} \ No newline at end of file diff --git a/src/profileTokens.es6 b/src/profileTokens.es6 index 7b848662..9a85cbcc 100644 --- a/src/profileTokens.es6 +++ b/src/profileTokens.es6 @@ -4,7 +4,8 @@ import ecurve from 'ecurve' import { ECPair as ECKeyPair } from 'bitcoinjs-lib' import { decodeToken, TokenSigner, TokenVerifier } from 'jsontokens' import BigInteger from 'bigi' -import { nextYear, privateKeyToPublicKey, generateUUID4 } from './utils' +import { nextYear, makeUUID4 } from './utils' +import { privateKeyToPublicKey } from './keyUtils' const secp256k1 = ecurve.getCurveByName('secp256k1') @@ -38,7 +39,7 @@ export function signProfileToken(profile, privateKey, subject=null, issuer=null, const tokenSigner = new TokenSigner(signingAlgorithm, privateKey) const payload = { - jti: generateUUID4(), + jti: makeUUID4(), iat: issuedAt.toISOString(), exp: expiresAt.toISOString(), subject: subject, @@ -70,18 +71,25 @@ export function verifyProfileToken(token, publicKeyOrAddress) { const decodedToken = decodeToken(token) const payload = decodedToken.payload - if (!payload.hasOwnProperty('subject')) { + // Inspect and verify the subject + if (payload.hasOwnProperty('subject')) { + if (!payload.subject.hasOwnProperty('publicKey')) { + throw new Error("Token doesn't have a subject public key") + } + } else { throw new Error("Token doesn't have a subject") } - if (!payload.subject.hasOwnProperty('publicKey')) { - throw new Error("Token doesn't have a subject public key") - } - if (!payload.hasOwnProperty('issuer')) { + + // Inspect and verify the issuer + if (payload.hasOwnProperty('issuer')) { + if (!payload.issuer.hasOwnProperty('publicKey')) { + throw new Error("Token doesn't have an issuer public key") + } + } else { throw new Error("Token doesn't have an issuer") } - if (!payload.issuer.hasOwnProperty('publicKey')) { - throw new Error("Token doesn't have an issuer public key") - } + + // Inspect and verify the claim if (!payload.hasOwnProperty('claim')) { throw new Error("Token doesn't have a claim") } diff --git a/src/testing/authUnitTests.es6 b/src/testing/authUnitTests.es6 index 04a01abc..1c0ca277 100644 --- a/src/testing/authUnitTests.es6 +++ b/src/testing/authUnitTests.es6 @@ -1,234 +1,68 @@ 'use strict' import test from 'tape' +import { decodeToken } from 'jsontokens' import { - AuthMessage, AuthRequest, AuthResponse, createUnsignedRequest, - verifyAuthMessage, decodeToken, AuthAgent + makeAuthRequest, makeAuthResponse, makeDIDFromPublicKey } from '../index' -import { OnenameClient } from 'onename-api' - -let onenameResolver = new OnenameClient( - process.env.ONENAME_APP_ID, process.env.ONENAME_APP_SECRET) - -function testBlockstackResolver(blockstackIDs, resolve, reject) { - if (blockstackIDs[0] === 'todo.app') { - resolve({ - "todo.app": { - "profile": { - "auth": [ - { - "publicKey": "027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69" - } - ] - } - } - }) - } else if (blockstackIDs[0] === 'ryan.id') { - resolve({ - "ryan.id": { - "profile": { - "auth": [ - { - "publicKeychain": "xpub661MyMwAqRbcFQVrQr4Q4kPjaP4JjWaf39fBVKjPdK6oGBayE46GAmKzo5UDPQdLSM9DufZiP8eauy56XNuHicBySvZp7J5wsyQVpi2axzZ" - } - ] - } - } - }) - } else { - resolve(null) - } -} - -function testAuthRequest() { - const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' - const publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69' - - const sampleToken = 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3N1ZWRBdCI6IjE0NDA3MTM0MTQuMTkiLCJjaGFsbGVuZ2UiOiIxZDc4NTBkNy01YmNmLTQ3ZDAtYTgxYy1jMDA4NTc5NzY1NDQiLCJwZXJtaXNzaW9ucyI6WyJibG9ja2NoYWluaWQiXSwiaXNzdWVyIjp7InB1YmxpY0tleSI6IjAzODI3YjZhMzRjZWJlZTZkYjEwZDEzNzg3ODQ2ZGVlYWMxMDIzYWNiODNhN2I4NjZlMTkyZmEzNmI5MTkwNjNlNCIsImRvbWFpbiI6Im9uZW5hbWUuY29tIn19.96Q_O_4DX8uPy1enosEwS2sIcyVelWhxvfj2F8rOvHldhqt9YRYilauepb95DVnmpqpCXxJb7jurT8auNCbptw' - const sampleTokenPayload = {"issuedAt": "1440713414.19", "challenge": "1d7850d7-5bcf-47d0-a81c-c00857976544", "permissions": ["blockchainid"], "issuer": {"publicKey": "03827b6a34cebee6db10d13787846deeac1023acb83a7b866e192fa36b919063e4", "domain": "onename.com"}} - - test('basicRequest', (t) => { - t.plan(4) - - const issuingBlockchainID = 'todo.app' - - let authRequest = new AuthRequest(privateKey) - - authRequest.setIssuer({ - username: issuingBlockchainID - }) - - const authRequestToken = authRequest.sign() - const decodedAuthRequestToken = decodeToken(authRequestToken) - - t.ok(authRequest instanceof AuthRequest, 'authRequest should be a valid AuthMessage object') - t.equal(typeof authRequestToken, 'string', 'token should be a string') - t.equal(decodedAuthRequestToken.payload.issuer.username, issuingBlockchainID, 'token blockchain id should match the reference') - - verifyAuthMessage(authRequestToken, testBlockstackResolver, (verified) => { - t.equal(verified, true, 'token should be verified') - }, function(err) { - console.log(err) - }) - }) - - test('unsignedRequest', (t) => { - t.plan(2) - - const unsignedRequestToken = createUnsignedRequest({ 'app': 'unknown' }) - t.ok(unsignedRequestToken) - console.log(unsignedRequestToken) - - const decodedRequestToken = decodeToken(unsignedRequestToken) - t.ok(decodedRequestToken) - console.log(decodedRequestToken) - }) - - test('advancedRequest', (t) => { - t.plan(4) - - const issuingBlockchainID = 'todo.app' - - let authRequest = new AuthRequest(privateKey) - - authRequest.setIssuer({ - username: issuingBlockchainID, - appName: 'Todo App', - appDomain: 'todo.app' - }) - authRequest.setProvisions([ - { action: 'disclose', scope: 'username' }, - { action: 'write', data: { uuid: '34e57db64ce7435ab0f759oca31386527c670bd1' } } - ]) - - const authRequestToken = authRequest.sign() - const decodedAuthRequestToken = decodeToken(authRequestToken) - - console.log(authRequestToken) - console.log(JSON.stringify(decodedAuthRequestToken, null, 2)) - - t.ok(authRequest instanceof AuthRequest, 'authRequest should be a valid AuthMessage object') - t.equal(typeof authRequestToken, 'string', 'token should be a string') - t.equal(decodedAuthRequestToken.payload.issuer.username, issuingBlockchainID, 'token blockchain id should match the reference') - - verifyAuthMessage(authRequestToken, testBlockstackResolver, function(verified) { - t.equal(verified, true, 'token should be verified') - }, function(err) { - console.log(err) - }) - }) - - test('requestDecoding', (t) => { - t.plan(1) - - const decodedSampleToken = decodeToken(sampleToken) - t.equal(JSON.stringify(decodedSampleToken.payload), JSON.stringify(sampleTokenPayload), 'token payload should match the reference payload') - }) -} - - -function testAuthResponse() { - let privateKeyHex = '278a5de700e29faae8e40e366ec5012b5ec63d36ec77e8a2417154cc1d25383f', - publicKeyHex = '03fdd57adec3d438ea237fe46b33ee1e016eda6b585c3e27ea66686c2ea5358479', - publicKeychain = 'xpub661MyMwAqRbcFQVrQr4Q4kPjaP4JjWaf39fBVKjPdK6oGBayE46GAmKzo5UDPQdLSM9DufZiP8eauy56XNuHicBySvZp7J5wsyQVpi2axzZ', - privateKeychain = 'xprv9s21ZrQH143K2vRPJpXPhcT12MDpL3rofvjagwKn4yZpPPFpgWn1cy1Wwp3pk78wfHSLcdyZhmEBQsZ29ZwFyTQhhkVVa9QgdTC7hGMB1br', - chainPath = 'bd62885ec3f0e3838043115f4ce25eedd22cc86711803fb0c19601eeef185e39', - provisions = [ - { action: 'sign', data: '7cd9ed5e-bb0e-49ea-a323-f28bde3a0549' }, - { action: 'disclose', scope: 'username' } - ], - challengeSignature = "3045022100963da1185591472e1bc867319ddd372593e17758724aaae49a2a30284b399bf0022037022ba279cf20421b96e9cac2a16ab6e415878cda488bc429fbc325f04315af", - username = 'ryan.id', - sampleToken = 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3N1ZWRBdCI6IjE0NDA3MTM0MTQuODUiLCJjaGFsbGVuZ2UiOiI3Y2Q5ZWQ1ZS1iYjBlLTQ5ZWEtYTMyMy1mMjhiZGUzYTA1NDkiLCJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDNmZGQ1N2FkZWMzZDQzOGVhMjM3ZmU0NmIzM2VlMWUwMTZlZGE2YjU4NWMzZTI3ZWE2NjY4NmMyZWE1MzU4NDc5IiwiY2hhaW5QYXRoIjoiYmQ2Mjg4NWVjM2YwZTM4MzgwNDMxMTVmNGNlMjVlZWRkMjJjYzg2NzExODAzZmIwYzE5NjAxZWVlZjE4NWUzOSIsInB1YmxpY0tleWNoYWluIjoieHB1YjY2MU15TXdBcVJiY0ZRVnJRcjRRNGtQamFQNEpqV2FmMzlmQlZLalBkSzZvR0JheUU0NkdBbUt6bzVVRFBRZExTTTlEdWZaaVA4ZWF1eTU2WE51SGljQnlTdlpwN0o1d3N5UVZwaTJheHpaIiwiYmxvY2tjaGFpbmlkIjoicnlhbiJ9fQ.oO7ROPKq3T3X0azAXzHsf6ub6CYy5nUUFDoy8MS22B3TlYisqsBrRtzWIQcSYiFXLytrXwAdt6vjehj3OFioDQ', - sampleTokenPayload = {"issuedAt": "1440713414.85", "challenge": "7cd9ed5e-bb0e-49ea-a323-f28bde3a0549", "issuer": {"publicKey": "03fdd57adec3d438ea237fe46b33ee1e016eda6b585c3e27ea66686c2ea5358479", "chainPath": "bd62885ec3f0e3838043115f4ce25eedd22cc86711803fb0c19601eeef185e39", "publicKeychain": "xpub661MyMwAqRbcFQVrQr4Q4kPjaP4JjWaf39fBVKjPdK6oGBayE46GAmKzo5UDPQdLSM9DufZiP8eauy56XNuHicBySvZp7J5wsyQVpi2axzZ", "blockchainid": "ryan"}}, - partiallyIdentifiedToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJpc3N1ZXIiOnsicHVibGljS2V5IjoiMDNmZGQ1N2FkZWMzZDQzOGVhMjM3ZmU0NmIzM2VlMWUwMTZlZGE2YjU4NWMzZTI3ZWE2NjY4NmMyZWE1MzU4NDc5IiwiYmxvY2tjaGFpbmlkIjoicnlhbiIsInB1YmxpY0tleWNoYWluIjoieHB1YjY2MU15TXdBcVJiY0ZRVnJRcjRRNGtQamFQNEpqV2FmMzlmQlZLalBkSzZvR0JheUU0NkdBbUt6bzVVRFBRZExTTTlEdWZaaVA4ZWF1eTU2WE51SGljQnlTdlpwN0o1d3N5UVZwaTJheHpaIn0sImlzc3VlZEF0IjoxNDQxNzU1NjE5MDk2LCJjaGFsbGVuZ2UiOiI3Y2Q5ZWQ1ZS1iYjBlLTQ5ZWEtYTMyMy1mMjhiZGUzYTA1NDkiLCJpYXQiOjE0NDE3NTU2MTl9.1LxW_yg2z40Qd84x0kep0-7TWiDdTEoJbdYFUJ3qt297zxbwo8OOvYW43W6TMT5cloxur5wifq0WoOTdXw4C_Q', - invalidUsername = 'ryanshea.id', - privateData = {} - - test('basicResponse', function(t) { - t.plan(5) - - let authResponse = new AuthResponse(privateKeyHex) - - authResponse.satisfyProvisions(provisions, username, privateData) - authResponse.setIssuer(username, publicKeychain, chainPath) - - const authResponseToken = authResponse.sign() - const decodedAuthResponseToken = decodeToken(authResponseToken) - - console.log(JSON.stringify(decodedAuthResponseToken, null, 2)) - - t.ok(authResponse instanceof AuthResponse, 'authRequest should be a valid AuthResponse object') - t.equal(typeof authResponseToken, 'string', 'token should be a string') - t.equal(decodedAuthResponseToken.payload.issuer.publicKey, publicKeyHex, 'token public key hex should match the reference value') - t.equal(decodedAuthResponseToken.payload.provisions[0].signature, challengeSignature, 'challenge signature should match the reference value') - - verifyAuthMessage(authResponseToken, testBlockstackResolver, function(verified) { - t.equal(verified, true, 'token should be verified') - }, function(err) { - console.log(err) - }) - }) - - test('partiallyIdentifiedResponse', function(t) { - t.plan(1) - - verifyAuthMessage(partiallyIdentifiedToken, testBlockstackResolver, function(verified) { - t.equal(verified, false, 'token should be invalid') - }, function(err) { - console.log(err) - }) - }) - - test('responseWithIncorrectBlockchainID', function(t) { - t.plan(2) - - let authResponse = new AuthResponse(privateKeyHex, publicKeyHex) - - authResponse.satisfyProvisions(provisions, invalidUsername, privateData) - authResponse.setIssuer(invalidUsername, publicKeychain, chainPath) - - const authResponseToken = authResponse.sign() - t.ok(authResponseToken, 'token should have been created') - - verifyAuthMessage(authResponseToken, testBlockstackResolver, function(verified) { - t.equal(verified, false, 'token should be invalid') - }, function(err) { - console.log(err) - }) - }) - - test('anonymousResponse', function(t) { - t.plan(4) - - let authResponse = new AuthResponse(privateKeyHex) - - authResponse.satisfyProvisions(provisions) - - const authResponseToken = authResponse.sign() - const decodedAuthResponseToken = decodeToken(authResponseToken) - - t.ok(authResponse instanceof AuthResponse, 'authRequest should be a valid AuthResponse object') - t.equal(typeof authResponseToken, 'string', 'token should be a string') - t.equal(decodedAuthResponseToken.payload.issuer.publicKey, publicKeyHex, 'token public key hex should match the reference value') - - verifyAuthMessage(authResponseToken, testBlockstackResolver, function(verified) { - t.equal(verified, true, 'token should be verified') - }, function(err) { - console.log(err) - }) - }) - - test('responseDecoding', function(t) { - t.plan(1) - - const decodedSampleToken = decodeToken(sampleToken) - t.equal(JSON.stringify(decodedSampleToken.payload), JSON.stringify(sampleTokenPayload), 'token payload should match the reference payload') - }) -} export function runAuthTests() { - testAuthRequest() - testAuthResponse() + const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' + const publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69' + const appManifest = { + name: "Hello, Blockstack", + short_name: "Hello, Blockstack", + start_url: "https://helloblockstack.com", + display: "standalone", + background_color: "#fff", + description: "A simple app demonstrating how to log in with Blockstack.", + icons: [ + { + src: "https://raw.githubusercontent.com/blockstack/blockstack-portal/master/app/images/app-hello-blockstack.png", + sizes: "192x19x", + type: "image/png" + } + ] + } + const profile = { + "@type": "Person", + name: "Ryan Shea", + description: "Co-founder of Blockstack Inc." + } + + //const sampleToken = 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3N1ZWRBdCI6IjE0NDA3MTM0MTQuMTkiLCJjaGFsbGVuZ2UiOiIxZDc4NTBkNy01YmNmLTQ3ZDAtYTgxYy1jMDA4NTc5NzY1NDQiLCJwZXJtaXNzaW9ucyI6WyJibG9ja2NoYWluaWQiXSwiaXNzdWVyIjp7InB1YmxpY0tleSI6IjAzODI3YjZhMzRjZWJlZTZkYjEwZDEzNzg3ODQ2ZGVlYWMxMDIzYWNiODNhN2I4NjZlMTkyZmEzNmI5MTkwNjNlNCIsImRvbWFpbiI6Im9uZW5hbWUuY29tIn19.96Q_O_4DX8uPy1enosEwS2sIcyVelWhxvfj2F8rOvHldhqt9YRYilauepb95DVnmpqpCXxJb7jurT8auNCbptw' + //const sampleTokenPayload = {"issuedAt": "1440713414.19", "challenge": "1d7850d7-5bcf-47d0-a81c-c00857976544", "permissions": ["blockchainid"], "issuer": {"publicKey": "03827b6a34cebee6db10d13787846deeac1023acb83a7b866e192fa36b919063e4", "domain": "onename.com"}} + + test('makeAuthRequest', (t) => { + t.plan(4) + + const authRequest = makeAuthRequest(privateKey, appManifest) + t.ok(authRequest, 'auth request should have been created') + + const decodedToken = decodeToken(authRequest) + t.ok(decodedToken, 'auth request token should have been decoded') + + const referenceDID = makeDIDFromPublicKey(publicKey) + t.equal(decodedToken.payload.iss, referenceDID, 'auth request issuer should include the public key') + + t.equal(JSON.stringify(decodedToken.payload.scopes), "[]", 'auth request scopes should be an empty list') + }) + + test('makeAuthResponse', (t) => { + t.plan(5) + + const authResponse = makeAuthResponse(privateKey, profile) + t.ok(authResponse, 'auth response should have been created') + + const decodedToken = decodeToken(authResponse) + t.ok(decodedToken, 'auth response should have been decoded') + + const referenceDID = makeDIDFromPublicKey(publicKey) + t.equal(decodedToken.payload.iss, referenceDID, 'auth response issuer should include the public key') + + t.equal(JSON.stringify(decodedToken.payload.profile), JSON.stringify(profile), 'auth response profile should equal the reference value') + + t.equal(decodedToken.payload.username, null, 'auth response username should be null') + }) } \ No newline at end of file diff --git a/src/testing/index.es6 b/src/testing/index.es6 index 46c2ba30..2e585390 100644 --- a/src/testing/index.es6 +++ b/src/testing/index.es6 @@ -2,15 +2,15 @@ import { runProofsUnitTests } from './proofsUnitTests' import { runUtilsUnitTests } from './utilsUnitTests' import { runServicesUnitTests } from './servicesUnitTests' import { runProfilesUnitTests } from './profilesUnitTests' -//import { runAuthTests } from './authUnitTests' +import { runAuthTests } from './authUnitTests' -/* Profiles Tests */ +// Auth Tests +runAuthTests() + +// Profiles Tests runProfilesUnitTests() -/* Proofs Tests */ +// Proofs Tests runUtilsUnitTests() runServicesUnitTests() runProofsUnitTests() - -/* Auth Tests */ -//runAuthTests() \ No newline at end of file diff --git a/src/testing/profilesUnitTests.es6 b/src/testing/profilesUnitTests.es6 index 82eac823..c591fc68 100644 --- a/src/testing/profilesUnitTests.es6 +++ b/src/testing/profilesUnitTests.es6 @@ -17,7 +17,7 @@ import { resolveZoneFileToPerson } from '../index' -import { sampleProfiles, sampleProofs, sampleVerifications, sampleTokenFiles } from './samples' +import { sampleProfiles, sampleProofs, sampleVerifications, sampleTokenFiles } from './sampleData' function testTokening(filename, profile) { const keyPair = new ECPair.makeRandom({ rng: getEntropy }) diff --git a/src/testing/proofsUnitTests.es6 b/src/testing/proofsUnitTests.es6 index ba2dc899..e14ba337 100644 --- a/src/testing/proofsUnitTests.es6 +++ b/src/testing/proofsUnitTests.es6 @@ -2,7 +2,7 @@ import test from 'blue-tape' import fs from 'fs' import FetchMock from 'fetch-mock' import { validateProofs } from '../index' -import { sampleProfiles, sampleProofs, sampleVerifications } from './samples' +import { sampleProfiles, sampleProofs, sampleVerifications } from './sampleData' function testProofs(profile, username, totalProofs) { mockRequests() diff --git a/src/testing/samples.es6 b/src/testing/sampleData.es6 similarity index 100% rename from src/testing/samples.es6 rename to src/testing/sampleData.es6 diff --git a/src/testing/servicesUnitTests.es6 b/src/testing/servicesUnitTests.es6 index e0f52f94..45abed6a 100644 --- a/src/testing/servicesUnitTests.es6 +++ b/src/testing/servicesUnitTests.es6 @@ -4,7 +4,7 @@ import test from 'tape' import { services } from '../services/index' import { Service } from '../services/service' import { Facebook } from '../services/facebook' -import { sampleProofs } from './samples' +import { sampleProofs } from './sampleData' export function runServicesUnitTests() { diff --git a/src/testing/utilsUnitTests.es6 b/src/testing/utilsUnitTests.es6 index 2debeb70..75219f70 100644 --- a/src/testing/utilsUnitTests.es6 +++ b/src/testing/utilsUnitTests.es6 @@ -1,7 +1,7 @@ import test from 'tape' import fs from 'fs' import { containsValidProofStatement } from '../services' -import { sampleVerifications } from './samples' +import { sampleVerifications } from './sampleData' export function runUtilsUnitTests() { test('containsValidProofStatement', (t) => { diff --git a/src/utils.es6 b/src/utils.es6 index 05b2a20b..8497aa5b 100644 --- a/src/utils.es6 +++ b/src/utils.es6 @@ -5,7 +5,27 @@ */ export function nextYear() { - return new Date(new Date().setFullYear(new Date().getFullYear() + 1)) + return new Date( + new Date().setFullYear( + new Date().getFullYear() + 1 + ) + ) +} + +export function nextMonth() { + return new Date( + new Date().setMonth( + new Date().getMonth() + 1 + ) + ) +} + +export function nextHour() { + return new Date( + new Date().setHours( + new Date().getHours() + 1 + ) + ) } /** @@ -21,33 +41,18 @@ export function getEntropy(numberOfBytes) { return randomBytes(numberOfBytes) } -/** - * Elliptic Curve Keys - */ - -import BigInteger from 'bigi' -import { ECPair as ECKeyPair } from 'bitcoinjs-lib' - -export function privateKeyToPublicKey(privateKey) { - const privateKeyBuffer = new Buffer(privateKey, 'hex') - const privateKeyBigInteger = BigInteger.fromBuffer(privateKeyBuffer) - const keyPair = new ECKeyPair(privateKeyBigInteger, null, {}) - const publicKey = keyPair.getPublicKeyBuffer().toString('hex') - return publicKey -} - /** * UUIDs */ -export function generateUUID4 () { - let d = new Date().getTime(); - if (typeof performance !== 'undefined' && typeof performance.now === 'function'){ - d += performance.now(); //use high-precision timer if available - } - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = (d + Math.random() * 16) % 16 | 0; - d = Math.floor(d / 16); - return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); - }); -} \ No newline at end of file +export function makeUUID4() { + let d = new Date().getTime() + if (typeof performance !== 'undefined' && typeof performance.now === 'function') { + d += performance.now(); //use high-precision timer if available + } + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random() * 16) % 16 | 0 + d = Math.floor(d / 16) + return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16) + }) +}