1010import requests
1111
1212
13- class Client (object ):
14- # This low-level interface works. Yet you'll find those *Grant sub-classes
13+ class BaseClient (object ):
14+ # This low-level interface works. Yet you'll find its sub-class
1515 # more friendly to remind you what parameters are needed in each scenario.
1616 # More on Client Types at https://tools.ietf.org/html/rfc6749#section-2.1
1717 def __init__ (
@@ -74,7 +74,8 @@ def _get_token(
7474 # so we simply return it here, without needing to invent an exception.
7575 return resp .json ()
7676
77- def get_token_by_refresh_token (self , refresh_token , scope = None , ** kwargs ):
77+ def acquire_token_with_refresh_token (
78+ self , refresh_token , scope = None , ** kwargs ):
7879 return self ._get_token (
7980 "refresh_token" , refresh_token = refresh_token , scope = scope , ** kwargs )
8081
@@ -84,28 +85,33 @@ def _normalize_to_string(self, scope):
8485 return scope # as-is
8586
8687
87- class AuthorizationCodeGrant (Client ):
88- # Can be used by Confidential Client or Public Client.
89- # See https://tools.ietf.org/html/rfc6749#section-4.1.3
90-
88+ class Client (BaseClient ):
9189 def authorization_url (
92- self , redirect_uri = None , scope = None , state = None , ** kwargs ):
90+ self ,
91+ response_type , redirect_uri = None , scope = None , state = None , ** kwargs ):
9392 """Generate an authorization url to be visited by resource owner.
9493
94+ :param response_type:
95+ Must be "code" when you are using Authorization Code Grant.
96+ Must be "token" when you are using Implicit Grant
9597 :param redirect_uri: Optional. Server will use the pre-registered one.
9698 :param scope: It is a space-delimited, case-sensitive string.
9799 Some ID provider can accept empty string to represent default scope.
98100 """
101+ assert response_type in ["code" , "token" ]
99102 return self ._authorization_url (
100- 'code' , redirect_uri = redirect_uri , scope = scope , state = state ,
103+ response_type , redirect_uri = redirect_uri , scope = scope , state = state ,
101104 ** kwargs )
102105 # Later when you receive the response at your redirect_uri,
103106 # validate_authorization() may be handy to check the returned state.
104107
105- def get_token (self , code , redirect_uri = None , ** kwargs ):
106- """Get an access token.
108+ def acquire_token_with_authorization_code (
109+ self , code , redirect_uri = None , ** kwargs ):
110+ """Get a token via auhtorization code. a.k.a. Authorization Code Grant.
107111
108- See also https://tools.ietf.org/html/rfc6749#section-4.1.3
112+ This is typically used by a server-side app (Confidential Client),
113+ but it can also be used by a device-side native app (Public Client).
114+ See more detail at https://tools.ietf.org/html/rfc6749#section-4.1.3
109115
110116 :param code: The authorization code received from authorization server.
111117 :param redirect_uri:
@@ -118,42 +124,29 @@ def get_token(self, code, redirect_uri=None, **kwargs):
118124 'authorization_code' , code = code ,
119125 redirect_uri = redirect_uri , ** kwargs )
120126
121-
122- def validate_authorization (params , state = None ):
123- """A thin helper to examine the authorization being redirected back"""
124- if not isinstance (params , dict ):
125- params = parse_qs (params )
126- if params .get ('state' ) != state :
127- raise ValueError ('state mismatch' )
128- return params
129-
130-
131- class ImplicitGrant (Client ):
132- """Implicit Grant is used to obtain access tokens (but not refresh token).
133-
134- It is optimized for public clients known to operate a particular
135- redirection URI. These clients are typically implemented in a browser
136- using a scripting language such as JavaScript.
137- Quoted from https://tools.ietf.org/html/rfc6749#section-4.2
138- """
139- def authorization_url (self , redirect_uri = None , scope = None , state = None ):
140- return self ._authorization_url ('token' , ** locals ())
141-
142-
143- class ResourceOwnerPasswordCredentialsGrant (Client ): # Legacy Application flow
144- def get_token (self , username , password , scope = None , ** kwargs ):
127+ def acquire_token_with_username_password (
128+ self , username , password , scope = None , ** kwargs ):
129+ """The Resource Owner Password Credentials Grant, used by legacy app."""
145130 return self ._get_token (
146131 "password" , username = username , password = password , scope = scope ,
147132 ** kwargs )
148133
134+ def acquire_token_with_client_credentials (self , scope = None , ** kwargs ):
135+ '''Get token by client credentials. a.k.a. Client Credentials Grant,
136+ used by Backend Applications.
149137
150- class ClientCredentialGrant (Client ): # a.k.a. Backend Application flow
151- def get_token (self , scope = None , ** kwargs ):
152- '''Get token by client credential.
153-
154- You may want to also provide an optional client_secret parameter,
138+ You may want to explicitly provide an optional client_secret parameter,
155139 or you can provide such extra parameters as `default_body` during the
156140 class initialization.
157141 '''
158142 return self ._get_token ("client_credentials" , scope = scope , ** kwargs )
159143
144+
145+ def validate_authorization (params , state = None ):
146+ """A thin helper to examine the authorization being redirected back"""
147+ if not isinstance (params , dict ):
148+ params = parse_qs (params )
149+ if params .get ('state' ) != state :
150+ raise ValueError ('state mismatch' )
151+ return params
152+
0 commit comments