Skip to content

Commit

Permalink
Merge pull request #7 from s7clarke10/feature/sdk_supported_oauth_hea…
Browse files Browse the repository at this point in the history
…ders

Feature/sdk supported oauth headers
  • Loading branch information
s7clarke10 authored Jul 24, 2023
2 parents e1a302a + 6bcf8aa commit adb41b5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "<3.12,>=3.7.1"
requests = "^2.25.1"
singer-sdk = "^0.26.0"
singer-sdk = "^0.30.0"
genson = "^1.2.2"
atomicwrites = "^1.4.0"
requests-aws4auth = "^1.2.3"
Expand Down
13 changes: 12 additions & 1 deletion tap_rest_api_msdk/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

import boto3
from requests_aws4auth import AWS4Auth
from singer_sdk.authenticators import APIKeyAuthenticator, BasicAuthenticator, BearerTokenAuthenticator, OAuthAuthenticator
from singer_sdk.authenticators import (
APIKeyAuthenticator,
BasicAuthenticator,
BearerTokenAuthenticator,
OAuthAuthenticator
)

class AWSConnectClient:
"""A connection class to AWS Resources"""
Expand Down Expand Up @@ -195,6 +200,11 @@ def select_authenticator(self) -> Any:
api_keys = my_config.get('api_keys', '')
self.http_auth = None

# Set http headers if headers are supplied
# Some OAUTH2 API's require headers to be supplied
# In the OAUTH request.
auth_headers = my_config.get('headers',None)

# Using API Key Authenticator, keys are extracted from api_keys dict
if auth_method == "api_key":
if api_keys:
Expand All @@ -220,6 +230,7 @@ def select_authenticator(self) -> Any:
auth_endpoint=my_config.get('access_token_url', ''),
oauth_scopes=my_config.get('scope', ''),
default_expiration=my_config.get('oauth_expiration_secs', ''),
oauth_headers=auth_headers,
)
# Using Bearer Token Authenticator
elif auth_method == "bearer_token":
Expand Down
27 changes: 16 additions & 11 deletions tap_rest_api_msdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class RestApiStream(RESTStream):

# Intialise self.http_auth used by prepare_request
http_auth = None
# Cache the authenticator using a Smart Singleton pattern
_authenticator = None

@property
def url_base(self) -> Any:
Expand All @@ -29,7 +31,6 @@ def url_base(self) -> Any:


@property
@cached
def authenticator(self) -> Any:
"""Calls an appropriate SDK Authentication method based on the the set auth_method
which is set via the config.
Expand All @@ -39,9 +40,8 @@ def authenticator(self) -> Any:
Note 1: Each auth method requires certain configuration to be present see README.md
for each auth methods configuration requirements.
Note 2: The cached decorator will have all calls to the authenticator use the
same instance logic to speed up processing. TODO: Examine if this affects OAuth2
callbacks and if logic is required for callback for expiring AWS STS tokens.
Note 2: Using Singleton Pattern on the autenticator for caching with a check
if an OAuth Token has expired and needs to be refreshed.
Raises:
ValueError: if the auth_method is unknown.
Expand All @@ -50,11 +50,16 @@ def authenticator(self) -> Any:
A SDK Authenticator or APIAuthenticatorBase if no auth_method supplied.
"""

stream_authenticator = select_authenticator(self)

if stream_authenticator:
return stream_authenticator
else:
return APIAuthenticatorBase(stream=self)

auth_method = self.config.get("auth_method",None)

if not self._authenticator:
self._authenticator = select_authenticator(self)
if not self._authenticator:
# No Auth Method, use default Authenticator
self._authenticator = APIAuthenticatorBase(stream=self)
elif auth_method == 'oauth':
if not self._authenticator.is_token_valid():
# Obtain a new OAuth token as it has expired
self._authenticator = select_authenticator(self)

return self._authenticator

0 comments on commit adb41b5

Please sign in to comment.