class Net::IMAP::SASL::OAuthAuthenticator

def authorization; raise "must be implemented by subclass" end

Implemented by subclasses.

Value of the HTTP Authorization header
def authorization; raise "must be implemented by subclass" end

def done?; @done end

does *not* indicate success.
The authentication should not succeed unless this returns true, but it

Returns true when the initial client response was sent.
def done?; @done end

def initial_client_response

formatted response.
The {RFC7628 §3.1}[https://www.rfc-editor.org/rfc/rfc7628#section-3.1]
def initial_client_response
  kv_pairs = {
    host: host, port: port, mthd: mthd, path: path, post: post, qs: qs,
    auth: authorization, # authorization is implemented by subclasses
  }.compact
  [gs2_header, *kv_pairs.map {|kv| kv.join("=") }, "\1"].join("\1")
end

def initialize(authzid: nil, host: nil, port: nil,

Any other keyword parameters are quietly ignored.

_optional_ #query — An alias for #qs

* _optional_ #qs — HTTP query string
* _optional_ #post — HTTP post data
* _optional_ #path — HTTP path data
* _optional_ #mthd — HTTP method
* _optional_ #port — Service port to which the client connected.
* _optional_ #host — Hostname to which the client connected.

token.
authentication identity is established for the client by the OAuth
_authorization_ identity and not the _authentication_ identity. The
Note that, unlike some other authenticators, +username+ sets the

_optional_ #username — An alias for #authzid.

* _optional_ #authzid ― Authorization identity to act as or on behalf of.

#host or #port) as are specific server implementations.
are allowed to require #authzid (or other parameters, such as
are all optional, but it is worth noting that application protocols
See child classes for required parameter(s). The following parameters

==== Parameters

authenticator.
Creates an RFC7628[https://www.rfc-editor.org/rfc/rfc7628] OAuth
def initialize(authzid: nil, host: nil, port: nil,
               username: nil, query: nil,
               mthd: nil, path: nil, post: nil, qs: nil, **)
  @authzid = authzid || username
  @host    = host
  @port    = port
  @mthd    = mthd
  @path    = path
  @post    = post
  @qs      = qs || query
  @done    = false
end

def process(data)

Returns initial_client_response the first time, then "^A".
def process(data)
  @last_server_response = data
  done? ? "\1" : initial_client_response
ensure
  @done = true
end