Class: Net::IMAP::SASL::AuthenticationExchange
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/net/imap/sasl/authentication_exchange.rb |
Overview
AuthenticationExchange
is used internally by Net::IMAP#authenticate. But the API is still experimental, and may change.
TODO: catch exceptions in #process and send #cancel_response
. TODO: raise an error if the command succeeds after being canceled. TODO: use with more clients, to verify the API can accommodate them. TODO: pass ClientAdapter#service
to authenticator
An AuthenticationExchange represents a single attempt to authenticate a ::Net::IMAP::SASL
client to a ::Net::IMAP::SASL
server. It is created from a client adapter, a mechanism name, and a mechanism authenticator. When #authenticate is called, it will send the appropriate authenticate command to the server, returning the client response on success and raising an exception on failure.
In most cases, the client will not need to use AuthenticationExchange
directly at all. Instead, use ClientAdapter#authenticate. If customizations are needed, the custom client adapter is probably the best place for that code.
def authenticate(...)
MyClient::SASLAdapter.new(self).authenticate(...)
end
ClientAdapter#authenticate delegates to .authenticate, like so:
def authenticate(...)
sasl_adapter = MyClient::SASLAdapter.new(self)
SASL::AuthenticationExchange.authenticate(sasl_adapter, ...)
end
.authenticate simply delegates to .build and #authenticate, like so:
def authenticate(...)
sasl_adapter = MyClient::SASLAdapter.new(self)
SASL::AuthenticationExchange
.build(sasl_adapter, ...)
.authenticate
end
And .build delegates to authenticator and .new, like so:
def authenticate(mechanism, ...)
sasl_adapter = MyClient::SASLAdapter.new(self)
authenticator = SASL.authenticator(mechanism, ...)
SASL::AuthenticationExchange
.new(sasl_adapter, mechanism, authenticator)
.authenticate
end
Class Method Summary
-
.authenticate
Convenience method for
build(...).authenticate
. -
.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block)
Convenience method to combine the creation of a new authenticator and a new Authentication exchange.
- .new(client, mechanism, authenticator, sasl_ir: true) ⇒ AuthenticationExchange constructor
Instance Attribute Summary
- #authenticator readonly
- #done? ⇒ Boolean readonly
- #mechanism readonly
- #send_initial_response? ⇒ Boolean readonly
- #client readonly private
Instance Method Summary
-
#authenticate
Call #authenticate to execute an authentication exchange for #client using #authenticator.
- #initial_response private
- #process(challenge) private
Constructor Details
.new(client, mechanism, authenticator, sasl_ir: true) ⇒ AuthenticationExchange
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 84
def initialize(client, mechanism, authenticator, sasl_ir: true) @client = client @mechanism = Authenticators.normalize_name(mechanism) @authenticator = authenticator @sasl_ir = sasl_ir @processed = false end
Class Method Details
.authenticate
Convenience method for build(...).authenticate
See also: ClientAdapter#authenticate
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 61
def self.authenticate(...) build(...).authenticate end
.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block)
Convenience method to combine the creation of a new authenticator and a new Authentication exchange.
#client must be an instance of ClientAdapter
.
#mechanism must be a ::Net::IMAP::SASL
mechanism name, as a string or symbol.
sasl_ir
allows or disallows sending an “initial response”, depending also on whether the server capabilities, mechanism authenticator, and client adapter all support it. Defaults to true
.
#mechanism, args
, kwargs
, and block
are all forwarded to Net::IMAP::SASL.authenticator. Use the registry
kwarg to override the global Authenticators
registry.
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 77
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
Instance Attribute Details
#authenticator (readonly)
[ GitHub ]# File 'lib/net/imap/sasl/authentication_exchange.rb', line 82
attr_reader :mechanism, :authenticator
#client (readonly, private)
[ GitHub ]# File 'lib/net/imap/sasl/authentication_exchange.rb', line 123
attr_reader :client
#done? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 117
def done? authenticator.respond_to?(:done?) ? authenticator.done? : @processed end
#mechanism (readonly)
[ GitHub ]# File 'lib/net/imap/sasl/authentication_exchange.rb', line 82
attr_reader :mechanism, :authenticator
#send_initial_response? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 109
def send_initial_response? @sasl_ir && authenticator.respond_to?(:initial_response?) && authenticator.initial_response? && client.sasl_ir_capable? && client.auth_capable?(mechanism) end
Instance Method Details
#authenticate
Call #authenticate
to execute an authentication exchange for #client using #authenticator. Authentication failures will raise an exception. Any exceptions other than those in RESPONSE_ERRORS will drop the connection.
# File 'lib/net/imap/sasl/authentication_exchange.rb', line 96
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
#initial_response (private)
[ GitHub ]# File 'lib/net/imap/sasl/authentication_exchange.rb', line 125
def initial_response return unless send_initial_response? client.encode_ir authenticator.process nil end
#process(challenge) (private)
[ GitHub ]# File 'lib/net/imap/sasl/authentication_exchange.rb', line 130
def process(challenge) client.encode authenticator.process client.decode challenge ensure @processed = true end