blockstack
Version:
The Blockstack Javascript library for identity and authentication.
156 lines (135 loc) • 5.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.makeCoreSessionRequest = makeCoreSessionRequest;
exports.sendCoreSessionRequest = sendCoreSessionRequest;
exports.getCoreSession = getCoreSession;
var _jsontokens = require('jsontokens');
var _isomorphicFetch = require('isomorphic-fetch');
var _isomorphicFetch2 = _interopRequireDefault(_isomorphicFetch);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* Create an authentication token to be sent to the Core API server
* in order to generate a Core session JWT.
*
* @param appDomain (String) The unique application identifier (e.g. foo.app, www.foo.com, etc).
* @param appMethods (Array) The list of API methods this application will need.
* @param appPrivateKey (String) The application-specific private key
* @param blockchainId (String|null) This is the blockchain ID of the requester,
*
* @returns a JWT signed by the app's private key
* @private
*/
function makeCoreSessionRequest(appDomain, appMethods, appPrivateKey) {
var blockchainID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var thisDevice = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
if (thisDevice === null) {
thisDevice = '.default';
}
// TODO: multi-device
var appPublicKey = _jsontokens.SECP256K1Client.derivePublicKey(appPrivateKey);
var appPublicKeys = [{
public_key: appPublicKey,
device_id: thisDevice
}];
var authBody = {
version: 1,
blockchain_id: blockchainID,
app_private_key: appPrivateKey,
app_domain: appDomain,
methods: appMethods,
app_public_keys: appPublicKeys,
device_id: thisDevice
// make token
};var tokenSigner = new _jsontokens.TokenSigner('ES256k', appPrivateKey);
var token = tokenSigner.sign(authBody);
return token;
}
/*
* Send Core a request for a session token.
*
* @param coreAuthRequest (String) a signed JWT encoding the authentication request
* @param apiPassword (String) the API password for Core
*
* Returns a JWT signed with the Core API server's private key that authorizes the bearer
* to carry out the requested operations.
* @private
*/
function sendCoreSessionRequest(coreHost, corePort, coreAuthRequest, apiPassword) {
return new Promise(function (resolve, reject) {
if (!apiPassword) {
reject('Missing API password');
return null;
}
var options = {
headers: {
Authorization: 'bearer ' + apiPassword
}
};
var url = 'http://' + coreHost + ':' + corePort + '/v1/auth?authRequest=' + coreAuthRequest;
return (0, _isomorphicFetch2.default)(url, options).then(function (response) {
if (!response.ok) {
reject('HTTP status not OK');
return null;
}
return response.text();
}).then(function (responseText) {
return JSON.parse(responseText);
}).then(function (responseJson) {
var token = responseJson.token;
if (!token) {
reject('Failed to get Core session token');
return null;
}
resolve(token);
return token;
}).catch(function (error) {
console.error(error);
reject('Invalid Core response: not JSON');
});
});
}
/*
* Get a core session token. Generate an auth request, sign it, send it to Core,
* and get back a session token.
*
* @param coreHost (String) Core API server's hostname
* @param corePort (Integer) Core API server's port number
* @param appPrivateKey (String) Application's private key
* @param blockchainId (String|null) blockchain ID of the user signing in.
* `null` if user has no blockchain ID
*
* Returns a Promise that resolves to a Core session token.
* @private
*/
function getCoreSession(coreHost, corePort, apiPassword, appPrivateKey) {
var blockchainId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
var authRequest = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
var deviceId = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '0';
if (!authRequest) {
return Promise.reject('No authRequest provided');
}
var payload = null;
var authRequestObject = null;
try {
authRequestObject = (0, _jsontokens.decodeToken)(authRequest);
if (!authRequestObject) {
return Promise.reject('Invalid authRequest in URL query string');
}
if (!authRequestObject.payload) {
return Promise.reject('Invalid authRequest in URL query string');
}
payload = authRequestObject.payload;
} catch (e) {
console.error(e.stack);
return Promise.reject('Failed to parse authRequest in URL');
}
var appDomain = payload.domain_name;
if (!appDomain) {
return Promise.reject('No domain_name in authRequest');
}
var appMethods = payload.scopes;
var coreAuthRequest = makeCoreSessionRequest(appDomain, appMethods, appPrivateKey, blockchainId, deviceId);
return sendCoreSessionRequest(coreHost, corePort, coreAuthRequest, apiPassword);
}