33
44from requests_oauthlib import OAuth2Session
55
6+ from pardner .services .utils import scope_as_set , scope_as_string
67from pardner .verticals import Vertical
78
89
@@ -47,6 +48,7 @@ def __init__(
4748 client_secret : str ,
4849 redirect_uri : str ,
4950 supported_verticals : set [Vertical ],
51+ state : Optional [str ] = None ,
5052 verticals : set [Vertical ] = set (),
5153 ) -> None :
5254 """
@@ -58,28 +60,42 @@ def __init__(
5860 :param client_secret: The `client_secret` paired to the `client_id`.
5961 :param redirect_uri: The registered callback URI.
6062 :param supported_verticals: The `Vertical`s that can be fetched on the service.
63+ :param state: State string used to prevent CSRF and identify flow.
6164 :param verticals: The `Vertical`s for which the transfer service has
6265 appropriate scope to fetch.
6366 """
64- self ._oAuth2Session = OAuth2Session (
65- client_id = client_id , redirect_uri = redirect_uri
66- )
6767 self ._client_secret = client_secret
6868 self ._supported_verticals = supported_verticals
6969 self ._service_name = service_name
7070 self ._verticals = verticals
71+ self ._oAuth2Session = OAuth2Session (
72+ client_id = client_id , redirect_uri = redirect_uri , state = state
73+ )
74+ self .scope = self .scope_for_verticals (verticals )
7175
7276 @property
7377 def name (self ) -> str :
7478 return self ._service_name
7579
7680 @property
7781 def scope (self ) -> set [str ]:
78- return self ._oAuth2Session .scope if self ._oAuth2Session .scope else set ()
82+ return (
83+ scope_as_set (self ._oAuth2Session .scope )
84+ if self ._oAuth2Session .scope
85+ else set ()
86+ )
7987
8088 @scope .setter
8189 def scope (self , new_scope : Iterable [str ]) -> None :
82- self ._oAuth2Session .scope = set (new_scope )
90+ """
91+ Sets the scope of the transfer service flow.
92+ Some services have specific requirements for the format of the scope
93+ string (e.g., scopes have to be comma separated, or `+` separated).
94+
95+ :param new_scope: The new scopes that should be set for the transfer
96+ service.
97+ """
98+ self ._oAuth2Session .scope = scope_as_string (new_scope )
8399
84100 @property
85101 def verticals (self ) -> set [Vertical ]:
@@ -118,22 +134,23 @@ def add_verticals(
118134 """
119135 new_verticals = set (verticals ) - self .verticals
120136 new_scopes = self .scope_for_verticals (new_verticals )
121- original_scopes : set [str ] = self .scope if self .scope else set ()
122137
123- if not new_scopes .issubset (original_scopes ) and not should_reauth :
138+ if not new_scopes .issubset (self . scope ) and not should_reauth :
124139 raise InsufficientScopeException (verticals , self .name )
125- elif not new_scopes .issubset (original_scopes ):
140+ elif not new_scopes .issubset (self . scope ):
126141 self .verticals = new_verticals | self .verticals
127142 del self ._oAuth2Session .access_token
128- self .scope = original_scopes | new_scopes
143+ self .scope = self . scope | new_scopes
129144 return False
130145
131146 self .verticals = new_verticals | self .verticals
132147 return True
133148
134- @abstractmethod
135149 def fetch_token (
136- self , code : Optional [str ] = None , authorization_response : Optional [str ] = None
150+ self ,
151+ code : Optional [str ] = None ,
152+ authorization_response : Optional [str ] = None ,
153+ include_client_id : bool = False ,
137154 ) -> dict [str , Any ]:
138155 """
139156 Once the end-user authorizes the application to access their data, the
@@ -147,20 +164,26 @@ def fetch_token(
147164 browser redirected to.
148165 :param authorization_response: the URL (with parameters) the end-user's browser
149166 redirected to after authorization.
167+ :param include_client_id: whether or not to send the client ID with the token request
150168
151169 :returns: the authorization URL and state, respectively.
152170 """
153- pass
171+ return self ._oAuth2Session .fetch_token (
172+ token_url = self ._token_url ,
173+ code = code ,
174+ authorization_response = authorization_response ,
175+ include_client_id = include_client_id ,
176+ client_secret = self ._client_secret ,
177+ )
154178
155- @abstractmethod
156179 def authorization_url (self ) -> tuple [str , str ]:
157180 """
158181 Builds the authorization URL and state. Once the end-user (i.e., resource owner)
159182 navigates to the authorization URL they can begin the authorization flow.
160183
161184 :returns: the authorization URL and state, respectively.
162185 """
163- pass
186+ return self . _oAuth2Session . authorization_url ( self . _authorization_url )
164187
165188 @abstractmethod
166189 def scope_for_verticals (self , verticals : Iterable [Vertical ]) -> set [str ]:
0 commit comments