Skip to content

Commit ad40d0e

Browse files
jj-nilbodeesherifnada
authored andcommitted
Allows user to specify grant_type in OAuthAuthenticator (#19139)
Co-authored-by: Sherif A. Nada <[email protected]>
1 parent 61dc364 commit ad40d0e

File tree

9 files changed

+42
-3
lines changed

9 files changed

+42
-3
lines changed

airbyte-cdk/python/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 0.9.0
4+
Low-code: Allow `grant_type` to be specified for OAuthAuthenticator
5+
36
## 0.8.1
47
Low-code: Don't update cursor for non-record messages and fix default loader for connector builder manifests
58

airbyte-cdk/python/airbyte_cdk/sources/declarative/auth/oauth.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class DeclarativeOauth2Authenticator(AbstractOauth2Authenticator, DeclarativeAut
3131
scopes (Optional[List[str]]): The scopes to request
3232
token_expiry_date (Optional[Union[InterpolatedString, str]]): The access token expiration date
3333
refresh_request_body (Optional[Mapping[str, Any]]): The request body to send in the refresh request
34+
grant_type: The grant_type to request for access_token
3435
"""
3536

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

4951
def __post_init__(self, options: Mapping[str, Any]):
5052
self.token_refresh_endpoint = InterpolatedString.create(self.token_refresh_endpoint, options=options)
@@ -53,6 +55,7 @@ def __post_init__(self, options: Mapping[str, Any]):
5355
self.refresh_token = InterpolatedString.create(self.refresh_token, options=options)
5456
self.access_token_name = InterpolatedString.create(self.access_token_name, options=options)
5557
self.expires_in_name = InterpolatedString.create(self.expires_in_name, options=options)
58+
self.grant_type = InterpolatedString.create(self.grant_type, options=options)
5659
self._refresh_request_body = InterpolatedMapping(self.refresh_request_body or {}, options=options)
5760
self._token_expiry_date = (
5861
pendulum.parse(InterpolatedString.create(self.token_expiry_date, options=options).eval(self.config))
@@ -81,6 +84,9 @@ def get_access_token_name(self) -> InterpolatedString:
8184

8285
def get_expires_in_name(self) -> InterpolatedString:
8386
return self.expires_in_name.eval(self.config)
87+
88+
def get_grant_type(self) -> InterpolatedString:
89+
return self.grant_type.eval(self.config)
8490

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

airbyte-cdk/python/airbyte_cdk/sources/declarative/config_component_schema.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,17 @@
515515
},
516516
"refresh_request_body": {
517517
"type": "object"
518+
},
519+
"grant_type": {
520+
"anyOf": [
521+
{
522+
"$ref": "#/definitions/InterpolatedString"
523+
},
524+
{
525+
"type": "string"
526+
}
527+
],
528+
"default": "refresh_token"
518529
}
519530
}
520531
}

airbyte-cdk/python/airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def build_refresh_request_body(self) -> Mapping[str, Any]:
4747
Override to define additional parameters
4848
"""
4949
payload: MutableMapping[str, Any] = {
50-
"grant_type": "refresh_token",
50+
"grant_type": self.get_grant_type(),
5151
"client_id": self.get_client_id(),
5252
"client_secret": self.get_client_secret(),
5353
"refresh_token": self.get_refresh_token(),
@@ -117,6 +117,10 @@ def get_expires_in_name(self) -> str:
117117
@abstractmethod
118118
def get_refresh_request_body(self) -> Mapping[str, Any]:
119119
"""Returns the request body to set on the refresh request"""
120+
121+
@abstractmethod
122+
def get_grant_type(self) -> str:
123+
"""Returns grant_type specified for requesting access_token"""
120124

121125
@property
122126
@abstractmethod

airbyte-cdk/python/airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(
2525
access_token_name: str = "access_token",
2626
expires_in_name: str = "expires_in",
2727
refresh_request_body: Mapping[str, Any] = None,
28+
grant_type: str = "refresh_token",
2829
):
2930
self._token_refresh_endpoint = token_refresh_endpoint
3031
self._client_secret = client_secret
@@ -34,6 +35,7 @@ def __init__(
3435
self._access_token_name = access_token_name
3536
self._expires_in_name = expires_in_name
3637
self._refresh_request_body = refresh_request_body
38+
self._grant_type = grant_type
3739

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

6264
def get_refresh_request_body(self) -> Mapping[str, Any]:
6365
return self._refresh_request_body
66+
67+
def get_grant_type(self) -> str:
68+
return self._grant_type
6469

6570
def get_token_expiry_date(self) -> pendulum.DateTime:
6671
return self._token_expiry_date

airbyte-cdk/python/unit_tests/sources/declarative/auth/test_oauth.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"token_expiry_date": pendulum.now().subtract(days=2).to_rfc3339_string(),
2121
"custom_field": "in_outbound_request",
2222
"another_field": "exists_in_body",
23+
"grant_type": "some_grant_type",
2324
}
2425
options = {"refresh_token": "some_refresh_token"}
2526

@@ -48,10 +49,11 @@ def test_refresh_request_body(self):
4849
"scopes": ["no_override"],
4950
},
5051
options=options,
52+
grant_type="{{ config['grant_type'] }}"
5153
)
5254
body = oauth.build_refresh_request_body()
5355
expected = {
54-
"grant_type": "refresh_token",
56+
"grant_type": "some_grant_type",
5557
"client_id": "some_client_id",
5658
"client_secret": "some_client_secret",
5759
"refresh_token": "some_refresh_token",

airbyte-cdk/python/unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,12 @@ def test_refresh_request_body(self):
126126
refresh_token="some_refresh_token",
127127
scopes=["scope1", "scope2"],
128128
token_expiry_date=pendulum.now().add(days=3),
129+
grant_type="some_grant_type",
129130
refresh_request_body={"custom_field": "in_outbound_request", "another_field": "exists_in_body", "scopes": ["no_override"]},
130131
)
131132
body = oauth.build_refresh_request_body()
132133
expected = {
133-
"grant_type": "refresh_token",
134+
"grant_type": "some_grant_type",
134135
"client_id": "some_client_id",
135136
"client_secret": "some_client_secret",
136137
"refresh_token": "some_refresh_token",

docs/connector-development/config-based/source_schema.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ definitions:
222222
default: "expires_in"
223223
refresh_request_body:
224224
type: object
225+
grant_type:
226+
type: string
227+
default: "refresh_token"
225228
Paginator:
226229
type: object
227230
anyOf:

docs/connector-development/config-based/understanding-the-yaml-file/authentication.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ OAuth authentication is supported through the `OAuthAuthenticator`, which requir
133133
- access_token_name (Optional): The field to extract access token from in the response. Default: "access_token".
134134
- expires_in_name (Optional): The field to extract expires_in from in the response. Default: "expires_in"
135135
- refresh_request_body (Optional): The request body to send in the refresh request. Default: None
136+
- grant_type (Optional): The parameter specified grant_type to request access_token. Default: "refresh_token"
136137

137138
Schema:
138139

@@ -173,6 +174,9 @@ Schema:
173174
default: "expires_in"
174175
refresh_request_body:
175176
type: object
177+
grant_type:
178+
type: string
179+
default: "refresh_token"
176180
```
177181

178182
Example:

0 commit comments

Comments
 (0)