trinodb / trinodb/trino-python-client

Make JWTAuthentication accept token providers to support token refresh

Open
#466 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
439
Forks
206
PR merge metrics
No merged PRs in 30d

Description

Describe the feature

Extend JWTAuthentication to support both static JWT tokens and JWT tokens dynamically produced by given Callable objects.

This extension aims to refresh JWT tokens in JWTAuthentication.

Context

We are currently trying to use JWT access tokens issued by Azure Entra ID (aka. Azure Active Directory) to authenticate clients (more precisely, DBT workflows running in Azure) accessing our Trino.

Retrieving access tokens from Entra ID is a straightforward process. We can accomplish this by using the TokenCredential implementations provided by the azure-identity package. For instance,

### "api://..." is the application URI of our Trino registered in Entra ID -> will appear as "aud" in JWT tokens.
scope = "api://xxxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx/.default"

credential = DefaultAzureCredential()
jwt_token = credential.get_token(scope).token

conn = connect(
    auth=JWTAuthentication(jwt_token)
    http_scheme="https",
    ...
)

A problem here is that there is no way to refresh tokens set to JWTAuthentication as the current version of JWTAuthentication accepts only a static token, and sets the token to requests.Session objects as a static auth header value.

For example, JWT tokens issued by Entra ID usually expire within 1 hour or less. Therefore, an application using JWTAuthentication will fail at a certain moment due to the expiration of access tokens unless the application frequently recreates the JWTAuthentication instance with a new token.

Proposal

Extend JWTAuthentication to accept both a static JWT token and a Callable object as the init argument.

https://github.com/trinodb/trino-python-client/blob/0.328.0/trino/auth.py#L146-L153

class JWTAuthentication(Authentication):

    def __init__(self, token: Union[str, Callable[[], str]]):
        if isinstance(token, str):
            self.token_provider = lambda : token
        else:
            self.token_provider = token

    def set_http_session(self, http_session: Session) -> Session:
        http_session.auth = _BearerAuth(self.token_provider)
        return http_session

We also need to extend _BearerAuth.
https://github.com/trinodb/trino-python-client/blob/0.328.0/trino/auth.py#L142

        r.headers["Authorization"] = "Bearer " + self.token_provider()

With this extension, we can rewrite the sample code above as follows:

conn = connect(
    auth=JWTAuthentication(lambda: credential.get_token(scope).token)
    http_scheme="https",
    ...
)

This code won't fail as the credential (DefaultAzureCredential) will automatically cache and refresh access tokens.

Describe alternatives you've considered

We have implemented a custom JWTAuthentication with this extension by ourselves. However, JWT token refresh is a common concern that can appear in various use case scenarios. It would be nice to have this extension as a part of the Trino Python client.

Are you willing to submit PR?
  • Yes I am willing to submit a PR!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in trino/auth.py at JWTAuthentication and _BearerAuth, the entry points linked in the issue. Verify that static strings and callable providers both produce the Authorization header at request time, including refreshed values; done means the proposed callable usage works without recreating JWTAuthentication.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, python
Domain
authentication
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.