blockstack
Version:
The Blockstack Javascript library for authentication, identity, and storage.
424 lines (321 loc) • 18 kB
JavaScript
;
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'