verify.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. var url = require('url');
  2. var Gun = require('../gun');
  3. /**
  4. * Verify the origin
  5. *
  6. * @param {RegExp|Array|String|Function} allowed The allowed origins
  7. * @param {String} origin String representation of the request URL
  8. * @return {Boolean} Whether or not the origin is valid
  9. */
  10. var verifyOrigin = function(allowed, origin) {
  11. var isValid = false;
  12. if (allowed instanceof RegExp) {
  13. isValid = allowed.test(origin);
  14. } else if (allowed instanceof Array) {
  15. isValid = allowed.indexOf(origin) !== -1;
  16. } else if (allowed instanceof Function) {
  17. isValid = allowed(origin);
  18. } else {
  19. isValid = allowed === origin;
  20. }
  21. return isValid;
  22. };
  23. /**
  24. * Verify the authentication header
  25. *
  26. * @todo make this callback based
  27. *
  28. * @param {Function|String} check Check option passed in
  29. * @param {String} authToken The auth token passed in query string
  30. * @param {Object} query Full query string as an object
  31. * @return {Boolean} Whether or not the auth header is valid
  32. */
  33. var verifyAuth = function(check, authToken, query) {
  34. var isValid = false;
  35. if (check instanceof Function) {
  36. isValid = check(authToken, query);
  37. } else {
  38. isValid = check === authToken;
  39. }
  40. return isValid === true;
  41. };
  42. Gun.on('opt', function(context) {
  43. var opt = context.opt || {};
  44. var ws = opt.ws || {};
  45. if (!opt.verify) {
  46. this.to.next(context);
  47. return;
  48. }
  49. /**
  50. * verify when instantiating Gun can contain the following keys:
  51. * allowOrigins: Array|RegExp|String
  52. * auth: String|Function
  53. * authKey: String
  54. * check: Function
  55. */
  56. var verify = opt.verify;
  57. if (ws.verifyClient && !verify.override) {
  58. throw Error('Cannot override existing verifyClient option in `ws` configuration.');
  59. }
  60. /**
  61. * Attach a verifyClient to the WS configuration.
  62. *
  63. * @param {Object} info Request information
  64. * @param {Function} callback Called when verification is complete
  65. */
  66. ws.verifyClient = function(info, callback) {
  67. // Callback Definitions
  68. var errorCallback = (errorCode, message) => {
  69. callback(false, errorCode, message);
  70. };
  71. var successCallback = () => {
  72. callback(true);
  73. };
  74. // 0. Verify security
  75. if (verify.requireSecure && !info.secure) {
  76. errorCallback(400, 'Insecure connection');
  77. return;
  78. }
  79. // 1. Verify request origin
  80. if (verify.allowOrigins && !verifyOrigin(verify.allowOrigins, info.origin)) {
  81. errorCallback(403, 'Origin forbidden');
  82. return;
  83. }
  84. // 2. Check authentication
  85. if (verify.auth) {
  86. // Retrieve parameters from the query string
  87. // and convert into an object
  88. var queryUrl = url.parse(info.req.url, true);
  89. queryUrl.query = queryUrl.query || {};
  90. // Get the header defined by the user
  91. // Or use authorization by default.
  92. var token = (verify.authKey)
  93. ? queryUrl.query[verify.authKey]
  94. : queryUrl.query.authorization;
  95. // Check the token against the verification function
  96. if (!token || !verifyAuth(verify.auth, token, queryUrl.query)) {
  97. errorCallback(403, 'Forbidden');
  98. return;
  99. }
  100. }
  101. // If no additional verification check is provided,
  102. // simply return true at this point since all
  103. // provided verifications have passed.
  104. if (!verify.check) {
  105. successCallback();
  106. return;
  107. }
  108. // 3. Pass to generic check handler
  109. // This can return a value; alternatively, this can use the
  110. // callback functionality
  111. var isValid = verify.check(info, successCallback, errorCallback);
  112. // Check returned a response, pass this to the callback
  113. // If not, assume the user will call
  114. if (typeof isValid !== 'undefined') {
  115. if (typeof isValid === 'boolean') {
  116. if (isValid === true) {
  117. successCallback();
  118. } else {
  119. errorCallback(400);
  120. }
  121. }
  122. }
  123. };
  124. context.opt.ws = ws;
  125. // Pass to next plugins
  126. this.to.next(context);
  127. });
  128. module.exports = Gun;