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

Add support for custom OAuth functions #1925

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Claimundefine
Copy link
Contributor

@Claimundefine Claimundefine commented Feb 26, 2025

What

Add custom OAuth implementation. Created new base class for bearer field provider, which will be called to retrieve all fields that need to be modified in the header.

Checklist

  • Contains customer facing changes? Including API/behavior changes
  • Did you add sufficient unit test and/or integration test coverage for this PR?
    • If not, please explain why it is not required

References

JIRA:

https://confluentinc.atlassian.net/browse/DGS-17473

Test & Review

Tested locally with OAuth for custom.

Open questions / Follow-ups

@confluent-cla-assistant
Copy link

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

@Claimundefine Claimundefine marked this pull request as ready for review February 26, 2025 22:42
@Copilot Copilot bot review requested due to automatic review settings February 26, 2025 22:42
@Claimundefine Claimundefine requested review from a team as code owners February 26, 2025 22:42

Choose a reason for hiding this comment

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

PR Overview

This PR adds support for custom OAuth functionality by introducing a common _BearerFieldProvider interface with implementations for OAuth, static tokens, and custom logic. It also updates existing tests and configuration handling to work with the new provider abstraction while removing legacy OAuth client tests.

Reviewed Changes

File Description
tests/schema_registry/test_bearer_field_provider.py Adds tests covering expiration, token retrieval, static and custom OAuth implementations.
tests/schema_registry/test_config.py Adds tests to validate custom bearer configuration handling.
src/confluent_kafka/schema_registry/schema_registry_client.py Refactors bearer auth handling by introducing _BearerFieldProvider and related classes, and adapts configuration accordingly.
tests/schema_registry/test_oauth_client.py Removes legacy OAuth client tests in favor of the new provider approach.

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (2)

tests/schema_registry/test_bearer_field_provider.py:95

  • [nitpick] The test for the custom OAuth client only asserts that get_bearer_fields() returns the same value on successive calls. Consider asserting specific expected fields from the custom function to improve test coverage.
def test_custom_oauth_client():

src/confluent_kafka/schema_registry/schema_registry_client.py:84

  • [nitpick] Consider renaming '_OAuthClient' to 'OAuthBearerFieldProvider' to better reflect its role as an implementation of _BearerFieldProvider for OAuth logic.
class _OAuthClient(_BearerFieldProvider):
@sonarqube-confluent
Copy link

Passed

Analysis Details

6 Issues

  • Bug 0 Bugs
  • Vulnerability 1 Vulnerability
  • Code Smell 5 Code Smells

Coverage and Duplications

  • Coverage 87.00% Coverage (62.00% Estimated after merge)
  • Duplications No duplication information (0.90% Estimated after merge)

Project ID: confluent-kafka-python

View in SonarQube

@Elmerboul
Copy link

Hi, a potential user of this functionality here 😁 Do you already have a (rough) estimate on when you plan to release this?

Copy link
Member

@rayokota rayokota left a comment

Choose a reason for hiding this comment

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

Thanks @Claimundefine , left some nits, otherwise looking good

@@ -62,7 +62,26 @@ def _urlencode(value: str) -> str:
VALID_AUTH_PROVIDERS = ['URL', 'USER_INFO']


class _OAuthClient:
class _BearerFieldProvider:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
class _BearerFieldProvider:
class _BearerFieldProvider(metaclass=abc.ABCMeta):

@@ -62,7 +62,26 @@ def _urlencode(value: str) -> str:
VALID_AUTH_PROVIDERS = ['URL', 'USER_INFO']


class _OAuthClient:
class _BearerFieldProvider:
def get_bearer_fields(self) -> dict:
Copy link
Member

Choose a reason for hiding this comment

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

@abc.abstractmethod
def get_bearer_fields(self) -> dict:

raise NotImplementedError


class _StaticFieldProvider(_BearerFieldProvider):
Copy link
Member

Choose a reason for hiding this comment

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

Add __init__ that takes a token and sets a local bearer_token member variable. Then you can remove the bearer_token member variable in the SR client.


class _StaticFieldProvider(_BearerFieldProvider):
def get_bearer_fields(self) -> dict:
return {}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return {}
return {'bearer.auth.token': self.bearer_token}

@@ -206,23 +228,28 @@ def __init__(self, conf: dict):
+ str(type(retries_max_wait_ms)))
self.retries_max_wait_ms = retries_max_wait_ms

self.oauth_client = None
self.bearer_field_provider = None
self.bearer_token = None
Copy link
Member

Choose a reason for hiding this comment

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

Remove

elif self.bearer_auth_credentials_source == 'STATIC_TOKEN':
if 'bearer.auth.token' not in conf_copy:
raise ValueError("Missing bearer.auth.token")
self.bearer_token = conf_copy.pop('bearer.auth.token')
self.bearer_field_provider = _StaticFieldProvider()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
self.bearer_field_provider = _StaticFieldProvider()
self.bearer_field_provider = _StaticFieldProvider(bearer_token)

if not isinstance(self.bearer_token, string_type):
raise TypeError("bearer.auth.token must be a str, not " + str(type(self.bearer_token)))
elif self.bearer_auth_credentials_source == "CUSTOM":
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
elif self.bearer_auth_credentials_source == "CUSTOM":
elif self.bearer_auth_credentials_source == 'CUSTOM':

Copy link
Member

Choose a reason for hiding this comment

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

For consistency

@Claimundefine
Copy link
Contributor Author

Hi, a potential user of this functionality here 😁 Do you already have a (rough) estimate on when you plan to release this?

HI @Elmerboul, the projected release date is end of March.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants