You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.6 KiB

  1. /*!
  2. * Connect - basicAuth
  3. * Copyright(c) 2010 Sencha Inc.
  4. * Copyright(c) 2011 TJ Holowaychuk
  5. * MIT Licensed
  6. */
  7. /**
  8. * Module dependencies.
  9. */
  10. var utils = require('../utils')
  11. , unauthorized = utils.unauthorized;
  12. /**
  13. * Basic Auth:
  14. *
  15. * Enfore basic authentication by providing a `callback(user, pass)`,
  16. * which must return `true` in order to gain access. Alternatively an async
  17. * method is provided as well, invoking `callback(user, pass, callback)`. Populates
  18. * `req.user`. The final alternative is simply passing username / password
  19. * strings.
  20. *
  21. * Simple username and password
  22. *
  23. * connect(connect.basicAuth('username', 'password'));
  24. *
  25. * Callback verification
  26. *
  27. * connect()
  28. * .use(connect.basicAuth(function(user, pass){
  29. * return 'tj' == user & 'wahoo' == pass;
  30. * }))
  31. *
  32. * Async callback verification, accepting `fn(err, user)`.
  33. *
  34. * connect()
  35. * .use(connect.basicAuth(function(user, pass, fn){
  36. * User.authenticate({ user: user, pass: pass }, fn);
  37. * }))
  38. *
  39. * @param {Function|String} callback or username
  40. * @param {String} realm
  41. * @api public
  42. */
  43. module.exports = function basicAuth(callback, realm) {
  44. var username, password;
  45. // user / pass strings
  46. if ('string' == typeof callback) {
  47. username = callback;
  48. password = realm;
  49. if ('string' != typeof password) throw new Error('password argument required');
  50. realm = arguments[2];
  51. callback = function(user, pass){
  52. return user == username && pass == password;
  53. }
  54. }
  55. realm = realm || 'Authorization Required';
  56. return function(req, res, next) {
  57. var authorization = req.headers.authorization;
  58. if (req.user) return next();
  59. if (!authorization) return unauthorized(res, realm);
  60. var parts = authorization.split(' ');
  61. if (parts.length !== 2) return next(utils.error(400));
  62. var scheme = parts[0]
  63. , credentials = new Buffer(parts[1], 'base64').toString()
  64. , index = credentials.indexOf(':');
  65. if ('Basic' != scheme || index < 0) return next(utils.error(400));
  66. var user = credentials.slice(0, index)
  67. , pass = credentials.slice(index + 1);
  68. // async
  69. if (callback.length >= 3) {
  70. var pause = utils.pause(req);
  71. callback(user, pass, function(err, user){
  72. if (err || !user) return unauthorized(res, realm);
  73. req.user = req.remoteUser = user;
  74. next();
  75. pause.resume();
  76. });
  77. // sync
  78. } else {
  79. if (callback(user, pass)) {
  80. req.user = req.remoteUser = user;
  81. next();
  82. } else {
  83. unauthorized(res, realm);
  84. }
  85. }
  86. }
  87. };