Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1356 implements OAuth2 Client Credentials Flow #1357

Merged
merged 31 commits into from
Jun 24, 2024

Conversation

willi-mueller
Copy link
Collaborator

@willi-mueller willi-mueller commented May 14, 2024

Description

This PR implements OAuth2 Client Credentials Flow with access token refresh for server-to-server authorization.

Related Issues

Additional Context

Example usage:

import dlt

from rest_api import RESTAPIConfig, rest_api_source
from dlt.sources.helpers.rest_client.auth import OAuth2ClientCredentialsFlow
from dlt.sources.helpers.rest_client.paginators import JSONResponseCursorPaginator

class OAuth2Zoom(OAuth2ClientCredentials):
            """OAuth 2.0 as required by e.g. Zoom Video Communications, Inc."""

            def build_access_token_request(self) -> Dict[str, Any]:
                authentication: str = b64encode(
                    f"{self.client_id}:{self.client_secret}".encode()
                ).decode()
                return {
                    "headers": {
                        "Authorization": f"Basic {authentication}",
                        "Content-Type": "application/x-www-form-urlencoded",
                    },
                    "data": {
                        "grant_type": "account_credentials",
                        **self.access_token_request_data,
                    },
                }

zoom_auth = OAuth2ClientCredentialsHTTPBasic(
            access_token_url=dlt.secrets["sources.zoom.access_token_url"]
            client_id=dlt.secrets["sources.zoom.client_id"]
            client_secret=dlt.secrets["sources.zoom.client_secret"],
            access_token_request_data={
                "account_id": dlt.secrets["sources.zoom.account_id"],
            },
        )

config: RESTAPIConfig = {
    "client": {
        "base_url": "https://api.zoom.us/v2",
        "auth": zoom_auth,
        "paginator": JSONResponseCursorPaginator(
            cursor_path="response.next_page_token",
            cursor_param="next_page_token",
        ),
    },
    "resources": [
        "users",
        {
            "name": "meetings",
            "endpoint": {
                "path": "users/{user_id}/meetings",
                "params": {
                    "user_id": {
                        "type": "resolve",
                        "resource": "users",
                        "field": "id",
                    }
                },
            },
        },
    ],
}

zoom_source = rest_api_source(config)
pipeline = dlt.pipeline(pipeline_name="zoom_test", destination="duckdb", progress="log")
load_info = pipeline.run(zoom_source)

print(load_info)

Copy link

netlify bot commented May 14, 2024

Deploy Preview for dlt-hub-docs canceled.

Name Link
🔨 Latest commit 8da3672
🔍 Latest deploy log https://app.netlify.com/sites/dlt-hub-docs/deploys/66758b73d097170008956fbb

@willi-mueller
Copy link
Collaborator Author

willi-mueller commented May 14, 2024

Questions:

  1. Am I using @configspeccorrectly? Do I have to implement the __init__ in this way?
  2. make lint has many errors unrelated to this PR when invoked on my PC. How can I test if it lints properly?
  3. How to implement a test case? I have a running pipeline pasted into this PR but I'm unsure where to implement it in the dlt core. Can you help me?

Thank you!

@burnash burnash self-assigned this May 14, 2024
@burnash burnash added the enhancement New feature or request label May 14, 2024
@willi-mueller
Copy link
Collaborator Author

I'm doing more research right now on which OAuth sources would be covered by this implementation. So far, I have tested only with Zoom. I know that LinkedIn and Hivebrite would not work.

@willi-mueller willi-mueller marked this pull request as draft May 15, 2024 08:11
@willi-mueller willi-mueller force-pushed the 1356-oauth2-implicit branch 2 times, most recently from 2cd8d72 to 5f4b8ec Compare May 21, 2024 17:32
@willi-mueller willi-mueller marked this pull request as ready for review May 25, 2024 07:01
@willi-mueller willi-mueller changed the title #1356 implements OAuth2 implicit flow #1356 implements OAuth2 Two-legged flow May 29, 2024
@willi-mueller
Copy link
Collaborator Author

for the record: one user in slack reported that he used this OAuth2 implementation successfully for Hivebrite

https://hivebrite.com/documentation/api/admin#oauth-post

https://dlthub-community.slack.com/archives/C04DQA7JJN6/p1716812907076409?thread_ts=1715003601.550219&cid=C04DQA7JJN6

@burnash
Copy link
Collaborator

burnash commented Jun 5, 2024

Hey @willi-mueller, thanks again for the PR. Looks good in general. I'll help you with the tests, let me know if it's ok if I push to your branch.

@willi-mueller
Copy link
Collaborator Author

Hey @willi-mueller, thanks again for the PR. Looks good in general. I'll help you with the tests, let me know if it's ok if I push to your branch.

Yes, please go ahead and refactor and add tests, I'll learn from that <3
The branch is yours.

@burnash
Copy link
Collaborator

burnash commented Jun 17, 2024

@willi-mueller the CI is failing tests/sources/helpers/rest_client/test_client.py::TestRESTClient::test_oauth2_client_credentials_flow_wrong_client_id
Could you please take a look?

Copy link
Collaborator

@burnash burnash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

@willi-mueller
Copy link
Collaborator Author

This looks great!

Wonderful, thank you for the thorough checks and coaching. Could you please merge the PR? I am not authorized by the branch protection rule.

@burnash burnash added the ci from fork run ci workflows on a pr even if they are from a fork label Jun 24, 2024
@burnash burnash merged commit 934829b into dlt-hub:devel Jun 24, 2024
49 of 50 checks passed
@willi-mueller willi-mueller deleted the 1356-oauth2-implicit branch June 24, 2024 09:41
@willi-mueller willi-mueller changed the title #1356 implements OAuth2 Two-legged flow #1356 implements OAuth2 Client Credentials Flow Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci from fork run ci workflows on a pr even if they are from a fork enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement OAuth2 Client Credentials Flow
2 participants