 Auth = (api, next) ->
   config = api.config.auth
 
+  # Used to call a function when it's unknown whether it uses node callback style
+  # or returns a promise.
+  # Mimics Q.ninvoke except that it will still work if the function is already using 
+  # promises instead of node callback style
+  # If object['name'] returns a promise, this simply forwards that promise on
+  # If object['name'] resolves via node callback style, a promise is created and 
+  # resolved when the callback is called
+  _hninvoke = (object, name) ->
+    deferred = Q.defer()
+    callback = (err, result) ->
+      if (err)
+        deferred.reject(err)
+      else
+        deferred.resolve(result)
+    args = [].slice.call(arguments, 2) || []
+    args.push(callback)
+    
+    result = object[name].apply(object, args);
+
+    if Q.isPromiseAlike(result)
+      return result
+    else
+      return deferred.promise;
+
   _encodePassword =
     scrypt: (password) ->
       Q.ninvoke(scrypt, 'passwordHash', password, config.scrypt.maxtime)
 
-  _encodePasswordPromise = (password) ->
-    if Q.isPromiseAlike api.AuthImpl.encodePassword
-      api.AuthImpl.encodePassword password
-    else
-      Q.ninvoke api.AuthImpl, 'encodePassword', password
-
   encodePassword = (password, callback) ->
     if api.AuthImpl and api.AuthImpl.encodePassword
-      _encodePasswordPromise(password).nodeify callback
+      promise = _hninvoke(api.AuthImpl, 'encodePassword', password)
     else
-      _encodePassword['scrypt'](password).nodeify callback
+      promise = _hninvoke(_encodePassword, 'scrypt', password)
+    promise.nodeify(callback)
+    promise
 
   _matchPassword =
     scrypt: (passwordHash, password) ->

          deferred.resolve result
      deferred.promise

  _matchPasswordPromise = (passwordHash, password) ->
    if Q.isPromiseAlike api.AuthImpl.matchPassword
      api.AuthImpl.matchPassword passwordHash, password
    else
      Q.ninvoke api.AuthImpl, 'matchPassword', passwordHash, password

  matchPassword = (passwordHash, password, callback) ->
    deferred = Q.defer()
    if api.AuthImpl and api.AuthImpl.encodePassword

          new ImplementationError(
            "No 'api.AuthImpl.matchPassword' implementation"))
      else
        _hninvoke(api.AuthImpl, 'matchPassword', passwordHash, password)
        .then (result) ->
          deferred.resolve result
        .catch (error) ->
