Skip to content

Commit

Permalink
chore: oauth sdk implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
manisha1997 committed Jul 6, 2024
1 parent 691071d commit 6204eae
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 41 deletions.
Empty file removed twilio/http/BaseHttpClient.py
Empty file.
14 changes: 5 additions & 9 deletions twilio/http/bearer_token_http_client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime
import jwt

from twilio.base.version import Version
from twilio.http.orgs_token_manager import OrgTokenManager
from twilio.twilio_bearer_token_auth import TwilioBearerTokenAuth

Expand All @@ -9,22 +10,17 @@ class BearerTokenHTTPClient:
def __init__(self, orgs_token_manager: OrgTokenManager):
self.orgs_token_manager = orgs_token_manager

def get_headers(self):
headers = {}
def get_headers(self, version: Version):
if TwilioBearerTokenAuth.get_access_token() is None or self.is_token_expired(TwilioBearerTokenAuth.get_access_token()):
access_token = self.orgs_token_manager.fetch_access_token()
access_token = self.orgs_token_manager.fetch_access_token(version)
TwilioBearerTokenAuth.init(access_token)
else:
access_token = TwilioBearerTokenAuth.get_access_token()

headers.update({
'Authorization': 'Bearer {}'.format(access_token)
})

return headers
return access_token

def is_token_expired(self, token):
decoded_jwt = jwt.decode(token, options={"verify_signature": False})
decoded_jwt = jwt.decode(token, options={"verify_signature": True})
expires_at = decoded_jwt.get('exp')
# Add a buffer of 30 seconds
buffer_seconds = 30
Expand Down
20 changes: 9 additions & 11 deletions twilio/http/orgs_token_manager.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
from twilio.rest.preview_iam.organizations_openapi.token import TokenList
from twilio.http.http_client import TwilioHttpClient

class OrgTokenManager:
from twilio.base.version import Version
from twilio.rest.preview_iam.organizations.token import TokenList

class OrgTokenManager():
"""
Orgs Token Manager
"""
def __init__(self, grant_type: str, client_id: str, client_secret: str):
self.grant_type = grant_type
self.client_id = client_id
self.client_secret = client_secret

def __init__(self, grant_type: str, client_id: str, client_secret: str, code: str, redirect_uri: str, audience: str, refreshToken: str, scope: str):
def __init__(self, grant_type: str, client_id: str, client_secret: str, code: str = None, redirect_uri: str = None, audience: str = None, refreshToken: str = None, scope: str = None):
self.grant_type = grant_type
self.client_id = client_id
self.client_secret = client_secret
Expand All @@ -20,9 +17,9 @@ def __init__(self, grant_type: str, client_id: str, client_secret: str, code: st
self.refreshToken = refreshToken
self.scope = scope

def fetch_access_token(self):
token_list = TokenList()
return token_list.create(
def fetch_access_token(self, version: Version):
token_list = TokenList(version)
token_instance = token_list.create(
grant_type=self.grant_type,
client_id=self.client_id,
client_secret=self.client_secret,
Expand All @@ -31,3 +28,4 @@ def fetch_access_token(self):
audience=self.audience,
scope=self.scope
)
return token_instance.access_token
15 changes: 15 additions & 0 deletions twilio/http/token_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from twilio.base.version import Version
from twilio.http.orgs_token_manager import OrgTokenManager
class TokenManager:
org_token_manager = None

@classmethod
def init(cls, grant_type: str, client_id: str, client_secret: str, code: str = None, redirect_uri: str = None, audience: str = None, refreshToken: str = None, scope: str = None):
cls.org_token_manager = OrgTokenManager(grant_type, client_id, client_secret, code, redirect_uri, audience, refreshToken, scope)

@classmethod
def get_token_manager(cls, version: Version):
if cls.org_token_manager is None:
raise Exception("Token Manager not initialized")
cls.org_token_manager.version = version
return cls.org_token_manager
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
from decimal import Decimal
from typing import Any, Dict, List, Optional, Union, Iterator, AsyncIterator
from twilio.base import deserialize, serialize, values
import json

from twilio.base.instance_resource import InstanceResource
from twilio.base.list_resource import ListResource
from twilio.base.version import Version
from twilio.http.http_client import TwilioHttpClient



Expand Down Expand Up @@ -56,20 +54,21 @@ def __repr__(self) -> str:
:returns: Machine friendly representation
"""

return '<Twilio.PreviewIam.Organizations_openapi.TokenInstance>'
return '<Twilio.PreviewIam.Organizations.TokenInstance>'




class TokenList(ListResource):

def __init__(self):
def __init__(self, version: Version):
"""
Initialize the TokenList
:param version: Version that contains the resource
"""
super().__init__(version)


self._uri = '/token'
Expand Down Expand Up @@ -102,21 +101,60 @@ def create(self, grant_type: str, client_id: str, client_secret: Union[str, obje
'refresh_token': refresh_token,
'scope': scope,
})
headers = values.of({
'Content-Type': 'application/x-www-form-urlencoded'
})



payload = self._version.create(method='POST', uri=self._uri, data=data, headers=headers)

return TokenInstance(self._version, payload)

async def create_async(self, grant_type: str, client_id: str, client_secret: Union[str, object]=values.unset, code: Union[str, object]=values.unset, redirect_uri: Union[str, object]=values.unset, audience: Union[str, object]=values.unset, refresh_token: Union[str, object]=values.unset, scope: Union[str, object]=values.unset) -> TokenInstance:
"""
Asynchronously create the TokenInstance
:param grant_type: Grant type is a credential representing resource owner's authorization which can be used by client to obtain access token.
:param client_id: A 34 character string that uniquely identifies this OAuth App.
:param client_secret: The credential for confidential OAuth App.
:param code: JWT token related to the authorization code grant type.
:param redirect_uri: The redirect uri
:param audience: The targeted audience uri
:param refresh_token: JWT token related to refresh access token.
:param scope: The scope of token
:returns: The created TokenInstance
"""

data = values.of({
'grant_type': grant_type,
'client_id': client_id,
'client_secret': client_secret,
'code': code,
'redirect_uri': redirect_uri,
'audience': audience,
'refresh_token': refresh_token,
'scope': scope,
})
headers = values.of({
'Content-Type': 'application/x-www-form-urlencoded'
})


twilioHttpClient = TwilioHttpClient()
retries = 0
while retries < 5:
try:
response = twilioHttpClient.request(
'POST',
'https://preview-iam.twilio.com/v1/token',
data=data
)
if response.status_code == 401:
retries += 1
continue
return json.loads(response.content)['access_token']
except Exception as e:
if retries == 5:
raise e
continue

payload = await self._version.create_async(method='POST', uri=self._uri, data=data, headers=headers)

return TokenInstance(self._version, payload)




def __repr__(self) -> str:
"""
Provide a friendly representation
:returns: Machine friendly representation
"""
return '<Twilio.PreviewIam.Organizations.TokenList>'

0 comments on commit 6204eae

Please sign in to comment.