net-imap 0.4.1 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,8 +29,9 @@ module Net
29
29
  # this, see Net::IMAP#authenticate or your client's authentication
30
30
  # method.
31
31
  #
32
- # #anonymous_message is an optional message which is sent to the server.
33
- # It may be sent as a positional argument or as a keyword argument.
32
+ # ==== Parameters
33
+ #
34
+ # * _optional_ #anonymous_message — a message to send to the server.
34
35
  #
35
36
  # Any other keyword arguments are silently ignored.
36
37
  def initialize(anon_msg = nil, anonymous_message: nil, **)
@@ -58,8 +58,8 @@ module Net::IMAP::SASL
58
58
  # {SASL mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
59
59
  # implemented by +authenticator_class+ (for instance, <tt>"PLAIN"</tt>).
60
60
  #
61
- # If +mechanism+ refers to an existing authenticator, a warning will be
62
- # printed and the old authenticator will be replaced.
61
+ # If +mechanism+ refers to an existing authenticator,
62
+ # the old authenticator will be replaced.
63
63
  #
64
64
  # When only a single argument is given, the authenticator class will be
65
65
  # lazily loaded from <tt>Net::IMAP::SASL::#{name}Authenticator</tt> (case is
@@ -14,13 +14,17 @@
14
14
  # of cleartext and recommends TLS version 1.2 or greater be used for all
15
15
  # traffic. With TLS +CRAM-MD5+ is okay, but so is +PLAIN+
16
16
  class Net::IMAP::SASL::CramMD5Authenticator
17
- def initialize(user, password, warn_deprecation: true, **_ignored)
17
+ def initialize(user = nil, pass = nil,
18
+ authcid: nil, username: nil,
19
+ password: nil, secret: nil,
20
+ warn_deprecation: true,
21
+ **)
18
22
  if warn_deprecation
19
23
  warn "WARNING: CRAM-MD5 mechanism is deprecated." # TODO: recommend SCRAM
20
24
  end
21
25
  require "digest/md5"
22
- @user = user
23
- @password = password
26
+ @user = authcid || username || user
27
+ @password = password || secret || pass
24
28
  @done = false
25
29
  end
26
30
 
@@ -20,8 +20,9 @@ class Net::IMAP::SASL::DigestMD5Authenticator
20
20
  # "Authentication identity" is the generic term used by
21
21
  # RFC-4422[https://tools.ietf.org/html/rfc4422].
22
22
  # RFC-4616[https://tools.ietf.org/html/rfc4616] and many later RFCs abbreviate
23
- # that to +authcid+. So +authcid+ is available as an alias for #username.
23
+ # this to +authcid+.
24
24
  attr_reader :username
25
+ alias authcid username
25
26
 
26
27
  # A password or passphrase that matches the #username.
27
28
  #
@@ -44,6 +45,7 @@ class Net::IMAP::SASL::DigestMD5Authenticator
44
45
  # :call-seq:
45
46
  # new(username, password, authzid = nil, **options) -> authenticator
46
47
  # new(username:, password:, authzid: nil, **options) -> authenticator
48
+ # new(authcid:, password:, authzid: nil, **options) -> authenticator
47
49
  #
48
50
  # Creates an Authenticator for the "+DIGEST-MD5+" SASL mechanism.
49
51
  #
@@ -51,17 +53,27 @@ class Net::IMAP::SASL::DigestMD5Authenticator
51
53
  #
52
54
  # ==== Parameters
53
55
  #
54
- # * #username Identity whose #password is used.
55
- # * #password — A password or passphrase associated with this #username.
56
- # * #authzid ― Alternate identity to act as or on behalf of. Optional.
57
- # * +warn_deprecation+ — Set to +false+ to silence the warning.
56
+ # * #authcid ― Authentication identity that is associated with #password.
58
57
  #
59
- # See the documentation for each attribute for more details.
58
+ # #username An alias for +authcid+.
59
+ #
60
+ # * #password ― A password or passphrase associated with this #authcid.
61
+ #
62
+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
63
+ #
64
+ # When +authzid+ is not set, the server should derive the authorization
65
+ # identity from the authentication identity.
66
+ #
67
+ # * _optional_ +warn_deprecation+ — Set to +false+ to silence the warning.
68
+ #
69
+ # Any other keyword arguments are silently ignored.
60
70
  def initialize(user = nil, pass = nil, authz = nil,
61
71
  username: nil, password: nil, authzid: nil,
72
+ authcid: nil, secret: nil,
62
73
  warn_deprecation: true, **)
63
- username ||= user or raise ArgumentError, "missing username"
64
- password ||= pass or raise ArgumentError, "missing password"
74
+ username = authcid || username || user or
75
+ raise ArgumentError, "missing username (authcid)"
76
+ password ||= secret || pass or raise ArgumentError, "missing password"
65
77
  authzid ||= authz
66
78
  if warn_deprecation
67
79
  warn "WARNING: DIGEST-MD5 SASL mechanism was deprecated by RFC6331."
@@ -12,24 +12,45 @@ module Net
12
12
  # established external to SASL, for example by TLS certificate or IPsec.
13
13
  class ExternalAuthenticator
14
14
 
15
- # Authorization identity: an identity to act as or on behalf of.
15
+ # Authorization identity: an identity to act as or on behalf of. The
16
+ # identity form is application protocol specific. If not provided or
17
+ # left blank, the server derives an authorization identity from the
18
+ # authentication identity. The server is responsible for verifying the
19
+ # client's credentials and verifying that the identity it associates
20
+ # with the client's authentication identity is allowed to act as (or on
21
+ # behalf of) the authorization identity.
22
+ #
23
+ # For example, an administrator or superuser might take on another role:
24
+ #
25
+ # imap.authenticate "PLAIN", "root", passwd, authzid: "user"
16
26
  #
17
- # If not explicitly provided, the server defaults to using the identity
18
- # that was authenticated by the external credentials.
19
27
  attr_reader :authzid
28
+ alias username authzid
20
29
 
21
30
  # :call-seq:
22
31
  # new(authzid: nil, **) -> authenticator
32
+ # new(username: nil, **) -> authenticator
33
+ # new(username = nil, **) -> authenticator
23
34
  #
24
35
  # Creates an Authenticator for the "+EXTERNAL+" SASL mechanism, as
25
36
  # specified in RFC-4422[https://tools.ietf.org/html/rfc4422]. To use
26
37
  # this, see Net::IMAP#authenticate or your client's authentication
27
38
  # method.
28
39
  #
29
- # #authzid is an optional identity to act as or on behalf of.
40
+ # ==== Parameters
41
+ #
42
+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
43
+ #
44
+ # _optional_ #username ― An alias for #authzid.
45
+ #
46
+ # Note that, unlike some other authenticators, +username+ sets the
47
+ # _authorization_ identity and not the _authentication_ identity. The
48
+ # authentication identity is established for the client by the
49
+ # external credentials.
30
50
  #
31
51
  # Any other keyword parameters are quietly ignored.
32
- def initialize(authzid: nil, **)
52
+ def initialize(user = nil, authzid: nil, username: nil, **)
53
+ authzid ||= username || user
33
54
  @authzid = authzid&.to_str&.encode "UTF-8"
34
55
  if @authzid&.match?(/\u0000/u) # also validates UTF8 encoding
35
56
  raise ArgumentError, "contains NULL"
@@ -23,12 +23,16 @@ class Net::IMAP::SASL::LoginAuthenticator
23
23
  STATE_DONE = :DONE
24
24
  private_constant :STATE_USER, :STATE_PASSWORD, :STATE_DONE
25
25
 
26
- def initialize(user, password, warn_deprecation: true, **_ignored)
26
+ def initialize(user = nil, pass = nil,
27
+ authcid: nil, username: nil,
28
+ password: nil, secret: nil,
29
+ warn_deprecation: true,
30
+ **)
27
31
  if warn_deprecation
28
32
  warn "WARNING: LOGIN SASL mechanism is deprecated. Use PLAIN instead."
29
33
  end
30
- @user = user
31
- @password = password
34
+ @user = authcid || username || user
35
+ @password = password || secret || pass
32
36
  @state = STATE_USER
33
37
  end
34
38
 
@@ -14,18 +14,25 @@ module Net
14
14
  class OAuthAuthenticator
15
15
  include GS2Header
16
16
 
17
- # Authorization identity: an identity to act as or on behalf of.
17
+ # Authorization identity: an identity to act as or on behalf of. The
18
+ # identity form is application protocol specific. If not provided or
19
+ # left blank, the server derives an authorization identity from the
20
+ # authentication identity. The server is responsible for verifying the
21
+ # client's credentials and verifying that the identity it associates
22
+ # with the client's authentication identity is allowed to act as (or on
23
+ # behalf of) the authorization identity.
24
+ #
25
+ # For example, an administrator or superuser might take on another role:
26
+ #
27
+ # imap.authenticate "PLAIN", "root", passwd, authzid: "user"
18
28
  #
19
- # If no explicit authorization identity is provided, it is usually
20
- # derived from the authentication identity. For the OAuth-based
21
- # mechanisms, the authentication identity is the identity established by
22
- # the OAuth credential.
23
29
  attr_reader :authzid
30
+ alias username authzid
24
31
 
25
- # Hostname to which the client connected.
32
+ # Hostname to which the client connected. (optional)
26
33
  attr_reader :host
27
34
 
28
- # Service port to which the client connected.
35
+ # Service port to which the client connected. (optional)
29
36
  attr_reader :port
30
37
 
31
38
  # HTTP method. (optional)
@@ -39,6 +46,7 @@ module Net
39
46
 
40
47
  # The query string. (optional)
41
48
  attr_reader :qs
49
+ alias query qs
42
50
 
43
51
  # Stores the most recent server "challenge". When authentication fails,
44
52
  # this may hold information about the failure reason, as JSON.
@@ -47,29 +55,42 @@ module Net
47
55
  # Creates an RFC7628[https://tools.ietf.org/html/rfc7628] OAuth
48
56
  # authenticator.
49
57
  #
50
- # === Options
58
+ # ==== Parameters
59
+ #
60
+ # See child classes for required parameter(s). The following parameters
61
+ # are all optional, but it is worth noting that <b>application protocols
62
+ # are allowed to require</b> #authzid (or other parameters, such as
63
+ # #host or #port) <b>as are specific server implementations</b>.
64
+ #
65
+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
66
+ #
67
+ # _optional_ #username — An alias for #authzid.
51
68
  #
52
- # See child classes for required configuration parameter(s). The
53
- # following parameters are all optional, but protocols or servers may
54
- # add requirements for #authzid, #host, #port, or any other parameter.
69
+ # Note that, unlike some other authenticators, +username+ sets the
70
+ # _authorization_ identity and not the _authentication_ identity. The
71
+ # authentication identity is established for the client by the OAuth
72
+ # token.
55
73
  #
56
- # * #authzid Identity to act as or on behalf of.
57
- # * #hostHostname to which the client connected.
58
- # * #portService port to which the client connected.
59
- # * #mthd — HTTP method
60
- # * #path — HTTP path data
61
- # * #post — HTTP post data
62
- # * #qs — HTTP query string
74
+ # * _optional_ #host Hostname to which the client connected.
75
+ # * _optional_ #portService port to which the client connected.
76
+ # * _optional_ #mthdHTTP method
77
+ # * _optional_ #path — HTTP path data
78
+ # * _optional_ #post — HTTP post data
79
+ # * _optional_ #qs — HTTP query string
63
80
  #
81
+ # _optional_ #query — An alias for #qs
82
+ #
83
+ # Any other keyword parameters are quietly ignored.
64
84
  def initialize(authzid: nil, host: nil, port: nil,
85
+ username: nil, query: nil,
65
86
  mthd: nil, path: nil, post: nil, qs: nil, **)
66
- @authzid = authzid
87
+ @authzid = authzid || username
67
88
  @host = host
68
89
  @port = port
69
90
  @mthd = mthd
70
91
  @path = path
71
92
  @post = post
72
- @qs = qs
93
+ @qs = qs || query
73
94
  @done = false
74
95
  end
75
96
 
@@ -116,35 +137,49 @@ module Net
116
137
  # the bearer token.
117
138
  class OAuthBearerAuthenticator < OAuthAuthenticator
118
139
 
119
- # An OAuth2 bearer token, generally the access token.
140
+ # An OAuth 2.0 bearer token. See {RFC-6750}[https://www.rfc-editor.org/rfc/rfc6750]
120
141
  attr_reader :oauth2_token
142
+ alias secret oauth2_token
121
143
 
122
144
  # :call-seq:
123
- # new(oauth2_token, **options) -> authenticator
124
- # new(oauth2_token:, **options) -> authenticator
145
+ # new(oauth2_token, **options) -> authenticator
146
+ # new(authzid, oauth2_token, **options) -> authenticator
147
+ # new(oauth2_token:, **options) -> authenticator
125
148
  #
126
149
  # Creates an Authenticator for the "+OAUTHBEARER+" SASL mechanism.
127
150
  #
128
151
  # Called by Net::IMAP#authenticate and similar methods on other clients.
129
152
  #
130
- # === Options
153
+ # ==== Parameters
154
+ #
155
+ # * #oauth2_token — An OAuth2 bearer token
156
+ #
157
+ # All other keyword parameters are passed to
158
+ # {super}[rdoc-ref:OAuthAuthenticator::new] (see OAuthAuthenticator).
159
+ # The most common ones are:
160
+ #
161
+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
162
+ #
163
+ # _optional_ #username — An alias for #authzid.
131
164
  #
132
- # Only +oauth2_token+ is required by the mechanism, however protocols
133
- # and servers may add requirements for #authzid, #host, #port, or any
134
- # other parameter.
165
+ # Note that, unlike some other authenticators, +username+ sets the
166
+ # _authorization_ identity and not the _authentication_ identity. The
167
+ # authentication identity is established for the client by
168
+ # #oauth2_token.
135
169
  #
136
- # * #oauth2_tokenAn OAuth2 bearer token or access token. *Required.*
137
- # May be provided as either regular or keyword argument.
138
- # * #authzid ― Identity to act as or on behalf of.
139
- # * #host — Hostname to which the client connected.
140
- # * #port — Service port to which the client connected.
141
- # * See OAuthAuthenticator documentation for less common parameters.
170
+ # * _optional_ #hostHostname to which the client connected.
171
+ # * _optional_ #port Service port to which the client connected.
142
172
  #
143
- def initialize(oauth2_token_arg = nil, oauth2_token: nil, **args, &blk)
144
- super(**args, &blk) # handles authzid, host, port, etc
145
- oauth2_token && oauth2_token_arg and
146
- raise ArgumentError, "conflicting values for oauth2_token"
147
- @oauth2_token = oauth2_token || oauth2_token_arg or
173
+ # Although only oauth2_token is required by this mechanism, it is worth
174
+ # noting that <b><em>application protocols are allowed to
175
+ # require</em></b> #authzid (<em>or other parameters, such as</em> #host
176
+ # _or_ #port) <b><em>as are specific server implementations</em></b>.
177
+ def initialize(arg1 = nil, arg2 = nil,
178
+ oauth2_token: nil, secret: nil,
179
+ **args, &blk)
180
+ username, oauth2_token_arg = arg2.nil? ? [nil, arg1] : [arg1, arg2]
181
+ super(username: username, **args, &blk)
182
+ @oauth2_token = oauth2_token || secret || oauth2_token_arg or
148
183
  raise ArgumentError, "missing oauth2_token"
149
184
  end
150
185
 
@@ -22,9 +22,11 @@ class Net::IMAP::SASL::PlainAuthenticator
22
22
  # RFC-4616[https://tools.ietf.org/html/rfc4616] and many later RFCs abbreviate
23
23
  # this to +authcid+.
24
24
  attr_reader :username
25
+ alias authcid username
25
26
 
26
27
  # A password or passphrase that matches the #username.
27
28
  attr_reader :password
29
+ alias secret password
28
30
 
29
31
  # Authorization identity: an identity to act as or on behalf of. The identity
30
32
  # form is application protocol specific. If not provided or left blank, the
@@ -42,26 +44,32 @@ class Net::IMAP::SASL::PlainAuthenticator
42
44
  # :call-seq:
43
45
  # new(username, password, authzid: nil, **) -> authenticator
44
46
  # new(username:, password:, authzid: nil, **) -> authenticator
47
+ # new(authcid:, password:, authzid: nil, **) -> authenticator
45
48
  #
46
49
  # Creates an Authenticator for the "+PLAIN+" SASL mechanism.
47
50
  #
48
51
  # Called by Net::IMAP#authenticate and similar methods on other clients.
49
52
  #
50
- # === Parameters
53
+ # ==== Parameters
51
54
  #
52
- # * #usernameIdentity whose +password+ is used.
53
- # * #password ― Password or passphrase associated with this username+.
54
- # * #authzid ― Alternate identity to act as or on behalf of. Optional.
55
+ # * #authcidAuthentication identity that is associated with #password.
55
56
  #
56
- # See attribute documentation for more details.
57
+ # #username An alias for #authcid.
58
+ #
59
+ # * #password ― A password or passphrase associated with the #authcid.
60
+ #
61
+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
62
+ #
63
+ # When +authzid+ is not set, the server should derive the authorization
64
+ # identity from the authentication identity.
65
+ #
66
+ # Any other keyword parameters are quietly ignored.
57
67
  def initialize(user = nil, pass = nil,
68
+ authcid: nil, secret: nil,
58
69
  username: nil, password: nil, authzid: nil, **)
59
- [username, user].compact.count == 1 or
60
- raise ArgumentError, "conflicting values for username"
61
- [password, pass].compact.count == 1 or
62
- raise ArgumentError, "conflicting values for password"
63
- username ||= user or raise ArgumentError, "missing username"
64
- password ||= pass or raise ArgumentError, "missing password"
70
+ username ||= authcid || user or
71
+ raise ArgumentError, "missing username (authcid)"
72
+ password ||= secret || pass or raise ArgumentError, "missing password"
65
73
  raise ArgumentError, "username contains NULL" if username.include?(NULL)
66
74
  raise ArgumentError, "password contains NULL" if password.include?(NULL)
67
75
  raise ArgumentError, "authzid contains NULL" if authzid&.include?(NULL)
@@ -60,6 +60,7 @@ module Net
60
60
  # :call-seq:
61
61
  # new(username, password, **options) -> auth_ctx
62
62
  # new(username:, password:, **options) -> auth_ctx
63
+ # new(authcid:, password:, **options) -> auth_ctx
63
64
  #
64
65
  # Creates an authenticator for one of the "+SCRAM-*+" SASL mechanisms.
65
66
  # Each subclass defines #digest to match a specific mechanism.
@@ -68,39 +69,47 @@ module Net
68
69
  #
69
70
  # === Parameters
70
71
  #
71
- # * #username ― Identity whose #password is used. Aliased as #authcid.
72
+ # * #authcid ― Identity whose #password is used.
73
+ #
74
+ # #username - An alias for #authcid.
72
75
  # * #password ― Password or passphrase associated with this #username.
73
- # * #authzid ― Alternate identity to act as or on behalf of. Optional.
74
- # * #min_iterations - Overrides the default value (4096). Optional.
76
+ # * _optional_ #authzid ― Alternate identity to act as or on behalf of.
77
+ # * _optional_ #min_iterations - Overrides the default value (4096).
75
78
  #
76
- # See the documentation on the corresponding attributes for more.
79
+ # Any other keyword parameters are quietly ignored.
77
80
  def initialize(username_arg = nil, password_arg = nil,
78
- username: nil, password: nil, authcid: nil, authzid: nil,
81
+ authcid: nil, username: nil,
82
+ authzid: nil,
83
+ password: nil, secret: nil,
79
84
  min_iterations: 4096, # see both RFC5802 and RFC7677
80
85
  cnonce: nil, # must only be set in tests
81
86
  **options)
82
87
  @username = username || username_arg || authcid or
83
88
  raise ArgumentError, "missing username (authcid)"
84
- [username, username_arg, authcid].compact.count == 1 or
85
- raise ArgumentError, "conflicting values for username (authcid)"
86
- @password = password || password_arg or
89
+ @password = password || secret || password_arg or
87
90
  raise ArgumentError, "missing password"
88
- [password, password_arg].compact.count == 1 or
89
- raise ArgumentError, "conflicting values for password"
90
91
  @authzid = authzid
91
92
 
92
93
  @min_iterations = Integer min_iterations
93
94
  @min_iterations.positive? or
94
95
  raise ArgumentError, "min_iterations must be positive"
96
+
95
97
  @cnonce = cnonce || SecureRandom.base64(32)
96
98
  end
97
99
 
98
100
  # Authentication identity: the identity that matches the #password.
101
+ #
102
+ # RFC-2831[https://tools.ietf.org/html/rfc2831] uses the term +username+.
103
+ # "Authentication identity" is the generic term used by
104
+ # RFC-4422[https://tools.ietf.org/html/rfc4422].
105
+ # RFC-4616[https://tools.ietf.org/html/rfc4616] and many later RFCs abbreviate
106
+ # this to +authcid+.
99
107
  attr_reader :username
100
108
  alias authcid username
101
109
 
102
110
  # A password or passphrase that matches the #username.
103
111
  attr_reader :password
112
+ alias secret password
104
113
 
105
114
  # Authorization identity: an identity to act as or on behalf of. The
106
115
  # identity form is application protocol specific. If not provided or
@@ -6,34 +6,48 @@
6
6
  # Google[https://developers.google.com/gmail/imap/xoauth2-protocol] and
7
7
  # Microsoft[https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth].
8
8
  #
9
- # This mechanism requires an OAuth2 +access_token+ which has been authorized
10
- # with the appropriate OAuth2 scopes to access IMAP. These scopes are not
11
- # standardized---consult each email service provider's documentation.
9
+ # This mechanism requires an OAuth2 access token which has been authorized
10
+ # with the appropriate OAuth2 scopes to access the user's services. Most of
11
+ # these scopes are not standardized---consult each service provider's
12
+ # documentation for their scopes.
12
13
  #
13
14
  # Although this mechanism was never standardized and has been obsoleted by
14
15
  # "+OAUTHBEARER+", it is still very widely supported.
15
16
  #
16
- # See Net::IMAP::SASL:: OAuthBearerAuthenticator.
17
+ # See Net::IMAP::SASL::OAuthBearerAuthenticator.
17
18
  class Net::IMAP::SASL::XOAuth2Authenticator
18
19
 
19
20
  # It is unclear from {Google's original XOAUTH2
20
21
  # documentation}[https://developers.google.com/gmail/imap/xoauth2-protocol],
21
22
  # whether "User" refers to the authentication identity (+authcid+) or the
22
- # authorization identity (+authzid+). It appears to behave as +authzid+.
23
+ # authorization identity (+authzid+). The authentication identity is
24
+ # established for the client by the OAuth token, so it seems that +username+
25
+ # must be the authorization identity.
23
26
  #
24
27
  # {Microsoft's documentation for shared
25
28
  # mailboxes}[https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#sasl-xoauth2-authentication-for-shared-mailboxes-in-office-365]
26
- # clearly indicate that the Office 365 server interprets it as the
29
+ # _clearly_ indicates that the Office 365 server interprets it as the
27
30
  # authorization identity.
31
+ #
32
+ # Although they _should_ validate that the token has been authorized to access
33
+ # the service for +username+, _some_ servers appear to ignore this field,
34
+ # relying only the identity and scope authorized by the token.
28
35
  attr_reader :username
29
36
 
37
+ # Note that, unlike most other authenticators, #username is an alias for the
38
+ # authorization identity and not the authentication identity. The
39
+ # authenticated identity is established for the client by the #oauth2_token.
40
+ alias authzid username
41
+
30
42
  # An OAuth2 access token which has been authorized with the appropriate OAuth2
31
43
  # scopes to use the service for #username.
32
44
  attr_reader :oauth2_token
45
+ alias secret oauth2_token
33
46
 
34
47
  # :call-seq:
35
48
  # new(username, oauth2_token, **) -> authenticator
36
49
  # new(username:, oauth2_token:, **) -> authenticator
50
+ # new(authzid:, oauth2_token:, **) -> authenticator
37
51
  #
38
52
  # Creates an Authenticator for the "+XOAUTH2+" SASL mechanism, as specified by
39
53
  # Google[https://developers.google.com/gmail/imap/xoauth2-protocol],
@@ -43,26 +57,30 @@ class Net::IMAP::SASL::XOAuth2Authenticator
43
57
  # === Properties
44
58
  #
45
59
  # * #username --- the username for the account being accessed.
60
+ #
61
+ # #authzid --- an alias for #username.
62
+ #
63
+ # Note that, unlike some other authenticators, +username+ sets the
64
+ # _authorization_ identity and not the _authentication_ identity. The
65
+ # authenticated identity is established for the client with the OAuth token.
66
+ #
46
67
  # * #oauth2_token --- An OAuth2.0 access token which is authorized to access
47
68
  # the service for #username.
48
69
  #
49
- # See the documentation for each attribute for more details.
50
- def initialize(user = nil, token = nil, username: nil, oauth2_token: nil, **)
51
- @username = username || user or
52
- raise ArgumentError, "missing username"
53
- @oauth2_token = oauth2_token || token or
70
+ # Any other keyword parameters are quietly ignored.
71
+ def initialize(user = nil, token = nil, username: nil, oauth2_token: nil,
72
+ authzid: nil, secret: nil, **)
73
+ @username = authzid || username || user or
74
+ raise ArgumentError, "missing username (authzid)"
75
+ @oauth2_token = oauth2_token || secret || token or
54
76
  raise ArgumentError, "missing oauth2_token"
55
- [username, user].compact.count == 1 or
56
- raise ArgumentError, "conflicting values for username"
57
- [oauth2_token, token].compact.count == 1 or
58
- raise ArgumentError, "conflicting values for oauth2_token"
59
77
  @done = false
60
78
  end
61
79
 
62
80
  # :call-seq:
63
81
  # initial_response? -> true
64
82
  #
65
- # +PLAIN+ can send an initial client response.
83
+ # +XOAUTH2+ can send an initial client response.
66
84
  def initial_response?; true end
67
85
 
68
86
  # Returns the XOAUTH2 formatted response, which combines the +username+