Python exchangelib OAuth2 authentication failing

Viewed 1138

Since Microsoft has apparently EOL'd basic authentication for Exchange Web Services, I'm trying to convert my Python app to use OAuth2. Python 3.8, exchangelib 3.2.1, ms-exchange version unknown but recent. Relevant code follows:

from exchangelib import Credentials, Account, Message, Mailbox, ExtendedProperty, Configuration, \
                        OAuth2Credentials, OAuth2AuthorizationCodeCredentials, Identity, OAUTH2
from oauthlib.oauth2 import OAuth2Token

    credentials = OAuth2Credentials(client_id="xxxxxxxx-xxxx-etc", client_secret="xxxxxxxxxxxxx-etc",
                                    tenant_id="xxxxxxxx-xxxx-etc")
    config=Configuration(credentials=credentials, auth_type=OAUTH2)
    acct = Account(primary_smtp_address='testAddr@example.com', config=config, autodiscover=True)

The result:

ValueError: Auth type must be 'OAuth 2.0' for credentials type OAuth2Credentials
DEBUG:exchangelib.protocol:Server autodiscover.example.com: Closing sessions

The exception is being thrown at the beginning of BaseProtocol.create_oauth2_session() in protocol.py:

        if self.auth_type != OAUTH2:
            raise ValueError('Auth type must be %r for credentials type OAuth2Credentials' % OAUTH2)

Straightforward enough...except that I clearly specified auth_type=OAUTH2 in my code. Eventually I discovered that a second Configuration object is being created; the first with type OAUTH2 as expected, the second with type NTLM, and that's the one that create_oauth2_session is failing on. The second instance is carrying my credentials, but the service endpoint argument changes from None to autodiscover.example.com/Autodiscover/Autodiscover.xml. This makes sense as part of the autodiscover process (I think,) but why the second instance, and why is it changing the auth type?? I'm stumped. Any/all help is greatly appreciated.

1 Answers

This looks like a bug. This commit should have allowed OAuth for autodiscover but it apparently doesn't work for you. I would break out a debugger and find out where the auth_type value is getting reset. I don't have an OAuth-enabled EWS server, so I can't test this myself.

Related