UNPKG

blockstack

Version:

The Blockstack Javascript library for authentication, identity, and storage.

424 lines (321 loc) 18 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.runAuthTests = runAuthTests; var _tape = require('tape-promise/tape'); var _tape2 = _interopRequireDefault(_tape); var _jsontokens = require('jsontokens'); var _fetchMock = require('fetch-mock'); var _fetchMock2 = _interopRequireDefault(_fetchMock); var _lib = require('../../../lib'); var _sampleData = require('./sampleData'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // global.window = {} function runAuthTests() { var privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229'; var publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69'; var nameLookupURL = 'https://core.blockstack.org/v1/names/'; (0, _tape2.default)('makeAuthRequest && verifyAuthRequest', function (t) { t.plan(15); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); var authRequest = blockstack.makeAuthRequest(privateKey); t.ok(authRequest, 'auth request should have been created'); console.log(authRequest); var decodedToken = (0, _jsontokens.decodeToken)(authRequest); t.ok(decodedToken, 'auth request token should have been decoded'); console.log(JSON.stringify(decodedToken, null, 2)); var address = (0, _lib.publicKeyToAddress)(publicKey); var referenceDID = (0, _lib.makeDIDFromAddress)(address); var origin = 'http://localhost:3000'; t.equal(decodedToken.payload.iss, referenceDID, 'auth request issuer should include the public key'); t.equal(decodedToken.payload.domain_name, origin, 'auth request domain_name should be origin'); t.equal(decodedToken.payload.redirect_uri, 'http://localhost:3000', 'auth request redirects to correct uri'); t.equal(decodedToken.payload.manifest_uri, 'http://localhost:3000/manifest.json', 'auth request manifest is correct uri'); t.equal(JSON.stringify(decodedToken.payload.scopes), '["store_write"]', 'auth request scopes should be store_write'); (0, _lib.verifyAuthRequest)(authRequest).then(function (verified) { t.true(verified, 'auth request should be verified'); }); t.true((0, _lib.isExpirationDateValid)(authRequest), 'Expiration date should be valid'); t.true((0, _lib.isIssuanceDateValid)(authRequest), 'Issuance date should be valid'); t.true((0, _lib.doSignaturesMatchPublicKeys)(authRequest), 'Signatures should match the public keys'); t.true((0, _lib.doPublicKeysMatchIssuer)(authRequest), 'Public keys should match the issuer'); t.true((0, _lib.isManifestUriValid)(authRequest), 'Manifest URI should be on the app origin'); t.true((0, _lib.isRedirectUriValid)(authRequest), 'Redirect URL should be to app origin'); var manifiestUrl = 'http://localhost:3000/manifest.json'; var manifest = { name: 'App', start_url: 'http://localhost:3000/', description: 'A simple todo app build on blockstack', icons: [{ src: 'http://localhost:3000/logo.png', sizes: '400x400', type: 'image/png' }] }; var manifestString = JSON.stringify(manifest); _fetchMock2.default.get(manifiestUrl, manifestString); (0, _lib.verifyAuthRequestAndLoadManifest)(authRequest).then(function (appManifest) { console.log(appManifest); t.equal(appManifest.name, 'App', 'should fetch manifest for valid auth request'); }); }); (0, _tape2.default)('make and verify auth request with extraParams', function (t) { t.plan(4); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); var authRequest = blockstack.makeAuthRequest(privateKey, undefined, { myCustomParam: 'asdf' }); t.ok(authRequest, 'auth request should have been created'); var decodedToken = (0, _jsontokens.decodeToken)(authRequest); t.ok(decodedToken, 'auth request token should have been decoded'); t.equal(decodedToken.payload.myCustomParam, 'asdf', 'custom param from extraParams is included in payload'); (0, _lib.verifyAuthRequest)(authRequest).then(function (verified) { t.true(verified, 'auth request should be verified'); }); }); (0, _tape2.default)('invalid auth request - signature not verified', function (t) { t.plan(3); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); var authRequest = blockstack.makeAuthRequest(privateKey); var invalidAuthRequest = authRequest.substring(0, authRequest.length - 1); t.equal((0, _lib.doSignaturesMatchPublicKeys)(invalidAuthRequest), false, 'Signatures should not match the public keys'); (0, _lib.verifyAuthRequest)(invalidAuthRequest).then(function (verified) { t.equal(verified, false, 'auth request should be unverified'); }); (0, _lib.verifyAuthRequestAndLoadManifest)(invalidAuthRequest).then(function () { // no op }, function () { t.pass('invalid auth request rejected'); }); }); (0, _tape2.default)('invalid auth request - invalid redirect uri', function (t) { t.plan(3); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); appConfig.redirectURI = function () { return 'https://example.com'; }; // monkey patch for test var blockstack = new _lib.UserSession({ appConfig: appConfig }); var invalidAuthRequest = blockstack.makeAuthRequest(privateKey); console.log(invalidAuthRequest); t.equal((0, _lib.isRedirectUriValid)(invalidAuthRequest), false, 'Redirect URI should be invalid since it does not match origin'); (0, _lib.verifyAuthRequest)(invalidAuthRequest).then(function (verified) { t.equal(verified, false, 'auth request should be unverified'); }); (0, _lib.verifyAuthRequestAndLoadManifest)(invalidAuthRequest).then(function () { // no op }, function () { t.pass('invalid auth request rejected'); }); }); (0, _tape2.default)('invalid auth request - invalid manifest uri', function (t) { t.plan(2); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); appConfig.manifestURI = function () { return 'https://example.com/manifest.json'; }; // monkey patch for test var blockstack = new _lib.UserSession({ appConfig: appConfig }); var invalidAuthRequest = blockstack.makeAuthRequest(privateKey); t.equal((0, _lib.isManifestUriValid)(invalidAuthRequest), false, 'Manifest URI should be invalid since it does not match origin'); (0, _lib.verifyAuthRequest)(invalidAuthRequest).then(function (verified) { t.equal(verified, false, 'auth request should be unverified'); }); }); (0, _tape2.default)('makeAuthResponse && verifyAuthResponse', function (t) { t.plan(11); var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan); t.ok(authResponse, 'auth response should have been created'); var decodedToken = (0, _jsontokens.decodeToken)(authResponse); t.ok(decodedToken, 'auth response should have been decoded'); // console.log(JSON.stringify(decodedToken, null, 2)) var address = (0, _lib.publicKeyToAddress)(publicKey); var referenceDID = (0, _lib.makeDIDFromAddress)(address); t.equal(decodedToken.payload.iss, referenceDID, 'auth response issuer should include the public key'); t.equal(JSON.stringify(decodedToken.payload.profile), JSON.stringify(_sampleData.sampleProfiles.ryan), 'auth response profile should equal the reference value'); t.equal(decodedToken.payload.username, null, 'auth response username should be null'); // const verified = verifyAuthResponse(authResponse) // t.equal(verified, true, 'auth response should be verified') (0, _lib.verifyAuthResponse)(authResponse, nameLookupURL).then(function (verifiedResult) { t.true(verifiedResult, 'auth response should be verified'); }); t.true((0, _lib.isExpirationDateValid)(authResponse), 'Expiration date should be valid'); t.true((0, _lib.isIssuanceDateValid)(authResponse), 'Issuance date should be valid'); t.true((0, _lib.doSignaturesMatchPublicKeys)(authResponse), 'Signatures should match the public keys'); t.true((0, _lib.doPublicKeysMatchIssuer)(authResponse), 'Public keys should match the issuer'); (0, _lib.doPublicKeysMatchUsername)(authResponse, nameLookupURL).then(function (verifiedResult) { t.true(verifiedResult, 'Public keys should match the username'); }); }); (0, _tape2.default)('auth response with username', function (t) { t.plan(2); var url = nameLookupURL + 'ryan.id'; // console.log(`URL: ${url}`) _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id'); // console.log(decodeToken(authResponse)) (0, _lib.doPublicKeysMatchUsername)(authResponse, nameLookupURL).then(function (verified) { t.true(verified, 'Public keys should match the username'); }); (0, _lib.verifyAuthResponse)(authResponse, nameLookupURL).then(function (verifiedResult) { t.true(verifiedResult, 'auth response should be verified'); }); }); (0, _tape2.default)('auth response with invalid private key', function (t) { t.plan(2); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); var url = nameLookupURL + 'ryan.id'; // console.log(`URL: ${url}`) _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var appPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPublicKey = (0, _lib.getPublicKeyFromPrivate)(transitPrivateKey); var badTransitPrivateKey = (0, _lib.makeECPrivateKey)(); blockstack.store.getSessionData().transitKey = badTransitPrivateKey; var metadata = {}; var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id', metadata, undefined, appPrivateKey, undefined, transitPublicKey); blockstack.handlePendingSignIn(authResponse).then(function () { t.fail('Should have failed to decrypt auth response'); }).catch(function (err) { console.log(err); t.pass('Should fail to decrypt auth response'); }).then(function () { blockstack.store.getSessionData().transitKey = transitPrivateKey; return blockstack.handlePendingSignIn(authResponse); }).then(function () { t.pass('Should correctly sign in with correct transit key'); }).catch(function (err) { console.log(err.stack); t.fail('Should not error'); }); }); (0, _tape2.default)('handlePendingSignIn with authResponseToken', function (t) { t.plan(1); var url = nameLookupURL + 'ryan.id'; _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var appPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPublicKey = (0, _lib.getPublicKeyFromPrivate)(transitPrivateKey); var metadata = {}; var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); blockstack.store.getSessionData().transitKey = transitPrivateKey; var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id', metadata, undefined, appPrivateKey, undefined, transitPublicKey); blockstack.handlePendingSignIn(authResponse).then(function () { t.pass('Should correctly sign in with auth response'); }).catch(function (err) { console.log(err.stack); t.fail('Should not error'); }); }); (0, _tape2.default)('handlePendingSignIn 2', function (t) { t.plan(1); var url = nameLookupURL + 'ryan.id'; _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var appPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPublicKey = (0, _lib.getPublicKeyFromPrivate)(transitPrivateKey); var metadata = {}; var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id', metadata, undefined, appPrivateKey, undefined, transitPublicKey); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); blockstack.store.getSessionData().transitKey = transitPrivateKey; blockstack.handlePendingSignIn(authResponse).then(function () { t.pass('Should correctly sign in with auth response'); }).catch(function (err) { console.log(err.stack); t.fail('Should not error'); }); }); (0, _tape2.default)('app config defaults app domain to origin', function (t) { t.plan(5); global.window = { location: { origin: 'https://example.com' } }; var appConfig = new _lib.AppConfig(); t.equal(appConfig.appDomain, 'https://example.com'); t.equal(appConfig.scopes.length, 1); t.equal(appConfig.scopes[0], 'store_write'); t.equal(appConfig.manifestURI(), 'https://example.com/manifest.json'); t.equal(appConfig.redirectURI(), 'https://example.com'); global.window = undefined; }); (0, _tape2.default)('app config works with custom app domain to origin', function (t) { t.plan(5); global.window = { location: { origin: 'https://example.com' } }; var appConfig = new _lib.AppConfig(['store_write'], 'https://custom.example.com'); t.equal(appConfig.appDomain, 'https://custom.example.com'); t.equal(appConfig.scopes.length, 1); t.equal(appConfig.scopes[0], 'store_write'); t.equal(appConfig.manifestURI(), 'https://custom.example.com/manifest.json'); t.equal(appConfig.redirectURI(), 'https://custom.example.com'); global.window = undefined; }); (0, _tape2.default)('handlePendingSignIn with authResponseToken, transit key and custom Blockstack API URL', function (t) { t.plan(2); var customBlockstackAPIUrl = 'https://test.name.lookups'; var oldBlockstackAPIUrl = _lib.config.network.blockstackAPIUrl; var url = customBlockstackAPIUrl + '/v1/names/ryan.id'; _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var appPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPublicKey = (0, _lib.getPublicKeyFromPrivate)(transitPrivateKey); var metadata = {}; var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); blockstack.store.getSessionData().transitKey = transitPrivateKey; var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id', metadata, undefined, appPrivateKey, undefined, transitPublicKey, undefined, customBlockstackAPIUrl); blockstack.handlePendingSignIn(authResponse).then(function () { t.pass('Should correctly sign in with auth response'); t.equal(_lib.config.network.blockstackAPIUrl, customBlockstackAPIUrl, 'Should override global Blockstack API URL'); _lib.config.network.blockstackAPIUrl = oldBlockstackAPIUrl; }).catch(function (err) { console.log(err.stack); t.fail('Should not error'); }); }); (0, _tape2.default)('handlePendingSignIn with authResponseToken, transit key, ' + 'Blockstack API URL, and Gaia association token', function (t) { t.plan(3); var customBlockstackAPIUrl = 'https://test.name.lookups'; var oldBlockstackAPIUrl = _lib.config.network.blockstackAPIUrl; var url = customBlockstackAPIUrl + '/v1/names/ryan.id'; _fetchMock2.default.get(url, _sampleData.sampleNameRecords.ryan); var appPrivateKey = (0, _lib.makeECPrivateKey)(); var identityPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPrivateKey = (0, _lib.makeECPrivateKey)(); var transitPublicKey = (0, _lib.getPublicKeyFromPrivate)(transitPrivateKey); var metadata = {}; var appPublicKey = (0, _lib.getPublicKeyFromPrivate)(appPrivateKey); var FOUR_MONTH_SECONDS = 60 * 60 * 24 * 31 * 4; var salt = '00000000000000000000000000000'; var identityPublicKey = (0, _lib.getPublicKeyFromPrivate)(identityPrivateKey); var associationTokenClaim = { childToAssociate: appPublicKey, iss: identityPublicKey, exp: FOUR_MONTH_SECONDS + new Date() / 1000, salt: salt }; var gaiaAssociationToken = new _jsontokens.TokenSigner('ES256K', identityPrivateKey).sign(associationTokenClaim); var authResponse = (0, _lib.makeAuthResponse)(privateKey, _sampleData.sampleProfiles.ryan, 'ryan.id', metadata, undefined, appPrivateKey, undefined, transitPublicKey, undefined, customBlockstackAPIUrl, gaiaAssociationToken); var appConfig = new _lib.AppConfig(['store_write'], 'http://localhost:3000'); var blockstack = new _lib.UserSession({ appConfig: appConfig }); blockstack.store.getSessionData().transitKey = transitPrivateKey; blockstack.handlePendingSignIn(authResponse).then(function () { t.pass('Should correctly sign in with auth response'); t.equal(_lib.config.network.blockstackAPIUrl, customBlockstackAPIUrl, 'Should override global Blockstack API URL'); t.equal(blockstack.loadUserData().gaiaAssociationToken, gaiaAssociationToken, 'Should have Gaia association token'); // restore _lib.config.network.blockstackAPIUrl = oldBlockstackAPIUrl; }).catch(function (err) { console.log(err.stack); t.fail('Should not error'); }); }); } // import test from 'tape'