authenticate.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. 'use strict';
  2. var shallowClone = require('./utils').shallowClone,
  3. handleCallback = require('./utils').handleCallback,
  4. MongoError = require('mongodb-core').MongoError,
  5. f = require('util').format;
  6. var authenticate = function(client, username, password, options, callback) {
  7. // Did the user destroy the topology
  8. if (client.topology && client.topology.isDestroyed())
  9. return callback(new MongoError('topology was destroyed'));
  10. // the default db to authenticate against is 'self'
  11. // if authententicate is called from a retry context, it may be another one, like admin
  12. var authdb = options.dbName;
  13. authdb = options.authdb ? options.authdb : authdb;
  14. authdb = options.authSource ? options.authSource : authdb;
  15. // Callback
  16. var _callback = function(err, result) {
  17. if (client.listeners('authenticated').length > 0) {
  18. client.emit('authenticated', err, result);
  19. }
  20. // Return to caller
  21. handleCallback(callback, err, result);
  22. };
  23. // authMechanism
  24. var authMechanism = options.authMechanism || '';
  25. authMechanism = authMechanism.toUpperCase();
  26. // If classic auth delegate to auth command
  27. if (authMechanism === 'MONGODB-CR') {
  28. client.topology.auth('mongocr', authdb, username, password, function(err) {
  29. if (err) return handleCallback(callback, err, false);
  30. _callback(null, true);
  31. });
  32. } else if (authMechanism === 'PLAIN') {
  33. client.topology.auth('plain', authdb, username, password, function(err) {
  34. if (err) return handleCallback(callback, err, false);
  35. _callback(null, true);
  36. });
  37. } else if (authMechanism === 'MONGODB-X509') {
  38. client.topology.auth('x509', authdb, username, password, function(err) {
  39. if (err) return handleCallback(callback, err, false);
  40. _callback(null, true);
  41. });
  42. } else if (authMechanism === 'SCRAM-SHA-1') {
  43. client.topology.auth('scram-sha-1', authdb, username, password, function(err) {
  44. if (err) return handleCallback(callback, err, false);
  45. _callback(null, true);
  46. });
  47. } else if (authMechanism === 'SCRAM-SHA-256') {
  48. client.topology.auth('scram-sha-256', authdb, username, password, function(err) {
  49. if (err) return handleCallback(callback, err, false);
  50. _callback(null, true);
  51. });
  52. } else if (authMechanism === 'GSSAPI') {
  53. if (process.platform === 'win32') {
  54. client.topology.auth('sspi', authdb, username, password, options, function(err) {
  55. if (err) return handleCallback(callback, err, false);
  56. _callback(null, true);
  57. });
  58. } else {
  59. client.topology.auth('gssapi', authdb, username, password, options, function(err) {
  60. if (err) return handleCallback(callback, err, false);
  61. _callback(null, true);
  62. });
  63. }
  64. } else if (authMechanism === 'DEFAULT') {
  65. client.topology.auth('default', authdb, username, password, function(err) {
  66. if (err) return handleCallback(callback, err, false);
  67. _callback(null, true);
  68. });
  69. } else {
  70. handleCallback(
  71. callback,
  72. MongoError.create({
  73. message: f('authentication mechanism %s not supported', options.authMechanism),
  74. driver: true
  75. })
  76. );
  77. }
  78. };
  79. module.exports = function(self, username, password, options, callback) {
  80. if (typeof options === 'function') (callback = options), (options = {});
  81. options = options || {};
  82. // Shallow copy the options
  83. options = shallowClone(options);
  84. // Set default mechanism
  85. if (!options.authMechanism) {
  86. options.authMechanism = 'DEFAULT';
  87. } else if (
  88. options.authMechanism !== 'GSSAPI' &&
  89. options.authMechanism !== 'DEFAULT' &&
  90. options.authMechanism !== 'MONGODB-CR' &&
  91. options.authMechanism !== 'MONGODB-X509' &&
  92. options.authMechanism !== 'SCRAM-SHA-1' &&
  93. options.authMechanism !== 'SCRAM-SHA-256' &&
  94. options.authMechanism !== 'PLAIN'
  95. ) {
  96. return handleCallback(
  97. callback,
  98. MongoError.create({
  99. message:
  100. 'only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, or SCRAM-SHA-1 is supported by authMechanism',
  101. driver: true
  102. })
  103. );
  104. }
  105. // If we have a callback fallback
  106. if (typeof callback === 'function')
  107. return authenticate(self, username, password, options, function(err, r) {
  108. // Support failed auth method
  109. if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
  110. // Reject error
  111. if (err) return callback(err, r);
  112. callback(null, r);
  113. });
  114. // Return a promise
  115. return new self.s.promiseLibrary(function(resolve, reject) {
  116. authenticate(self, username, password, options, function(err, r) {
  117. // Support failed auth method
  118. if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
  119. // Reject error
  120. if (err) return reject(err);
  121. resolve(r);
  122. });
  123. });
  124. };