mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
147 lines
4.4 KiB
JavaScript
147 lines
4.4 KiB
JavaScript
var url = require('url');
|
|
var Gun = require('../gun');
|
|
|
|
/**
|
|
* Verify the origin
|
|
*
|
|
* @param {RegExp|Array|String|Function} allowed The allowed origins
|
|
* @param {String} origin String representation of the request URL
|
|
* @return {Boolean} Whether or not the origin is valid
|
|
*/
|
|
var verifyOrigin = function(allowed, origin) {
|
|
var isValid = false;
|
|
if (allowed instanceof RegExp) {
|
|
isValid = allowed.test(origin);
|
|
} else if (allowed instanceof Array) {
|
|
isValid = allowed.indexOf(origin) !== -1;
|
|
} else if (allowed instanceof Function) {
|
|
isValid = allowed(origin);
|
|
} else {
|
|
isValid = allowed === origin;
|
|
}
|
|
return isValid;
|
|
};
|
|
|
|
/**
|
|
* Verify the authentication header
|
|
*
|
|
* @todo make this callback based
|
|
*
|
|
* @param {Function|String} check Check option passed in
|
|
* @param {String} authToken The auth token passed in query string
|
|
* @param {Object} query Full query string as an object
|
|
* @return {Boolean} Whether or not the auth header is valid
|
|
*/
|
|
var verifyAuth = function(check, authToken, query) {
|
|
var isValid = false;
|
|
if (check instanceof Function) {
|
|
isValid = check(authToken, query);
|
|
} else {
|
|
isValid = check === authToken;
|
|
}
|
|
return isValid === true;
|
|
};
|
|
|
|
Gun.on('opt', function(context) {
|
|
var opt = context.opt || {};
|
|
var ws = opt.ws || {};
|
|
|
|
if (!opt.verify) {
|
|
this.to.next(context);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* verify when instantiating Gun can contain the following keys:
|
|
* allowOrigins: Array|RegExp|String
|
|
* auth: String|Function
|
|
* authKey: String
|
|
* check: Function
|
|
*/
|
|
var verify = opt.verify;
|
|
if (ws.verifyClient && !verify.override) {
|
|
throw Error('Cannot override existing verifyClient option in `ws` configuration.');
|
|
}
|
|
|
|
/**
|
|
* Attach a verifyClient to the WS configuration.
|
|
*
|
|
* @param {Object} info Request information
|
|
* @param {Function} callback Called when verification is complete
|
|
*/
|
|
ws.verifyClient = function(info, callback) {
|
|
|
|
// Callback Definitions
|
|
var errorCallback = (errorCode, message) => {
|
|
callback(false, errorCode, message);
|
|
};
|
|
var successCallback = () => {
|
|
callback(true);
|
|
};
|
|
|
|
// 0. Verify security
|
|
if (verify.requireSecure && !info.secure) {
|
|
errorCallback(400, 'Insecure connection');
|
|
return;
|
|
}
|
|
|
|
// 1. Verify request origin
|
|
if (verify.allowOrigins && !verifyOrigin(verify.allowOrigins, info.origin)) {
|
|
errorCallback(403, 'Origin forbidden');
|
|
return;
|
|
}
|
|
|
|
// 2. Check authentication
|
|
if (verify.auth) {
|
|
|
|
// Retrieve parameters from the query string
|
|
// and convert into an object
|
|
var queryUrl = url.parse(info.req.url, true);
|
|
queryUrl.query = queryUrl.query || {};
|
|
|
|
// Get the header defined by the user
|
|
// Or use authorization by default.
|
|
var token = (verify.authKey)
|
|
? queryUrl.query[verify.authKey]
|
|
: queryUrl.query.authorization;
|
|
|
|
// Check the token against the verification function
|
|
if (!token || !verifyAuth(verify.auth, token, queryUrl.query)) {
|
|
errorCallback(403, 'Forbidden');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If no additional verification check is provided,
|
|
// simply return true at this point since all
|
|
// provided verifications have passed.
|
|
if (!verify.check) {
|
|
successCallback();
|
|
return;
|
|
}
|
|
|
|
// 3. Pass to generic check handler
|
|
// This can return a value; alternatively, this can use the
|
|
// callback functionality
|
|
var isValid = verify.check(info, successCallback, errorCallback);
|
|
|
|
// Check returned a response, pass this to the callback
|
|
// If not, assume the user will call
|
|
if (typeof isValid !== 'undefined') {
|
|
if (typeof isValid === 'boolean') {
|
|
if (isValid === true) {
|
|
successCallback();
|
|
} else {
|
|
errorCallback(400);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
context.opt.ws = ws;
|
|
|
|
// Pass to next plugins
|
|
this.to.next(context);
|
|
});
|
|
|
|
module.exports = Gun;
|