|
1 | 1 | # frozen_string_literal: true
|
2 | 2 |
|
| 3 | +# Authenticator for the "+XOAUTH2+" SASL mechanism. This mechanism was |
| 4 | +# originally created for GMail and widely adopted by hosted email providers. |
| 5 | +# +XOAUTH2+ has been documented by |
| 6 | +# Google[https://developers.google.com/gmail/imap/xoauth2-protocol] and |
| 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 | +# |
| 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. |
| 12 | +# |
| 13 | +# Although this mechanism was never standardized and has been obsoleted by |
| 14 | +# "+OAUTHBEARER+", it is still very widely supported. |
| 15 | +# |
| 16 | +# See Net::IMAP::SASL:: OAuthBearerAuthenticator. |
3 | 17 | class Net::IMAP::SASL::XOAuth2Authenticator
|
4 | 18 |
|
5 |
| - def initialize(user, oauth2_token) |
6 |
| - @user = user |
| 19 | + # It is unclear from {Google's original XOAUTH2 |
| 20 | + # documentation}[https://developers.google.com/gmail/imap/xoauth2-protocol], |
| 21 | + # whether "User" refers to the authentication identity (+authcid+) or the |
| 22 | + # authorization identity (+authzid+). It appears to behave as +authzid+. |
| 23 | + # |
| 24 | + # {Microsoft's documentation for shared |
| 25 | + # 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 |
| 27 | + # authorization identity. |
| 28 | + attr_reader :username |
| 29 | + |
| 30 | + # An OAuth2 access token which has been authorized with the appropriate OAuth2 |
| 31 | + # scopes to use the service for #username. |
| 32 | + attr_reader :oauth2_token |
| 33 | + |
| 34 | + # :call-seq: |
| 35 | + # :call-seq: |
| 36 | + # new(username, oauth2_token) -> authenticator |
| 37 | + # |
| 38 | + # Creates an Authenticator for the "+XOAUTH2+" SASL mechanism, as specified by |
| 39 | + # Google[https://developers.google.com/gmail/imap/xoauth2-protocol], |
| 40 | + # Microsoft[https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth] |
| 41 | + # and Yahoo[https://senders.yahooinc.com/developer/documentation]. |
| 42 | + # |
| 43 | + # === Properties |
| 44 | + # |
| 45 | + # * #username --- the username for the account being accessed. |
| 46 | + # * #oauth2_token --- An OAuth2.0 access token which is authorized to access |
| 47 | + # the service for #username. |
| 48 | + # |
| 49 | + # See the documentation for each attribute for more details. |
| 50 | + def initialize(username, oauth2_token) |
| 51 | + @username = username |
7 | 52 | @oauth2_token = oauth2_token
|
8 | 53 | end
|
9 | 54 |
|
| 55 | + # :call-seq: |
| 56 | + # initial_response? -> true |
| 57 | + # |
| 58 | + # +PLAIN+ can send an initial client response. |
10 | 59 | def initial_response?; true end
|
11 | 60 |
|
| 61 | + # Returns the XOAUTH2 formatted response, which combines the +username+ |
| 62 | + # with the +oauth2_token+. |
12 | 63 | def process(_data)
|
13 |
| - build_oauth2_string(@user, @oauth2_token) |
| 64 | + build_oauth2_string(@username, @oauth2_token) |
14 | 65 | end
|
15 | 66 |
|
16 | 67 | private
|
17 | 68 |
|
18 |
| - def build_oauth2_string(user, oauth2_token) |
19 |
| - format("user=%s\1auth=Bearer %s\1\1", user, oauth2_token) |
| 69 | + def build_oauth2_string(username, oauth2_token) |
| 70 | + format("user=%s\1auth=Bearer %s\1\1", username, oauth2_token) |
20 | 71 | end
|
21 | 72 |
|
22 | 73 | end
|
0 commit comments