Skip to content

Commit cb690f5

Browse files
authored
Merge pull request #121 from QHivert/auth_xoauth2
Add xoauth2 auth mechanism
2 parents de75254 + 4b92c13 commit cb690f5

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ supported, with a simulated behaviour for server that do not support
133133
it.
134134

135135
For the ``AUTHENTICATE`` command, supported mechanisms are ``DIGEST-MD5``,
136-
``PLAIN``, ``LOGIN`` and ``OAUTHBEARER``.
136+
``PLAIN``, ``LOGIN``, ``OAUTHBEARER`` and ``XOAUTH2``.
137137

138138
Basic usage
139139
^^^^^^^^^^^

sievelib/managesieve.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"VERSION",
3232
]
3333

34-
SUPPORTED_AUTH_MECHS = ["DIGEST-MD5", "PLAIN", "LOGIN", "OAUTHBEARER"]
34+
SUPPORTED_AUTH_MECHS = ["DIGEST-MD5", "PLAIN", "LOGIN", "OAUTHBEARER", "XOAUTH2"]
3535

3636

3737
class Error(Exception):
@@ -421,6 +421,27 @@ def _oauthbearer_authentication(
421421
return True
422422
return False
423423

424+
def _xoauth2_authentication(
425+
self, login: bytes, password: bytes, authz_id: bytes = b""
426+
) -> bool:
427+
"""
428+
OAUTHBEARER authentication.
429+
430+
:param login: username
431+
:param password: access token
432+
:return: True on success, False otherwise.
433+
"""
434+
if isinstance(login, str):
435+
login = login.encode("utf-8")
436+
if isinstance(password, str):
437+
password = password.encode("utf-8")
438+
token = b"user=" + login + b",\001auth=Bearer " + password + b"\001\001"
439+
token = base64.b64encode(token)
440+
code, data = self.__send_command("AUTHENTICATE", [b"XOAUTH2", token])
441+
if code == "OK":
442+
return True
443+
return False
444+
424445
def __authenticate(
425446
self,
426447
login: str,

sievelib/tests/test_managesieve.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
CAPABILITIES = (
99
b'"IMPLEMENTATION" "Example1 ManageSieved v001"\r\n'
1010
b'"VERSION" "1.0"\r\n'
11-
b'"SASL" "PLAIN SCRAM-SHA-1 GSSAPI OAUTHBEARER"\r\n'
11+
b'"SASL" "PLAIN SCRAM-SHA-1 GSSAPI OAUTHBEARER XOAUTH2"\r\n'
1212
b'"SIEVE" "fileinto vacation"\r\n'
1313
b'"STARTTLS"\r\n'
1414
)
1515

1616
CAPABILITIES_WITHOUT_VERSION = (
1717
b'"IMPLEMENTATION" "Example1 ManageSieved v001"\r\n'
18-
b'"SASL" "PLAIN SCRAM-SHA-1 GSSAPI OAUTHBEARER"\r\n'
18+
b'"SASL" "PLAIN SCRAM-SHA-1 GSSAPI OAUTHBEARER XOAUTH2"\r\n'
1919
b'"SIEVE" "fileinto vacation"\r\n'
2020
b'"STARTTLS"\r\n'
2121
)
@@ -64,6 +64,11 @@ def test_auth_oauthbearer(self, mock_socket):
6464
mock_socket.return_value.recv.side_effect = (AUTHENTICATION,)
6565
self.assertTrue(self.client.connect("user", "token", authmech="OAUTHBEARER"))
6666

67+
def test_auth_xoauth2(self, mock_socket):
68+
"""Test XOAUTH2 mechanism."""
69+
mock_socket.return_value.recv.side_effect = (AUTHENTICATION,)
70+
self.assertTrue(self.client.connect("user", "token", authmech="XOAUTH2"))
71+
6772
def test_capabilities(self, mock_socket):
6873
"""Test capabilities command."""
6974
self.authenticate(mock_socket)

0 commit comments

Comments
 (0)