@@ -51,6 +51,11 @@ var authenticate = function(client, username, password, options, callback) {
       if (err) return handleCallback(callback, err, false);
       _callback(null, true);
     });
+  } else if (authMechanism === 'SCRAM-SHA-256') {
+    client.topology.auth('scram-sha-256', authdb, username, password, function(err) {
+      if (err) return handleCallback(callback, err, false);
+      _callback(null, true);
+    });
   } else if (authMechanism === 'GSSAPI') {
     if (process.platform === 'win32') {
       client.topology.auth('sspi', authdb, username, password, options, function(err) {
'use strict';

var shallowClone = require('./utils').shallowClone,
  handleCallback = require('./utils').handleCallback,
  MongoError = require('mongodb-core').MongoError,
  f = require('util').format;

var authenticate = function(client, username, password, options, callback) {
  // Did the user destroy the topology
  if (client.topology && client.topology.isDestroyed())
    return callback(new MongoError('topology was destroyed'));

  // the default db to authenticate against is 'self'
  // if authententicate is called from a retry context, it may be another one, like admin
  var authdb = options.dbName;
  authdb = options.authdb ? options.authdb : authdb;
  authdb = options.authSource ? options.authSource : authdb;

  // Callback
  var _callback = function(err, result) {
    if (client.listeners('authenticated').length > 0) {
      client.emit('authenticated', err, result);
    }

    // Return to caller
    handleCallback(callback, err, result);
  };

  // authMechanism
  var authMechanism = options.authMechanism || '';
  authMechanism = authMechanism.toUpperCase();

  // If classic auth delegate to auth command
  if (authMechanism === 'MONGODB-CR') {
    client.topology.auth('mongocr', authdb, username, password, function(err) {
      if (err) return handleCallback(callback, err, false);
      _callback(null, true);
    });
  } else if (authMechanism === 'PLAIN') {
    client.topology.auth('plain', authdb, username, password, function(err) {
      if (err) return handleCallback(callback, err, false);
      _callback(null, true);
    });
  } else if (authMechanism === 'MONGODB-X509') {
    client.topology.auth('x509', authdb, username, password, function(err) {
      if (err) return handleCallback(callback, err, false);
      _callback(null, true);
    });
  } else if (authMechanism === 'SCRAM-SHA-1') {
    client.topology.auth('scram-sha-1', authdb, username, password, function(err) {
      if (err) return handleCallback(callback, err, false);
      _callback(null, true);
    });
  } else if (authMechanism === 'GSSAPI') {
    if (process.platform === 'win32') {
      client.topology.auth('sspi', authdb, username, password, options, function(err) {
        if (err) return handleCallback(callback, err, false);
        _callback(null, true);
      });
    } else {
      client.topology.auth('gssapi', authdb, username, password, options, function(err) {
        if (err) return handleCallback(callback, err, false);
        _callback(null, true);
      });
    }
  } else if (authMechanism === 'DEFAULT') {
    client.topology.auth('default', authdb, username, password, function(err) {
      if (err) return handleCallback(callback, err, false);
      _callback(null, true);
    });
  } else {
    handleCallback(
      callback,
      MongoError.create({
        message: f('authentication mechanism %s not supported', options.authMechanism),
        driver: true
      })
    );
  }
};

module.exports = function(self, username, password, options, callback) {
  if (typeof options === 'function') (callback = options), (options = {});
  options = options || {};

  // Shallow copy the options
  options = shallowClone(options);

  // Set default mechanism
  if (!options.authMechanism) {
    options.authMechanism = 'DEFAULT';
  } else if (
    options.authMechanism !== 'GSSAPI' &&
    options.authMechanism !== 'DEFAULT' &&
    options.authMechanism !== 'MONGODB-CR' &&
    options.authMechanism !== 'MONGODB-X509' &&
    options.authMechanism !== 'SCRAM-SHA-1' &&
    options.authMechanism !== 'PLAIN'
  ) {
    return handleCallback(
      callback,
      MongoError.create({
        message:
          'only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, or SCRAM-SHA-1 is supported by authMechanism',
        driver: true
      })
    );
  }

  // If we have a callback fallback
  if (typeof callback === 'function')
    return authenticate(self, username, password, options, function(err, r) {
      // Support failed auth method
      if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
      // Reject error
      if (err) return callback(err, r);
      callback(null, r);
    });

  // Return a promise
  return new self.s.promiseLibrary(function(resolve, reject) {
    authenticate(self, username, password, options, function(err, r) {
      // Support failed auth method
      if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
      // Reject error
      if (err) return reject(err);
      resolve(r);
    });
  });
};

it looks like every one of these methods does exactly the same thing, only changing the first string parameter. Can we combine them? It would certainly make refactoring easier in the future.