3636
3737class AuthProvider (AuthProviderBase ):
3838
39- AUTH_SERVER_URL = "https://login.live.com/oauth20_authorize.srf"
40- AUTH_TOKEN_URL = "https://login.live.com/oauth20_token.srf"
39+ MSA_AUTH_SERVER_URL = "https://login.live.com/oauth20_authorize.srf"
40+ MSA_AUTH_TOKEN_URL = "https://login.live.com/oauth20_token.srf"
4141
42- def __init__ (self , http_provider , client_id = None , scopes = None , access_token = None , session_type = None , loop = None ):
42+ def __init__ (self , http_provider , client_id = None , scopes = None , access_token = None , session_type = None , loop = None ,
43+ auth_server_url = None , auth_token_url = None ):
4344 """Initialize the authentication provider for authenticating
4445 requests sent to OneDrive
4546
@@ -50,8 +51,7 @@ def __init__(self, http_provider, client_id=None, scopes=None, access_token=None
5051 application
5152 scopes (list of str): Defaults to None, the scopes
5253 that are required for your application
53- access_token (str): Defaults to None, the access token
54- for your application
54+ access_token (str): Defaults to None. Not used in this implementation.
5555 session_type (:class:`SessionBase<onedrivesdk.session_base.SessionBase>`):
5656 Defaults to :class:`Session<onedrivesdk.session.Session>`,
5757 the implementation of SessionBase that stores your
@@ -63,13 +63,18 @@ def __init__(self, http_provider, client_id=None, scopes=None, access_token=None
6363 loop to use for all async requests. If none is provided,
6464 asyncio.get_event_loop() will be called. If using Python
6565 3.3 or below this does not need to be specified
66+ auth_server_url (str): URL where OAuth authentication can be performed. If
67+ None, defaults to OAuth for Microsoft Account.
68+ auth_token_url (str): URL where OAuth token can be redeemed. If None,
69+ defaults to OAuth for Microsoft Account.
6670 """
6771 self ._http_provider = http_provider
6872 self ._client_id = client_id
6973 self ._scopes = scopes
70- self ._access_token = access_token
7174 self ._session_type = Session if session_type is None else session_type
7275 self ._session = None
76+ self ._auth_server_url = self .MSA_AUTH_SERVER_URL if auth_server_url is None else auth_server_url
77+ self ._auth_token_url = self .MSA_AUTH_TOKEN_URL if auth_token_url is None else auth_token_url
7378
7479 if sys .version_info >= (3 , 4 , 0 ):
7580 import asyncio
@@ -106,66 +111,95 @@ def scopes(self, value):
106111 @property
107112 def access_token (self ):
108113 """Gets and sets the access_token for the
114+ :class:`AuthProvider`
115+
116+ Returns:
117+ str: The access token. Looks at the session to figure out what the access token is, since this
118+ class does not directly store the access token.
119+ """
120+ if self ._session is not None :
121+ return self ._session .access_token
122+ return None
123+
124+ @property
125+ def auth_server_url (self ):
126+ """Gets and sets the authorization server url for the
127+ :class:`AuthProvider`
128+
129+ Returns:
130+ str: Auth server url
131+ """
132+ return self ._auth_server_url
133+
134+ @auth_server_url .setter
135+ def auth_server_url (self , value ):
136+ self ._auth_server_url = value
137+
138+ @property
139+ def auth_token_url (self ):
140+ """Gets and sets the authorization token url for the
109141 AuthProvider
110142
111143 Returns:
112- str: The access token
144+ str: The auth token url
113145 """
114- return self ._access_token
146+ return self ._auth_token_url
115147
116- @access_token .setter
117- def access_token (self , value ):
118- self ._access_token = value
148+ @auth_token_url .setter
149+ def auth_token_url (self , value ):
150+ self ._auth_token_url = value
119151
120- def get_auth_url (self , redirect_uri ):
152+ def get_auth_url (self , redirect_uri , response_type = None ):
121153 """Build the auth url using the params provided
122154 and the auth_provider
123155
124156 Args:
125157 redirect_uri (str): The URI to redirect the response
126158 to
159+ response_type (str): Response type query param value.
160+ If not provided, defaults to 'code'. Should be either
161+ 'code' or 'token'.
127162 """
128163
129164 params = {
130165 "client_id" : self .client_id ,
131- "scope" : " " .join (self .scopes ),
132- "response_type" : "code" ,
166+ "response_type" : "code" if response_type is None else response_type ,
133167 "redirect_uri" : redirect_uri
134168 }
135- return "{}?{}" .format (self .AUTH_SERVER_URL , urlencode (params ))
169+ if self .scopes is not None :
170+ params ["scope" ] = " " .join (self .scopes )
171+
172+ return "{}?{}" .format (self ._auth_server_url , urlencode (params ))
136173
137- def authenticate (self , code , redirect_uri , client_secret = None , resource = None ):
138- """Takes in a code string, gets the access token,
139- and creates session property bag
174+ def authenticate (self , code , redirect_uri , client_secret , resource = None ):
175+ """Takes in a code, gets the access token and creates a session.
140176
141177 Args:
142178 code (str):
143- The code provided by the oauth provider
179+ The code provided by the oauth provider.
144180 redirect_uri (str): The URI to redirect the callback
145181 to
146- client_secret (str): Defaults to None, the client
147- secret of your app
182+ client_secret (str): The client secret of your app.
148183 resource (str): Defaults to None,The resource
149184 you want to access
150185 """
151-
152186 params = {
153- "code" : code ,
154187 "client_id" : self .client_id ,
155188 "redirect_uri" : redirect_uri ,
156- "grant_type" : "authorization_code" ,
157- "resource" : resource ,
189+ "client_secret" : client_secret ,
190+ "code" : code ,
191+ "response_type" : "code" ,
192+ "grant_type" : "authorization_code"
158193 }
159194
160- if client_secret is not None :
161- params ["client_secret" ] = client_secret
162195 if resource is not None :
163196 params ["resource" ] = resource
164197
198+ auth_url = self ._auth_token_url
165199 headers = {"Content-Type" : "application/x-www-form-urlencoded" }
166200 response = self ._http_provider .send (method = "POST" ,
167201 headers = headers ,
168- url = self . AUTH_TOKEN_URL ,
202+ url = auth_url ,
169203 data = params )
170204
171205 rcont = json .loads (response .content )
@@ -174,7 +208,7 @@ def authenticate(self, code, redirect_uri, client_secret=None, resource=None):
174208 rcont ["scope" ],
175209 rcont ["access_token" ],
176210 self .client_id ,
177- self .AUTH_TOKEN_URL ,
211+ self ._auth_token_url ,
178212 redirect_uri ,
179213 rcont ["refresh_token" ] if "refresh_token" in rcont else None ,
180214 client_secret )
@@ -231,6 +265,41 @@ def refresh_token(self):
231265 rcont ["access_token" ],
232266 rcont ["refresh_token" ])
233267
268+ def redeem_refresh_token (self , resource ):
269+ """Redeem a refresh token against a new resource. Used
270+ only by OneDrive for Business apps.
271+
272+ Args:
273+ resource (str): URL to resource to be accessed.
274+ Can be a 'serviceResourceId' value obtained from
275+ Discovery Service."""
276+ if self ._session is None :
277+ raise RuntimeError ("""Session must be authenticated
278+ before refreshing token.""" )
279+
280+ if self ._session .refresh_token is None :
281+ raise RuntimeError ("""Refresh token not present.""" )
282+
283+ params = {
284+ "client_id" : self ._session .client_id ,
285+ "redirect_uri" : self ._session .redirect_uri ,
286+ "client_secret" : self ._session .client_secret ,
287+ "refresh_token" : self ._session .refresh_token ,
288+ "grant_type" : "refresh_token" ,
289+ "resource" : resource
290+ }
291+
292+ headers = {"Content-Type" : "application/x-www-form-urlencoded" }
293+ response = self ._http_provider .send (method = "POST" ,
294+ headers = headers ,
295+ url = self .auth_token_url ,
296+ data = params )
297+ rcont = json .loads (response .content )
298+ self ._session .refresh_session (rcont ["expires_in" ],
299+ "" ,
300+ rcont ["access_token" ],
301+ rcont ["refresh_token" ])
302+
234303 def save_session (self , ** save_session_kwargs ):
235304 """Save the current session. Must have already
236305 obtained an access_token.
0 commit comments