3 var BSON = require('bson');
5 var f = require('util').format
7 , retrieveBSON = require('../connection/utils').retrieveBSON
8 , Query = require('../connection/commands').Query
9 , MongoError = require('../error');
11 var BSON = retrieveBSON();
13 var AuthSession = function(db, username, password) {
15 this.username = username;
16 this.password = password;
19 AuthSession.prototype.equal = function(session) {
20 return session.db == this.db
21 && session.username == this.username
22 && session.password == this.password;
26 * Creates a new Plain authentication mechanism
28 * @return {Plain} A cursor instance
30 var Plain = function(bson) {
38 * @param {{Server}|{ReplSet}|{Mongos}} server Topology the authentication method is being called on
39 * @param {[]Connections} connections Connections to authenticate using this authenticator
40 * @param {string} db Name of the database
41 * @param {string} username Username
42 * @param {string} password Password
43 * @param {authResultCallback} callback The callback to return the result from the authentication
46 Plain.prototype.auth = function(server, connections, db, username, password, callback) {
49 var count = connections.length;
50 if(count == 0) return callback(null, null);
53 var numberOfValidConnections = 0;
54 var errorObject = null;
56 // For each connection we need to authenticate
57 while(connections.length > 0) {
59 var execute = function(connection) {
61 var payload = new Binary(f("\x00%s\x00%s", username, password));
63 // Let's start the sasl process
71 // Let's start the process
72 server(connection, new Query(self.bson, "$external.$cmd", command, {
73 numberToSkip: 0, numberToReturn: 1
74 }), function(err, r) {
78 // If we have an error
81 } else if(r.result['$err']) {
82 errorObject = r.result;
83 } else if(r.result['errmsg']) {
84 errorObject = r.result;
86 numberOfValidConnections = numberOfValidConnections + 1;
89 // We have authenticated all connections
90 if(count == 0 && numberOfValidConnections > 0) {
91 // Store the auth details
92 addAuthSession(self.authStore, new AuthSession(db, username, password));
93 // Return correct authentication
95 } else if(count == 0) {
96 if(errorObject == null) errorObject = new MongoError(f("failed to authenticate using mongocr"));
97 callback(errorObject, false);
102 var _execute = function(_connection) {
103 process.nextTick(function() {
104 execute(_connection);
108 _execute(connections.shift());
112 // Add to store only if it does not exist
113 var addAuthSession = function(authStore, session) {
116 for(var i = 0; i < authStore.length; i++) {
117 if(authStore[i].equal(session)) {
123 if(!found) authStore.push(session);
127 * Remove authStore credentials
129 * @param {string} db Name of database we are removing authStore details about
132 Plain.prototype.logout = function(dbName) {
133 this.authStore = this.authStore.filter(function(x) {
134 return x.db != dbName;
139 * Re authenticate pool
141 * @param {{Server}|{ReplSet}|{Mongos}} server Topology the authentication method is being called on
142 * @param {[]Connections} connections Connections to authenticate using this authenticator
143 * @param {authResultCallback} callback The callback to return the result from the authentication
146 Plain.prototype.reauthenticate = function(server, connections, callback) {
147 var authStore = this.authStore.slice(0);
148 var count = authStore.length;
149 if(count == 0) return callback(null, null);
150 // Iterate over all the auth details stored
151 for(var i = 0; i < authStore.length; i++) {
152 this.auth(server, connections, authStore[i].db, authStore[i].username, authStore[i].password, function(err) {
154 // Done re-authenticating
163 * This is a result from a authentication strategy
165 * @callback authResultCallback
166 * @param {error} error An error object. Set to null if no error present
167 * @param {boolean} result The result of the authentication process
170 module.exports = Plain;