Skip to content

Allows user to specify grant_type in OAuthAuthenticator #19139

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

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions airbyte-cdk/python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.8.1
Low-code: Allow `grant_type` to be specified for OAuthAuthenticator

## 0.8.0
Low-code: Allow for request and response to be emitted as log messages

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DeclarativeOauth2Authenticator(AbstractOauth2Authenticator, DeclarativeAut
scopes (Optional[List[str]]): The scopes to request
token_expiry_date (Optional[Union[InterpolatedString, str]]): The access token expiration date
refresh_request_body (Optional[Mapping[str, Any]]): The request body to send in the refresh request
grant_type: The grant_type to request for access_token
"""

token_refresh_endpoint: Union[InterpolatedString, str]
Expand All @@ -45,6 +46,7 @@ class DeclarativeOauth2Authenticator(AbstractOauth2Authenticator, DeclarativeAut
access_token_name: Union[InterpolatedString, str] = "access_token"
expires_in_name: Union[InterpolatedString, str] = "expires_in"
refresh_request_body: Optional[Mapping[str, Any]] = None
grant_type: Union[InterpolatedString, str] = "refresh_token"

def __post_init__(self, options: Mapping[str, Any]):
self.token_refresh_endpoint = InterpolatedString.create(self.token_refresh_endpoint, options=options)
Expand All @@ -53,6 +55,7 @@ def __post_init__(self, options: Mapping[str, Any]):
self.refresh_token = InterpolatedString.create(self.refresh_token, options=options)
self.access_token_name = InterpolatedString.create(self.access_token_name, options=options)
self.expires_in_name = InterpolatedString.create(self.expires_in_name, options=options)
self.grant_type = InterpolatedString.create(self.grant_type, options=options)
self._refresh_request_body = InterpolatedMapping(self.refresh_request_body or {}, options=options)
self._token_expiry_date = (
pendulum.parse(InterpolatedString.create(self.token_expiry_date, options=options).eval(self.config))
Expand Down Expand Up @@ -81,6 +84,9 @@ def get_access_token_name(self) -> InterpolatedString:

def get_expires_in_name(self) -> InterpolatedString:
return self.expires_in_name.eval(self.config)

def get_grant_type(self) -> InterpolatedString:
return self.grant_type.eval(self.config)

def get_refresh_request_body(self) -> Mapping[str, Any]:
return self._refresh_request_body.eval(self.config)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,17 @@
},
"refresh_request_body": {
"type": "object"
},
"grant_type": {
"anyOf": [
{
"$ref": "#/definitions/InterpolatedString"
},
{
"type": "string"
}
],
"default": "refresh_token"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def build_refresh_request_body(self) -> Mapping[str, Any]:
Override to define additional parameters
"""
payload: MutableMapping[str, Any] = {
"grant_type": "refresh_token",
"grant_type": self.get_grant_type(),
"client_id": self.get_client_id(),
"client_secret": self.get_client_secret(),
"refresh_token": self.get_refresh_token(),
Expand Down Expand Up @@ -117,6 +117,10 @@ def get_expires_in_name(self) -> str:
@abstractmethod
def get_refresh_request_body(self) -> Mapping[str, Any]:
"""Returns the request body to set on the refresh request"""

@abstractmethod
def get_grant_type(self) -> str:
"""Returns grant_type specified for requesting access_token"""

@property
@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(
access_token_name: str = "access_token",
expires_in_name: str = "expires_in",
refresh_request_body: Mapping[str, Any] = None,
grant_type: str = "refresh_token",
):
self._token_refresh_endpoint = token_refresh_endpoint
self._client_secret = client_secret
Expand All @@ -34,6 +35,7 @@ def __init__(
self._access_token_name = access_token_name
self._expires_in_name = expires_in_name
self._refresh_request_body = refresh_request_body
self._grant_type = grant_type

self._token_expiry_date = token_expiry_date or pendulum.now().subtract(days=1)
self._access_token = None
Expand Down Expand Up @@ -61,6 +63,9 @@ def get_expires_in_name(self) -> str:

def get_refresh_request_body(self) -> Mapping[str, Any]:
return self._refresh_request_body

def get_grant_type(self) -> str:
return self._grant_type

def get_token_expiry_date(self) -> pendulum.DateTime:
return self._token_expiry_date
Expand Down
2 changes: 1 addition & 1 deletion airbyte-cdk/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

setup(
name="airbyte-cdk",
version="0.8.0",
version="0.8.1",
description="A framework for writing Airbyte Connectors.",
long_description=README,
long_description_content_type="text/markdown",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"token_expiry_date": pendulum.now().subtract(days=2).to_rfc3339_string(),
"custom_field": "in_outbound_request",
"another_field": "exists_in_body",
"grant_type": "some_grant_type",
}
options = {"refresh_token": "some_refresh_token"}

Expand Down Expand Up @@ -48,10 +49,11 @@ def test_refresh_request_body(self):
"scopes": ["no_override"],
},
options=options,
grant_type="{{ config['grant_type'] }}"
)
body = oauth.build_refresh_request_body()
expected = {
"grant_type": "refresh_token",
"grant_type": "some_grant_type",
"client_id": "some_client_id",
"client_secret": "some_client_secret",
"refresh_token": "some_refresh_token",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,12 @@ def test_refresh_request_body(self):
refresh_token="some_refresh_token",
scopes=["scope1", "scope2"],
token_expiry_date=pendulum.now().add(days=3),
grant_type="some_grant_type",
refresh_request_body={"custom_field": "in_outbound_request", "another_field": "exists_in_body", "scopes": ["no_override"]},
)
body = oauth.build_refresh_request_body()
expected = {
"grant_type": "refresh_token",
"grant_type": "some_grant_type",
"client_id": "some_client_id",
"client_secret": "some_client_secret",
"refresh_token": "some_refresh_token",
Expand Down
3 changes: 3 additions & 0 deletions docs/connector-development/config-based/source_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ definitions:
default: "expires_in"
refresh_request_body:
type: object
grant_type:
type: string
default: "refresh_token"
Paginator:
type: object
anyOf:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ OAuth authentication is supported through the `OAuthAuthenticator`, which requir
- access_token_name (Optional): The field to extract access token from in the response. Default: "access_token".
- expires_in_name (Optional): The field to extract expires_in from in the response. Default: "expires_in"
- refresh_request_body (Optional): The request body to send in the refresh request. Default: None
- grant_type (Optional): The parameter specified grant_type to request access_token. Default: "refresh_token"

Schema:

Expand Down Expand Up @@ -173,6 +174,9 @@ Schema:
default: "expires_in"
refresh_request_body:
type: object
grant_type:
type: string
default: "refresh_token"
```

Example:
Expand Down