class Net::IMAP::SASL::AuthenticationExchange
end
.authenticate
.new(sasl_adapter, mechanism, authenticator)
SASL::AuthenticationExchange
authenticator = SASL.authenticator(mechanism, …)
sasl_adapter = MyClient::SASLAdapter.new(self)
def authenticate(mechanism, …)
And ::build delegates to SASL.authenticator and ::new, like so:
end
.authenticate
.build(sasl_adapter, …)
SASL::AuthenticationExchange
sasl_adapter = MyClient::SASLAdapter.new(self)
def authenticate(…)
::authenticate simply delegates to ::build and #authenticate, like so:
end
SASL::AuthenticationExchange.authenticate(sasl_adapter, …)
sasl_adapter = MyClient::SASLAdapter.new(self)
def authenticate(…)
SASL::ClientAdapter#authenticate delegates to ::authenticate, like so:
end
MyClient::SASLAdapter.new(self).authenticate(…)
def authenticate(…)
custom client adapter is probably the best place for that code.
SASL::ClientAdapter#authenticate. If customizations are needed, the
SASL::AuthenticationExchange directly at all. Instead, use
In most cases, the client will not need to use
failure.
returning the client response on success and raising an exception on
called, it will send the appropriate authenticate command to the server,
mechanism name, and a mechanism authenticator. When #authenticate is
a SASL client to a SASL server. It is created from a client adapter, a
An AuthenticationExchange represents a single attempt to authenticate
TODO: pass ClientAdapter#service to SASL.authenticator
TODO: use with more clients, to verify the API can accommodate them.
TODO: raise an error if the command succeeds after being canceled.
TODO: catch exceptions in #process and send #cancel_response.
But the API is still experimental, and may change.
AuthenticationExchange is used internally by Net::IMAP#authenticate.
def self.authenticate(...) build(...).authenticate end
Convenience method for build(...).authenticate
def self.authenticate(...) build(...).authenticate end
def self.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block)
SASL.authenticator. Use the +registry+ kwarg to override the global
+mechanism+, +args+, +kwargs+, and +block+ are all forwarded to
client adapter all support it. Defaults to +true+.
also on whether the server capabilities, mechanism authenticator, and
+sasl_ir+ allows or disallows sending an "initial response", depending
+mechanism+ must be a SASL mechanism name, as a string or symbol.
+client+ must be an instance of SASL::ClientAdapter.
a new Authentication exchange.
Convenience method to combine the creation of a new authenticator and
def self.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block) authenticator = SASL.authenticator(mechanism, *args, **kwargs, &block) new(client, mechanism, authenticator, sasl_ir: sasl_ir) end
def authenticate
exception. Any exceptions other than those in RESPONSE_ERRORS will
using #authenticator. Authentication failures will raise an
Call #authenticate to execute an authentication exchange for #client
def authenticate client.run_command(mechanism, initial_response) { process _1 } .tap { raise AuthenticationIncomplete, _1 unless done? } rescue *client.response_errors raise # but don't drop the connection rescue client.drop_connection raise rescue Exception # rubocop:disable Lint/RescueException client.drop_connection! raise end
def done?
def done? authenticator.respond_to?(:done?) ? authenticator.done? : @processed end
def initial_response
def initial_response return unless send_initial_response? client.encode_ir authenticator.process nil end
def initialize(client, mechanism, authenticator, sasl_ir: true)
def initialize(client, mechanism, authenticator, sasl_ir: true) @client = client @mechanism = Authenticators.normalize_name(mechanism) @authenticator = authenticator @sasl_ir = sasl_ir @processed = false end
def process(challenge)
def process(challenge) client.encode authenticator.process client.decode challenge ensure @processed = true end
def send_initial_response?
def send_initial_response? @sasl_ir && authenticator.respond_to?(:initial_response?) && authenticator.initial_response? && client.sasl_ir_capable? && client.auth_capable?(mechanism) end