123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Auth::Base Private

Do not use. This class is for internal use only.
Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Aws, Mongo::Auth::CR, Mongo::Auth::Gssapi, Mongo::Auth::LDAP, Mongo::Auth::Scram, Mongo::Auth::Scram256, Mongo::Auth::X509
Inherits: Object
Defined in: lib/mongo/auth/base.rb

Overview

Base class for authenticators.

Each authenticator is instantiated for authentication over a particular connection.

Since:

  • 2.0.0

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#connectionMongo::Connection (readonly)

Returns:

  • (Mongo::Connection)

    The connection to authenticate over.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 30

attr_reader :connection

#userMongo::Auth::User (readonly)

Returns:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 27

attr_reader :user

Instance Method Details

#conversation

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 42

def conversation
  @conversation ||= self.class.const_get(:Conversation).new(user, connection)
end

#converse_1_step(connection, conversation) (private)

Performs a single-step conversation on the given connection.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 49

def converse_1_step(connection, conversation)
  msg = conversation.start(connection)
  dispatch_msg(connection, conversation, msg)
end

#converse_2_step(connection, conversation) (private)

Performs a two-step conversation on the given connection.

The implementation is very similar to #converse_multi_step, but conversations using this method do not involve the server replying with true to indicate the end of the conversation.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 59

def converse_2_step(connection, conversation)
  msg = conversation.start(connection)
  reply_document = dispatch_msg(connection, conversation, msg)
  msg = conversation.continue(reply_document, connection)
  dispatch_msg(connection, conversation, msg)
end

#converse_multi_step(connection, conversation, speculative_auth_result: nil) (private)

Performs the variable-length SASL conversation on the given connection.

Parameters:

  • connection (Server::Connection)

    The connection.

  • conversation (Auth::*::Conversation)

    The conversation.

  • speculative_auth_result (BSON::Document | nil)

    The value of speculativeAuthenticate field of hello response of the handshake on the specified connection.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 73

def converse_multi_step(connection, conversation,
                        speculative_auth_result: nil)
  # Although the SASL conversation in theory can have any number of
  # steps, all defined authentication methods have a predefined number
  # of steps, and therefore all of our authenticators have a fixed set
  # of methods that generate payloads with one method per step.
  # We support a maximum of 3 total exchanges (start, continue and
  # finalize) and in practice the first two exchanges always happen.
  if speculative_auth_result
    reply_document = speculative_auth_result
  else
    msg = conversation.start(connection)
    reply_document = dispatch_msg(connection, conversation, msg)
  end
  msg = conversation.continue(reply_document, connection)
  reply_document = dispatch_msg(connection, conversation, msg)
  conversation.process_continue_response(reply_document)
  unless reply_document[:done]
    msg = conversation.finalize(connection)
    reply_document = dispatch_msg(connection, conversation, msg)
  end
  unless reply_document[:done]
    raise Error::InvalidServerAuthResponse,
          'Server did not respond with {done: true} after finalizing the conversation'
  end
  reply_document
end

#dispatch_msg(connection, conversation, msg) (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 101

def dispatch_msg(connection, conversation, msg)
  context = Operation::Context.new(options: {
                                     server_api: connection.options[:server_api],
                                   })
  if server_api = context.server_api
    msg = msg.maybe_add_server_api(server_api)
  end
  reply = connection.dispatch([ msg ], context)
  reply_document = reply.documents.first
  validate_reply!(connection, conversation, reply_document)
  connection_global_id = (connection.global_id if connection.respond_to?(:global_id))
  result = Operation::Result.new(reply, connection.description, connection_global_id, context: context)
  connection.update_cluster_time(result)
  reply_document
end

#validate_reply!(connection, _conversation, doc) (private)

Checks whether reply is successful (i.e. has 1 set) and raises Unauthorized if not.

Raises:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/auth/base.rb', line 119

def validate_reply!(connection, _conversation, doc)
  return unless doc[:ok] != 1

  message = Error::Parser.build_message(
    code: doc[:code],
    code_name: doc[:codeName],
    message: doc[:errmsg]
  )

  raise Unauthorized.new(user,
                         used_mechanism: self.class.const_get(:MECHANISM),
                         message: message,
                         server: connection.server,
                         code: doc[:code])
end