class Net::IMAP::SASL::ScramAuthenticator
Abstract base class for the “SCRAM-*
” family of SASL
mechanisms, defined in RFC5802. Use via Net::IMAP#authenticate
.
Directly supported:
-
SCRAM-SHA-1
—ScramSHA1Authenticator
-
SCRAM-SHA-256
—ScramSHA256Authenticator
New SCRAM-*
mechanisms can easily be added for any hash algorithm supported by OpenSSL::Digest. Subclasses need only set an appropriate DIGEST_NAME
constant.
SCRAM algorithm¶ ↑
See the documentation and method definitions on ScramAlgorithm
for an overview of the algorithm. The different mechanisms differ only by which hash function that is used (or by support for channel binding with -PLUS
).
See also the methods on GS2Header
.
Server messages¶ ↑
As server messages are received, they are validated and loaded into the various attributes, e.g: snonce
, salt
, iterations
, verifier, server_error
, etc.
Unlike many other SASL
mechanisms, the SCRAM-*
family supports mutual authentication and can return server error data in the server messages. If process
raises an Error
for the server-final-message, then server_error
may contain error details.
TLS Channel binding¶ ↑
The SCRAM-*-PLUS
mechanisms and channel binding are not supported yet.
Caching SCRAM secrets¶ ↑
Caching of salted_password, client_key, stored_key, and server_key is not supported yet.
Attributes
Authorization identity: an identity to act as or on behalf of. The identity form is application protocol specific. If not provided or left blank, the server derives an authorization identity from the authentication identity. For example, an administrator or superuser might take on another role:
imap.authenticate "SCRAM-SHA-256", "root", passwd, authzid: "user"
The server is responsible for verifying the client’s credentials and verifying that the identity it associates with the client’s authentication identity is allowed to act as (or on behalf of) the authorization identity.
The client nonce, generated by SecureRandom
The iteration count for the selected hash function and user
The minimal allowed iteration count. Lower iterations
will raise an Error
.
A password or passphrase that matches the username
.
The salt used by the server for this user
A password or passphrase that matches the username
.
An error reported by the server during the SASL exchange.
Does not include errors reported by the protocol, e.g. Net::IMAP::NoResponseError
.
The server nonce, which must start with cnonce
Public Class Methods
Creates an authenticator for one of the “SCRAM-*
” SASL
mechanisms. Each subclass defines digest
to match a specific mechanism.
Called by Net::IMAP#authenticate
and similar methods on other clients.
Parameters¶ ↑
-
password
― Password or passphrase associated with thisusername
. -
optional
authzid
― Alternate identity to act as or on behalf of. -
optional
min_iterations
- Overrides the default value (4096).
Any other keyword parameters are quietly ignored.
# File lib/net/imap/sasl/scram_authenticator.rb, line 80 def initialize(username_arg = nil, password_arg = nil, authcid: nil, username: nil, authzid: nil, password: nil, secret: nil, min_iterations: 4096, # see both RFC5802 and RFC7677 cnonce: nil, # must only be set in tests **options) @username = username || username_arg || authcid or raise ArgumentError, "missing username (authcid)" @password = password || secret || password_arg or raise ArgumentError, "missing password" @authzid = authzid @min_iterations = Integer min_iterations @min_iterations.positive? or raise ArgumentError, "min_iterations must be positive" @cnonce = cnonce || SecureRandom.base64(32) end
Public Instance Methods
Returns a new OpenSSL::Digest object, set to the appropriate hash function for the chosen mechanism.
The class’s DIGEST_NAME
constant must be set to the name of an algorithm supported by OpenSSL::Digest.
# File lib/net/imap/sasl/scram_authenticator.rb, line 155 def digest; OpenSSL::Digest.new self.class::DIGEST_NAME end
Is the authentication exchange complete?
If false, another server continuation is required.
# File lib/net/imap/sasl/scram_authenticator.rb, line 185 def done?; @state == :done end
See RFC5802 §7 client-first-message
.
# File lib/net/imap/sasl/scram_authenticator.rb, line 159 def initial_client_response "#{gs2_header}#{client_first_message_bare}" end
responds to the server’s challenges
# File lib/net/imap/sasl/scram_authenticator.rb, line 164 def process(challenge) case (@state ||= :initial_client_response) when :initial_client_response initial_client_response.tap { @state = :server_first_message } when :server_first_message recv_server_first_message challenge final_message_with_proof.tap { @state = :server_final_message } when :server_final_message recv_server_final_message challenge "".tap { @state = :done } else raise Error, "server sent after complete, %p" % [challenge] end rescue Exception => ex @state = ex raise end