Repository: trinodb/trino-python-client

Issue:
SQLAlchemy support for externalAuthentication
### Describe the feature

It'd be great to have SQLAlchemy support for the externalAuthentication query parameter since there are a few libraries that use SQLAlchemy underneath and sometimes passing a Python Class through the connection_args is not possible

### Describe alternatives you've considered

_No response_

### Are you willing to submit PR?

- [X] Yes I am willing to submit a PR!

Discussion:
cla-bot[bot]: Thank you for your pull request and welcome to the Trino community. We require contributors to sign our [Contributor License Agreement](https://github.com/trinodb/cla/raw/master/Trino%20Foundation%20Individual%20CLA.pdf), and we don't seem to have you on file. Continue to work with us on the review and improvements in this PR, and submit the signed CLA to cla@trino.io. Photos, scans, or digitally-signed PDF files are all suitable. Processing may take a few days. The CLA needs to be on file before we merge your changes. For more information, see https://github.com/trinodb/cla
IceS2: CLA should be good to go (=
hashhar: @cla-bot check
cla-bot[bot]: The cla-bot has been summoned, and re-checked this pull request!
esemeniuc: merge?
hashhar: Sorry for forgetting to come back to this. I'll just squash the commits and then merge this.

Thanks for your work @esemeniuc.
hashhar: Squashed the commits + reworded commit msg, will merge once CI is finished.

Patch:
diff --git a/trino/sqlalchemy/dialect.py b/trino/sqlalchemy/dialect.py
index febfac5..9a401d4 100644
--- a/trino/sqlalchemy/dialect.py
+++ b/trino/sqlalchemy/dialect.py
@@ -22,7 +22,12 @@ from sqlalchemy.engine.url import URL
 
 from trino import dbapi as trino_dbapi
 from trino import logging
-from trino.auth import BasicAuthentication, CertificateAuthentication, JWTAuthentication
+from trino.auth import (
+    BasicAuthentication,
+    CertificateAuthentication,
+    JWTAuthentication,
+    OAuth2Authentication,
+)
 from trino.dbapi import Cursor
 from trino.sqlalchemy import compiler, datatype, error
 
@@ -113,6 +118,10 @@ class TrinoDialect(DefaultDialect):
             kwargs["http_scheme"] = "https"
             kwargs["auth"] = CertificateAuthentication(unquote_plus(url.query['cert']), unquote_plus(url.query['key']))
 
+        if "externalAuthentication" in url.query:
+            kwargs["http_scheme"] = "https"
+            kwargs["auth"] = OAuth2Authentication()
+
         if "source" in url.query:
             kwargs["source"] = unquote_plus(url.query["source"])
         else:


Test patch:
diff --git a/tests/unit/sqlalchemy/test_dialect.py b/tests/unit/sqlalchemy/test_dialect.py
index c385ab9..413a6bb 100644
--- a/tests/unit/sqlalchemy/test_dialect.py
+++ b/tests/unit/sqlalchemy/test_dialect.py
@@ -4,7 +4,7 @@ from unittest import mock
 import pytest
 from sqlalchemy.engine.url import URL, make_url
 
-from trino.auth import BasicAuthentication
+from trino.auth import BasicAuthentication, OAuth2Authentication
 from trino.dbapi import Connection
 from trino.sqlalchemy import URL as trino_url
 from trino.sqlalchemy.dialect import (
@@ -296,3 +296,12 @@ def test_trino_connection_certificate_auth():
     assert isinstance(cparams['auth'], CertificateAuthentication)
     assert cparams['auth']._cert == cert
     assert cparams['auth']._key == key
+
+
+def test_trino_connection_oauth2_auth():
+    dialect = TrinoDialect()
+    url = make_url('trino://host/?externalAuthentication=true')
+    _, cparams = dialect.create_connect_args(url)
+
+    assert cparams['http_scheme'] == "https"
+    assert isinstance(cparams['auth'], OAuth2Authentication)