@@ -14,13 +14,20 @@ module SASL
1414 class OAuthAuthenticator
1515 include GS2Header
1616
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"
1828 #
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.
2329 attr_reader :authzid
30+ alias username authzid
2431
2532 # Hostname to which the client connected.
2633 attr_reader :host
@@ -39,6 +46,7 @@ class OAuthAuthenticator
3946
4047 # The query string. (optional)
4148 attr_reader :qs
49+ alias query qs
4250
4351 # Stores the most recent server "challenge". When authentication fails,
4452 # this may hold information about the failure reason, as JSON.
@@ -47,29 +55,44 @@ class OAuthAuthenticator
4755 # Creates an RFC7628[https://tools.ietf.org/html/rfc7628] OAuth
4856 # authenticator.
4957 #
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>.
5164 #
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.
65+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
66+ # * _optional_ #username — An alias for #authzid.
5567 #
56- # * #authzid ― Identity to act as or on behalf of.
57- # * #host — Hostname to which the client connected.
58- # * #port — Service 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
68+ # Note that, unlike some other authenticators, the +username+ keyword
69+ # parameter sets the authorization identity and not the authentication
70+ # identity. The authenticated identity is established for the client
71+ # with the #oauth2_token.
72+ # * _optional_ #host — Hostname to which the client connected.
73+ # * _optional_ #port — Service port to which the client connected.
74+ # * _optional_ #mthd — HTTP method
75+ # * _optional_ #path — HTTP path data
76+ # * _optional_ #post — HTTP post data
77+ # * _optional_ #qs — HTTP query string
78+ # * _optional_ #query — An alias for #qs
6379 #
80+ # Any other keyword parameters are quietly ignored.
81+ #
82+ # Note that, unlike some other authenticators, the +username+ keyword
83+ # parameter sets the authorization identity and not the authentication
84+ # identity. The authenticated identity is established for the client
85+ # with the OAuth credential.
6486 def initialize ( authzid : nil , host : nil , port : nil ,
87+ username : nil , query : nil ,
6588 mthd : nil , path : nil , post : nil , qs : nil , **)
66- @authzid = authzid
89+ @authzid = authzid || username
6790 @host = host
6891 @port = port
6992 @mthd = mthd
7093 @path = path
7194 @post = post
72- @qs = qs
95+ @qs = qs || query
7396 @done = false
7497 end
7598
@@ -116,36 +139,48 @@ def authorization; raise "must be implemented by subclass" end
116139 # the bearer token.
117140 class OAuthBearerAuthenticator < OAuthAuthenticator
118141
119- # An OAuth2 bearer token, generally the access token.
142+ # An OAuth 2.0 bearer token. See {RFC-6750}[https://www.rfc-editor.org/rfc/rfc6750]
120143 attr_reader :oauth2_token
121144
122145 # :call-seq:
123- # new(oauth2_token, **options) -> authenticator
124- # new(oauth2_token:, **options) -> authenticator
146+ # new(oauth2_token:, authzid: nil, host: nil, port: nil, **options) -> authenticator
147+ # new(oauth2_token:, username: nil, host: nil, port: nil, **options) -> authenticator
148+ # new(oauth2_token, authzid: nil, host: nil, port: nil, **options) -> authenticator
149+ # new(authzid, oauth2_token, host: nil, port: nil, **options) -> authenticator
125150 #
126151 # Creates an Authenticator for the "+OAUTHBEARER+" SASL mechanism.
127152 #
128153 # Called by Net::IMAP#authenticate and similar methods on other clients.
129154 #
130- # === Options
131- #
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.
135- #
136- # * #oauth2_token — An 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.
142- #
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
148- raise ArgumentError , "missing oauth2_token"
155+ # ==== Parameters
156+ #
157+ # * #oauth2_token — An OAuth2 bearer token
158+ #
159+ # All other keyword parameters are passed to
160+ # {super}[rdoc-ref:OAuthAuthenticator::new]. The most common ones are:
161+ #
162+ # * _optional_ #authzid ― Authorization identity to act as or on behalf of.
163+ # * _optional_ #username — An alias for #authzid.
164+ #
165+ # Note that, unlike some other authenticators, the +username+ keyword
166+ # parameter sets the authorization identity and not the authentication
167+ # identity. The authenticated identity is established for the client
168+ # with the #oauth2_token.
169+ # * _optional_ #host — Hostname to which the client connected.
170+ # * _optional_ #port — Service port to which the client connected.
171+ #
172+ # Only +oauth2_token+ is required by this mechanism, but it is worth
173+ # noting that <b>application protocols are allowed to require</b>
174+ # #authzid (or other parameters, such as #host or #port) <b>as are
175+ # specific server implementations</b>. At the time this was written,
176+ # <em>Gmail and Yahoo Mail both required</em> +authzid+.
177+ #
178+ # See OAuthAuthenticator documentation for other parameters.
179+ def initialize ( arg1 = nil , arg2 = nil , oauth2_token : nil , **args , &blk )
180+ username , oauth2_token_arg = arg2 . nil? ? [ nil , arg1 ] : [ arg1 , arg2 ]
181+ super ( username : username , **args , &blk )
182+ @oauth2_token = oauth2_token || oauth2_token_arg
183+ @oauth2_token or raise ArgumentError , "missing oauth2_token"
149184 end
150185
151186 # :call-seq:
0 commit comments