def extractRequestURL(request): # I am not sure why there isn't a thing that gets me the original # URI in the HTTP header and has to reconstruct all of this from # broken up pieces. actual_url = request.get('ACTUAL_URL', None) query_string = request.get('QUERY_STRING', None) if actual_url: result = actual_url if query_string: # XXX this is _seriously_ a pita. For some reason in some # circumstances we are not getting back the original encoded # values that we used to sign the request. This rectifies # that. try: urldecode(query_string) except ValueError: query_string = quote_plus(query_string, safe='=&;%+~') result += '?' + query_string else: # fallback. result = request.getURL() return result
def refresh_token(self, token_url, refresh_token=None, body='', auth=None, timeout=None, headers=None, verify=True, proxies=None, post_params=None, **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param timeout: Timeout of the request in seconds. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :param post_params: If True, sends body as url query string. :return: A token dict """ if not token_url: raise ValueError('No token endpoint set for auto_refresh.') if not is_secure_transport(token_url): raise InsecureTransportError() refresh_token = refresh_token or self.token.get('refresh_token') log.debug('Adding auto refresh key word arguments %s.', self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug('Prepared refresh token request body %s', body) if headers is None: headers = { 'Accept': 'application/json', 'Content-Type': ( 'application/x-www-form-urlencoded;charset=UTF-8' ), } if not post_params: r = self.post(token_url, data=dict(urldecode(body)), auth=auth, timeout=timeout, headers=headers, verify=verify, withhold_token=True, proxies=proxies) else: r = self.post(token_url, data=params(urldecode(body)), auth=auth, timeout=timeout, headers=headers, verify=verify, withhold_token=True, proxies=proxies) log.debug('Request to refresh token completed with status %s.', r.status_code) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['refresh_token_response'])) for hook in self.compliance_hook['refresh_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not 'refresh_token' in self.token: log.debug('No new refresh token given. Re-using old.') self.token['refresh_token'] = refresh_token return self.token
def callback(): """Retrieving an access token. After you've redirected from our provider to your callback URL, you'll have access to the auth code in the redirect URL, which we'll be using to get an access token. """ client = WebApplicationClient(client_id=CLIENT_ID) # Parse the response URI after the callback, with the same state we initially sent client.parse_request_uri_response(request.url, state=session["oauth_state"]) # Now we've access to the auth code code = client.code # Prepare request body to get the access token body = client.prepare_request_body( code=code, redirect_uri=REDIRECT_URI, include_client_id=False, scope=scope, ) # Basic HTTP auth by providing your client credentials auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET) # Making a post request to the TOKEN_URL endpoint r = requests.post(TOKEN_URL, data=dict(urldecode(body)), auth=auth) # Parse the response to get the token and store it in session token = client.parse_request_body_response(r.text, scope=scope) session["access_token"] = token return redirect("/home")
def __call__(self, response): """Hook is required to be callable""" req_params = {k: v for k, v in urldecode(response.request.body)} code = req_params["code"] # this is the unique param self.mapping[code] = response.json() return response
def parse_authorization_response(self, url: str) -> Dict[str, str]: token = dict(urldecode(urlparse(url).query)) self.oauth_client.resource_owner_key = token['oauth_token'] self.oauth_client.verifier = token['oauth_verifier'] return token
async def fetch_access_token(self, verifier: Optional[str] = None) -> Dict[str, str]: if verifier: self.oauth_client.verifier = verifier if not getattr(self.oauth_client, 'verifier', None): raise ValueError('No client verifier set.') # TODO: implement own exceptions log.debug(f'Fetching access token...') _, signed_headers, _ = self.oauth_client.sign(self.access_token_url, 'POST') log.debug(f'Signed headers: {signed_headers}') resp = await self.session.post(self.access_token_url, headers=signed_headers) log.debug(f'Response: {resp.status} {resp.reason}') log.debug(f'To: {resp.method} {resp.real_url.human_repr()}') log.debug(f'Requested as: {resp.request_info.method} {resp.request_info.real_url.human_repr()}') log.debug(f'Request headers: {resp.request_info.headers}') token_raw = await resp.text() log.debug(f'Token response: {token_raw}') token = dict(urldecode(token_raw)) self.oauth_client.resource_owner_key = token['oauth_token'] self.oauth_client.resource_owner_secret = token['oauth_token_secret'] # Unset verifier self.oauth_client.verifier = None return token
def refresh_token(self, token_url, refresh_token=None, body='', **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError('No token endpoint set for auto_refresh.') if not token_url.startswith('https://'): raise InsecureTransportError() # Need to nullify token to prevent it from being added to the request refresh_token = refresh_token or self.token.get('refresh_token') self.token = {} kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) r = self.post(token_url, data=dict(urldecode(body))) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not 'refresh_token' in self.token: self.token['refresh_token'] = refresh_token return self.token
def fetch_token(self, token_url, code=None, authorization_response=None, body='', username=None, password=None, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url.startswith('https://'): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self.state) code = self._client.code body = self._client.prepare_request_body(code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) # (ib-lundgren) All known, to me, token requests use POST. r = self.post(token_url, data=dict(urldecode(body)), headers={'Accept': 'application/json'}) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token return self.token
def refresh_token(self): refresh_token = self.token.get('refresh_token') body = self.oauth_client.prepare_refresh_body( body='', refresh_token=refresh_token, scope=self.scope, client_id=self.client_id, client_secret=self.client_secret) response = self.request( 'POST', self.token_url, headers={ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', }, data=dict(urldecode(body)), auth=httpx.BasicAuth(self.client_id, self.client_secret), withhold_token=True) self.token = self.oauth_client.parse_request_body_response( response.text, scope=self.scope) if 'refresh_token' not in self.token: self.token['refresh_token'] = refresh_token return self.token
def refresh_token(self, token_url, refresh_token=None, body='', auth=None, timeout=None, headers=None, verify=True, **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param timeout: Timeout of the request in seconds. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError('No token endpoint set for auto_refresh.') if not is_secure_transport(token_url): raise InsecureTransportError() # Need to nullify token to prevent it from being added to the request refresh_token = refresh_token or self.token.get('refresh_token') self.token = {} log.debug('Adding auto refresh key word arguments %s.', self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug('Prepared refresh token request body %s', body) if headers is None: headers = { 'Accept': 'application/json', 'Content-Type': ( 'application/x-www-form-urlencoded;charset=UTF-8' ), } r = self.post(token_url, data=dict(urldecode(body)), auth=auth, timeout=timeout, headers=headers, verify=verify) log.debug('Request to refresh token completed with status %s.', r.status_code) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['refresh_token_response'])) r.raise_for_status() for hook in self.compliance_hook['refresh_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not 'refresh_token' in self.token: log.debug('No new refresh token given. Re-using old.') self.token['refresh_token'] = refresh_token return self.token
def _compliance_fix(r): token = dict(urldecode(r.text)) expires = token.get('expires') if expires is not None: token['expires_in'] = expires token['token_type'] = 'Bearer' r._content = dumps(token) return r
def _fetch_token(self, url): request = self.get(url) if(not(isinstance(request,dict) and request.has_key('error'))): token = dict(urldecode(request)) self._populate_attributes(token) return token return request
def _compliance_fix(r): token = dict(urldecode(r.text)) expires = token.get("expires") if expires is not None: token["expires_in"] = expires token["token_type"] = "Bearer" r._content = dumps(token) return r
def fetch_token( self, token_url, code=None, authorization_response=None, body="", auth=None, username=None, password=None, **kwargs ): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self._state) code = self._client.code elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError("Please supply either code or " "authorization_code parameters.") body = self._client.prepare_request_body( code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs ) # (ib-lundgren) All known, to me, token requests use POST. r = self.post(token_url, data=dict(urldecode(body)), headers={"Accept": "application/json"}, auth=auth) log.debug("Prepared fetch token request body %s", body) log.debug("Request to fetch token completed with status %s.", r.status_code) log.debug("Response headers were %s and content %s.", r.headers, r.text) log.debug("Invoking %d token response hooks.", len(self.compliance_hook["access_token_response"])) for hook in self.compliance_hook["access_token_response"]: log.debug("Invoking hook %s.", hook) r = hook(r) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token log.debug("Obtained token %s.", self.token) return self.token
def test_urldecode(self): self.assertItemsEqual(urldecode(''), []) self.assertItemsEqual(urldecode('='), [('', '')]) self.assertItemsEqual(urldecode('%20'), [(' ', '')]) self.assertItemsEqual(urldecode('+'), [(' ', '')]) self.assertItemsEqual(urldecode('c2'), [('c2', '')]) self.assertItemsEqual(urldecode('c2='), [('c2', '')]) self.assertItemsEqual(urldecode('foo=bar'), [('foo', 'bar')]) self.assertItemsEqual(urldecode('foo_%20~=.bar-'), [('foo_ ~', '.bar-')]) self.assertItemsEqual(urldecode('foo=1,2,3'), [('foo', '1,2,3')]) self.assertItemsEqual(urldecode('foo=bar.*'), [('foo', 'bar.*')]) self.assertRaises(ValueError, urldecode, 'foo bar') self.assertRaises(ValueError, urldecode, '?') self.assertRaises(ValueError, urldecode, '%R') self.assertRaises(ValueError, urldecode, '%RA') self.assertRaises(ValueError, urldecode, '%AR') self.assertRaises(ValueError, urldecode, '%RR')
def get_access_token(self, callback_uri, request_token): """ Returns access token Third and last step of OAuth1 """ verifier = dict(urldecode(urlparse.urlparse(callback_uri).query)) self.client.verifier = verifier.get('oauth_verifier') self.client.resource_owner_key = request_token.get('oauth_token') self.client.resource_owner_secret = request_token.get('oauth_token_secret') uri, headers, body = self.client.sign(self.access_token_url) response = requests.request(self.token_method, uri, headers=headers, data=body) self.client.verifier = None response.raise_for_status() token = dict(urldecode(response.text)) self.set_token(token) return self.normalize_token_data(token)
def sign_post_parameters(self, url=None): client = Client(self.service.consumer_key, client_secret=self.service.consumer_secret, signature_method=SIGNATURE_HMAC, signature_type=SIGNATURE_TYPE_BODY) uri, headers, body = client.sign(url or self.service.url, http_method="POST", body=self.parameters, headers={"Content-Type": "application/x-www-form-urlencoded"}) return urldecode(body)
def sign_post_parameters(self, url=None): client = Client(self.service.consumer_key, client_secret=self.service.consumer_secret, signature_method=SIGNATURE_HMAC, signature_type=SIGNATURE_TYPE_BODY) uri, headers, body = client.sign(self._get_url(url), http_method="POST", body=self.parameters, headers={"Content-Type": "application/x-www-form-urlencoded"}) return urldecode(body)
def refresh_token( self, token_url, refresh_token=None, body="", auth=None, timeout=None, headers=None, verify=True, **kwargs ): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param timeout: Timeout of the request in seconds. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError("No token endpoint set for auto_refresh.") if not is_secure_transport(token_url): raise InsecureTransportError() refresh_token = refresh_token or self.token.get("refresh_token") log.debug("Adding auto refresh key word arguments %s.", self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug("Prepared refresh token request body %s", body) if headers is None: headers = { "Accept": "application/json", "Content-Type": ("application/x-www-form-urlencoded;charset=UTF-8"), } r = self.post( token_url, data=dict(urldecode(body)), auth=auth, timeout=timeout, headers=headers, verify=verify, withhold_token=True, ) log.debug("Request to refresh token completed with status %s.", r.status_code) log.debug("Response headers were %s and content %s.", r.headers, r.text) log.debug("Invoking %d token response hooks.", len(self.compliance_hook["refresh_token_response"])) for hook in self.compliance_hook["refresh_token_response"]: log.debug("Invoking hook %s.", hook) r = hook(r) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not "refresh_token" in self.token: log.debug("No new refresh token given. Re-using old.") self.token["refresh_token"] = refresh_token return self.token
def fetch_token(self, token_url, code=None, authorization_response=None, body='', auth=None, username=None, password=None, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self._state) code = self._client.code elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError('Please supply either code or ' 'authorization_code parameters.') body = self._client.prepare_request_body(code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) # (ib-lundgren) All known, to me, token requests use POST. r = self.post(token_url, data=dict(urldecode(body)), headers={'Accept': 'application/json'}, auth=auth) log.debug('Prepared fetch token request body %s', body) log.debug('Request to fetch token completed with status %s.', r.status_code) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['access_token_response'])) for hook in self.compliance_hook['access_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token log.debug('Obtained token %s.', self.token) return self.token
def _fetch_token(self, url): self.writeLog("Function: ---> fetch_token") self.writeLog("URL: " + url) self.writeLog("METHOD: GET") request = self.get(url) if(not(isinstance(request,dict) and request.has_key('error'))): token = dict(urldecode(request)) self._populate_attributes(token) return token return request
def _fetch_token(self, url): self.writeLog("Function: ---> fetch_token") self.writeLog("URL: " + url) self.writeLog("METHOD: GET") request = self.get(url) if (not (isinstance(request, dict) and request.has_key('error'))): token = dict(urldecode(request)) self._populate_attributes(token) return token return request
def get_request_token(self, redirect_uri): """ Retrieve oauth token and token secret First step of OAuth1 """ self.client.callback_uri = redirect_uri uri, headers, body = self.client.sign(self.request_token_url) response = requests.request(self.token_method, uri, headers=headers, data=body) response.raise_for_status() return dict(urldecode(response.text))
def _fetch_token(self, url, oauth_session, **request_kwargs): r = oauth_session.get(url, **request_kwargs) if r.status_code >= 400: error = 'Token request failed with code %s, response was \'%s\'.' raise TokenRequestDenied(error % (r.status_code, r.text), r) try: token = dict(urldecode(r.text.strip())) except ValueError as e: raise ValueError('Unable to decode token from token response. This is commonly caused by an unsuccessful request where a non urlencoded error message is returned. The decoding error was %s' % e) oauth_session._populate_attributes(token) return token
def _raise_on_bad_post_request(self, request): """Raise if invalid POST request received """ if request.http_method.upper() == 'POST': query_params = CaseInsensitiveDict( dict(urldecode(request.uri_query))) for key in query_params: if key not in OAUTHLIB_ALLOWED_POST_QUERY_PARAMS: raise InvalidRequestError( request=request, description=( 'URL query parameters are not allowed for key {key}' .format(key=key)))
def refresh_token(self, token_url, refresh_token=None, body='', auth=None, **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError('No token endpoint set for auto_refresh.') if not is_secure_transport(token_url): raise InsecureTransportError() # Need to nullify token to prevent it from being added to the request refresh_token = refresh_token or self.token.get('refresh_token') self.token = {} log.debug('Adding auto refresh key word arguments %s.', self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug('Prepared refresh token request body %s', body) r = self.post(token_url, data=dict(urldecode(body)), auth=auth) log.debug('Request to refresh token completed with status %s.', r.status_code) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['refresh_token_response'])) for hook in self.compliance_hook['refresh_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not 'refresh_token' in self.token: log.debug('No new refresh token given. Re-using old.') self.token['refresh_token'] = refresh_token return self.token
def fake_refresh_check_body_and_connection_params(r, **kwargs): if "/refresh" in r.url: self.assertEqual('proxy.b', kwargs['proxies']['https']) data = dict(urldecode(r.body)) self.assertDictEqual( { 'grant_type': 'refresh_token', 'refresh_token': 'sldvafkjw34509s8dfsdf', 'extra': 'spam' }, data) resp = mock.MagicMock() resp.text = json.dumps(self.token) return resp
def _compliance_fix(r): # Facebook returns urlencoded token, or json on error. Skip # compliance fix if we can't urldecode. try: token = dict(urldecode(r.text)) except ValueError: return r expires = token.get('expires') if expires is not None: token['expires_in'] = expires token['token_type'] = 'Bearer' r._content = dumps(token) return r
def get_token(): # imaginary API call to get token flickr = "https://www.flickr.com/services" REQUEST_TOKEN_URL = "https://www.flickr.com/services/oauth/request_token" AUTHORIZE_URL = "https://www.flickr.com/services/oauth/authorize" ACCESS_TOKEN_URL = "https://www.flickr.com/services/oauth/access_token" SET_LICENSE_URL = "https://www.flickr.com/services/rest/?method=flickr.photos.licenses.setLicense" # Get a request token oauth = OAuth1(config.API_KEY, config.SECRET) fetch_response = requests.post(REQUEST_TOKEN_URL, data={'oauth_callback': 'oob'}, auth=oauth) token = dict(urldecode(fetch_response.text.strip())) # Open a browser at the authentication URL authorize_url = "%s?oauth_token=%s&perms=%s" % ( AUTHORIZE_URL, token['oauth_token'], 'write') webbrowser.open_new_tab(authorize_url) # Get the verifier code from the user verifier = str(input('Verifier code: ')) # Trade the request token for an access token oauth = OAuth1(config.API_KEY, config.API_SECRET, resource_owner_key=token['oauth_token'], resource_owner_secret=token['oauth_token_secret'], verifier=verifier) fetch_response = requests.post(url=ACCESS_TOKEN_URL, auth=oauth) resp = dict(urldecode(fetch_response.text.strip())) save_token_to_file(resp['oauth_token'], resp['oauth_token_secret']) return (resp['oauth_token'], resp['oauth_token_secret'])
def fetch_token(self, token_url, code=None, authorization_response=None, body='', username=None, password=None, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url.startswith('https://'): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self.state) code = self._client.code body = self._client.prepare_request_body( code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) # (ib-lundgren) All known, to me, token requests use POST. r = self.post(token_url, data=dict(urldecode(body)), headers={'Accept': 'application/json'}) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token return self.token
def test_access_token_query_params(self): client = oauth1.Client(CLIENT_KEY, client_secret=CLIENT_SECRET, signature_type=SIGNATURE_TYPE_QUERY, signature_method=SIGNATURE_PLAINTEXT, resource_owner_key='V7jictT3VGpSG7IAkiY2F9naaQ0bRe', resource_owner_secret='h4x6lTb5UIgCFt0UOy1VJ0uQgcY68h', verifier='69qjCUfvYp3LjmgBJfz0FN9EMVOp6m') url = BASE_URL + ACCESS_TOKEN_ENDPOINT uri, headers, _ = client.sign(url, http_method='GET') req = urllib2.Request(str(uri), headers=headers) resp = urllib2.urlopen(req) data = resp.read() decoded_data = urldecode(data) oauth_response = dict(decoded_data) assert 'oauth_token' in oauth_response and 'oauth_token_secret' in oauth_response
def __test_request_token_headers_params(self): client = oauth1.Client(CLIENT_KEY, client_secret=CLIENT_SECRET, signature_type=SIGNATURE_TYPE_AUTH_HEADER, signature_method=SIGNATURE_PLAINTEXT, callback_uri='http://localhost/callback') url = BASE_URL + REQUEST_TOKEN_ENDPOINT uri, headers, _ = client.sign(url, http_method='GET') r = requests.get(uri, headers=headers) if r.status_code != 200: assert False decoded_data = urldecode(r.text) oauth_response = dict(decoded_data) assert 'oauth_token' in oauth_response and 'oauth_token_secret' in oauth_response
def refresh_token(self): """Step 3: obtains a new access_token from the the refresh token obtained in step 2. the token is internally saved """ ##the method in oauth does not allow a custom header (issue created #182) ## in the mean time here is a request from the ground up #out = self.oauth.refresh_token(self.refresh_token_url, #refresh_token=self.token['refresh_token'], #kwarg=self.auth_header) auth = OAuth2Session(self.client_id) body = auth._client.prepare_refresh_body(refresh_token=self.token['refresh_token']) r = auth.post(self.refresh_token_url, data=dict(urldecode(body)), verify=True,headers=self.auth_header) auth._client.parse_request_body_response(r.text, scope=self.oauth.scope) self.oauth.token = auth._client.token self.token = auth._client.token return(self.token)
def parse_authorization_response(self, url): """Extract parameters from the post authorization redirect response URL. :param url: The full URL that resulted from the user being redirected back from the OAuth provider to you, the client. :returns: A dict of parameters extracted from the URL. >>> redirect_response = 'https://127.0.0.1/callback?oauth_token=kjerht2309uf&oauth_token_secret=lsdajfh923874&oauth_verifier=w34o8967345' >>> oauth_session = OAuth1Session('client-key', client_secret='secret') >>> oauth_session.parse_authorization_response(redirect_response) { 'oauth_token: 'kjerht2309u', 'oauth_token_secret: 'lsdajfh923874', 'oauth_verifier: 'w34o8967345', } """ token = dict(urldecode(urlparse(url).query)) self._populate_attributes(token) return token
def __test_request_token_body_params(self): client = oauth1.Client(CLIENT_KEY, client_secret=CLIENT_SECRET, signature_type=SIGNATURE_TYPE_BODY, signature_method=SIGNATURE_PLAINTEXT, callback_uri='oob') headers = {'Content-Type': 'application/x-www-form-urlencoded'} url = BASE_URL + REQUEST_TOKEN_ENDPOINT uri, headers, body = client.sign(url, headers=headers, http_method='POST', body='') r = requests.post(uri, body, headers=headers) if r.status_code != 200: assert False decoded_data = urldecode(r.text) oauth_response = dict(decoded_data) assert 'oauth_token' in oauth_response and 'oauth_token_secret' in oauth_response
def test_access_token_query_params(self): client = oauth1.Client(CLIENT_KEY, client_secret=CLIENT_SECRET, signature_type=SIGNATURE_TYPE_QUERY, signature_method=SIGNATURE_PLAINTEXT, resource_owner_key='HJUCE34yYlRToKKu7fXq90bmRmZm1j', resource_owner_secret='4VVbhBQXcAdJhw42lTvGk0qN1F1Moe', verifier='cXqtvQxfP6EReq7A6ulLKbOrXeflTk') url = BASE_URL + ACCESS_TOKEN_ENDPOINT uri, headers, _ = client.sign(url, http_method='GET') headers['StackSync-API'] = "v2" r = requests.get(uri, headers=headers) if 200 < r.status_code >= 300: assert False decoded_data = urldecode(r.text) oauth_response = dict(decoded_data) assert 'oauth_token' in oauth_response and 'oauth_token_secret' in oauth_response
def _fetch_token(self, url): log.debug('Fetching token from %s using client %s', url, self._client.client) r = self.post(url) if r.status_code >= 400: error = "Token request failed with code %s, response was '%s'." raise TokenRequestDenied(error % (r.status_code, r.text), r.status_code) log.debug('Decoding token from response "%s"', r.text) try: token = dict(urldecode(r.text)) except ValueError as e: error = ("Unable to decode token from token response. " "This is commonly caused by an unsuccessful request where" " a non urlencoded error message is returned. " "The decoding error was %s""" % e) raise ValueError(error) log.debug('Obtained token %s', token) log.debug('Updating internal client attributes from token data.') self._populate_attributes(token) return token
async def fetch_request_token(self) -> Dict[str, str]: log.debug(f'Fetching request token...') _, signed_headers, _ = self.oauth_client.sign(self.request_token_url, 'POST') log.debug(f'Signed headers: {signed_headers}') resp = await self.session.post(self.request_token_url, headers=signed_headers) log.debug(f'Response: {resp.status} {resp.reason}') log.debug(f'To: {resp.method} {resp.real_url.human_repr()}') log.debug(f'Requested as: {resp.request_info.method} {resp.request_info.real_url.human_repr()}') log.debug(f'Request headers: {resp.request_info.headers}') token_raw = await resp.text() log.debug(f'Token response: {token_raw}') token = dict(urldecode(token_raw)) self.oauth_client.resource_owner_key = token['oauth_token'] self.oauth_client.resource_owner_secret = token['oauth_token_secret'] # Set callback to None for future signing calls self.oauth_client.callback_uri = None return token
def is_refresh_token_valid(refresh_token): client_id = settings.EVEOAUTH['CONSUMER_KEY'] client_secret = settings.EVEOAUTH['CONSUMER_SECRET'] headers = { 'Accept': 'application/json', 'Content-Type': ('application/x-www-form-urlencoded;charset=UTF-8'), } body = "grant_type=refresh_token&client_secret=%s&client_id=%s&refresh_token=%s" % ( client_secret, client_id, refresh_token) token_url = settings.EVEOAUTH['BASE_URL'] + settings.EVEOAUTH[ 'TOKEN_URL'] session = requests.Session() r = session.post(token_url, data=dict(urldecode(body)), headers=headers) logger.debug('Request to fetch token completed with status %s.', r.status_code) logger.debug('Request headers were %s', r.request.headers) logger.debug('Request body was %s', r.request.body) logger.debug('Response headers were %s and content %s.', r.headers, r.text) #breadcrumbs.record('Request to fetch token completed with status %s.',r.status_code) #breadcrumbs.record('Request headers were %s', r.request.headers) #breadcrumbs.record('Request body was %s', r.request.body) #breadcrumbs.record('Response headers were %s and content %s.',r.headers, r.text) if r.text: try: content = json.loads(r.text) if "error" in content: if content["error"] == "invalid_token": return False # any exceptions here are purely the fault of CCP oauth, and cannot be used to indicate token validity except ValueError: return True return True
def fetch_token(self, code): body = self.oauth_client.prepare_request_body( code=code, body='', redirect_uri=self.redirect_uri, include_client_id=None) response = self.request( 'POST', self.token_url, headers={ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', }, data=dict(urldecode(body)), auth=httpx.BasicAuth(self.client_id, self.client_secret)) self.token = self.oauth_client.parse_request_body_response( response.text, scope=self.scope) return self.token
def refresh_token(self, token_url, refresh_token=None, body='', auth=None, **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError('No token endpoint set for auto_refresh.') if not is_secure_transport(token_url): raise InsecureTransportError() # Need to nullify token to prevent it from being added to the request refresh_token = refresh_token or self.token.get('refresh_token') self.token = {} log.debug('Adding auto refresh key word arguments %s.', self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug('Prepared refresh token request body %s', body) r = self.post(token_url, data=dict(urldecode(body)), auth=auth) log.debug('Request to refresh token completed with status %s.', r.status_code) log.debug('Response headers were %s and content %s.', r.headers, r.text) self.token = self._client.parse_request_body_response(r.text, scope=self.scope) if not 'refresh_token' in self.token: log.debug('No new refresh token given. Re-using old.') self.token['refresh_token'] = refresh_token return self.token
def params_from_uri(uri): params = dict(urldecode(urlparse(uri).query)) if 'scope' in params: params['scope'] = scope_to_list(params['scope']) return params
def _fetch_token(self, url): token = dict(urldecode(self.post(url).text)) self._populate_attributes(token) return token
def fetch_token( self, token_url, code=None, authorization_response=None, body="", auth=None, username=None, password=None, method="POST", timeout=None, headers=None, verify=True, proxies=None, include_client_id=None, client_secret=None, **kwargs ): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use `token_from_fragment` instead of `fetch_token`. The current implementation enforces the RFC guidelines. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by `requests`. :param username: Username required by LegacyApplicationClients to appear in the request body. :param password: Password required by LegacyApplicationClients to appear in the request body. :param method: The HTTP method used to make the request. Defaults to POST, but may also be GET. Other methods should be added as needed. :param timeout: Timeout of the request in seconds. :param headers: Dict to default request headers with. :param verify: Verify SSL certificate. :param proxies: The `proxies` argument is passed onto `requests`. :param include_client_id: Should the request body include the `client_id` parameter. Default is `None`, which will attempt to autodetect. This can be forced to always include (True) or never include (False). :param client_secret: The `client_secret` paired to the `client_id`. This is generally required unless provided in the `auth` tuple. If the value is `None`, it will be omitted from the request, however if the value is an empty string, an empty string will be sent. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response( authorization_response, state=self._state ) code = self._client.code elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError( "Please supply either code or " "authorization_response parameters." ) # Earlier versions of this library build an HTTPBasicAuth header out of # `username` and `password`. The RFC states, however these attributes # must be in the request body and not the header. # If an upstream server is not spec compliant and requires them to # appear as an Authorization header, supply an explicit `auth` header # to this function. # This check will allow for empty strings, but not `None`. # # Refernences # 4.3.2 - Resource Owner Password Credentials Grant # https://tools.ietf.org/html/rfc6749#section-4.3.2 if isinstance(self._client, LegacyApplicationClient): if username is None: raise ValueError( "`LegacyApplicationClient` requires both the " "`username` and `password` parameters." ) if password is None: raise ValueError( "The required paramter `username` was supplied, " "but `password` was not." ) # merge username and password into kwargs for `prepare_request_body` if username is not None: kwargs["username"] = username if password is not None: kwargs["password"] = password # is an auth explicitly supplied? if auth is not None: # if we're dealing with the default of `include_client_id` (None): # we will assume the `auth` argument is for an RFC compliant server # and we should not send the `client_id` in the body. # This approach allows us to still force the client_id by submitting # `include_client_id=True` along with an `auth` object. if include_client_id is None: include_client_id = False # otherwise we may need to create an auth header else: # since we don't have an auth header, we MAY need to create one # it is possible that we want to send the `client_id` in the body # if so, `include_client_id` should be set to True # otherwise, we will generate an auth header if include_client_id is not True: client_id = self.client_id if client_id: log.debug( 'Encoding `client_id` "%s" with `client_secret` ' "as Basic auth credentials.", client_id, ) client_secret = client_secret if client_secret is not None else "" auth = requests.auth.HTTPBasicAuth(client_id, client_secret) if include_client_id: # this was pulled out of the params # it needs to be passed into prepare_request_body if client_secret is not None: kwargs["client_secret"] = client_secret body = self._client.prepare_request_body( code=code, body=body, redirect_uri=self.redirect_uri, include_client_id=include_client_id, **kwargs ) headers = headers or { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", } self.token = {} if method.upper() == "POST": r = self.post( token_url, data=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify, proxies=proxies, ) log.debug("Prepared fetch token request body %s", body) elif method.upper() == "GET": # if method is not 'POST', switch body to querystring and GET r = self.get( token_url, params=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify, proxies=proxies, ) log.debug("Prepared fetch token request querystring %s", body) else: raise ValueError("The method kwarg must be POST or GET.") log.debug("Request to fetch token completed with status %s.", r.status_code) log.debug("Request headers were %s", r.request.headers) log.debug("Request body was %s", r.request.body) log.debug("Response headers were %s and content %s.", r.headers, r.text) log.debug( "Invoking %d token response hooks.", len(self.compliance_hook["access_token_response"]), ) for hook in self.compliance_hook["access_token_response"]: log.debug("Invoking hook %s.", hook) r = hook(r) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token log.debug("Obtained token %s.", self.token) return self.token
def fetch_token(self, token_url, code=None, authorization_response=None, body='', auth=None, username=None, password=None, method='POST', timeout=None, headers=None, verify=True, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param method: The HTTP method used to make the request. Defaults to POST, but may also be GET. Other methods should be added as needed. :param headers: Dict to default request headers with. :param timeout: Timeout of the request in seconds. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self._state) code = self._client.code elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError('Please supply either code or ' 'authorization_code parameters.') body = self._client.prepare_request_body(code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) headers = headers or { 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', } if method.upper() == 'POST': r = self.post(token_url, data=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify) log.debug('Prepared fetch token request body %s', body) elif method.upper() == 'GET': # if method is not 'POST', switch body to querystring and GET r = self.get(token_url, params=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify) log.debug('Prepared fetch token request querystring %s', body) else: raise ValueError('The method kwarg must be POST or GET.') log.debug('Request to fetch token completed with status %s.', r.status_code) log.debug('Request headers were %s', r.request.headers) log.debug('Request body was %s', r.request.body) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['access_token_response'])) for hook in self.compliance_hook['access_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) r.raise_for_status() self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token log.debug('Obtained token %s.', self.token) return self.token
def _compliance_fix(r): token = dict(urldecode(r.text)) token['expires_in'] = token['expires'] token['token_type'] = 'Bearer' r._content = dumps(token) return r
def get_common_objects(self): super().get_common_objects() user = self.request.user # Determine user ID. student_id = "aplusuid%d" % (user.pk) if self.profile.student_id: student_id = self.profile.student_id # MD5 the user id so that the real student id and names or emails # are not linked in external services. student_id = hashlib.md5(student_id.encode('utf-8')).hexdigest() # Determine user role. role = "Student" if self.is_teacher: role = "Instructor" elif self.is_assistant: role = "TA,TeachingAssistant" parameters = { "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": "aplus%d" % (self.service.pk), "resource_link_title": self.menu_item.label, # User session. "user_id": student_id, "roles": role, "lis_person_name_full": "%s %s" % (user.first_name, user.last_name), "lis_person_name_given": user.first_name, "lis_person_name_family": user.last_name, "lis_person_contact_email_primary": user.email, # Selected course. "context_id": self.request.get_host() \ + self.instance.get_absolute_url(), "context_title": self.course.name, "context_label": self.course.code, "launch_presentation_locale": get_language(), "tool_consumer_instance_guid": self.request.get_host() + "/aplus", "tool_consumer_instance_name": "A+ LMS", } headers = { "Content-Type": "application/x-www-form-urlencoded", } # Sign the request using OAuth. client = Client(self.service.consumer_key, client_secret=self.service.consumer_secret, signature_method=SIGNATURE_HMAC, signature_type=SIGNATURE_TYPE_BODY) uri, headers, body = client.sign(self.service.url, http_method="POST", body=parameters, headers=headers) self.url = uri self.parameters = urldecode(body) self.note("url", "parameters")
def collect_parameters(uri_query="", body=[], headers=None, exclude_oauth_signature=True, with_realm=False): """**Parameter Sources** Parameters starting with `oauth_` will be unescaped. Body parameters must be supplied as a dict, a list of 2-tuples, or a formencoded query string. Headers must be supplied as a dict. Per `section 3.4.1.3.1`_ of the spec. For example, the HTTP request:: POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded Authorization: OAuth realm="Example", oauth_consumer_key="9djdj82h48djs9d2", oauth_token="kkk9d7dh3k39sjv7", oauth_signature_method="HMAC-SHA1", oauth_timestamp="137131201", oauth_nonce="7d8f3e4a", oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D" c2&a3=2+q contains the following (fully decoded) parameters used in the signature base sting:: +------------------------+------------------+ | Name | Value | +------------------------+------------------+ | b5 | =%3D | | a3 | a | | c@ | | | a2 | r b | | oauth_consumer_key | 9djdj82h48djs9d2 | | oauth_token | kkk9d7dh3k39sjv7 | | oauth_signature_method | HMAC-SHA1 | | oauth_timestamp | 137131201 | | oauth_nonce | 7d8f3e4a | | c2 | | | a3 | 2 q | +------------------------+------------------+ Note that the value of "b5" is "=%3D" and not "==". Both "c@" and "c2" have empty values. While the encoding rules specified in this specification for the purpose of constructing the signature base string exclude the use of a "+" character (ASCII code 43) to represent an encoded space character (ASCII code 32), this practice is widely used in "application/x-www-form-urlencoded" encoded values, and MUST be properly decoded, as demonstrated by one of the "a3" parameter instances (the "a3" parameter is used twice in this request). .. _`section 3.4.1.3.1`: http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 """ headers = headers or {} params = [] # The parameters from the following sources are collected into a single # list of name/value pairs: # * The query component of the HTTP request URI as defined by # `RFC3986, Section 3.4`_. The query component is parsed into a list # of name/value pairs by treating it as an # "application/x-www-form-urlencoded" string, separating the names # and values and decoding them as defined by # `W3C.REC-html40-19980424`_, Section 17.13.4. # # .. _`RFC3986, Section 3.4`: http://tools.ietf.org/html/rfc3986#section-3.4 # .. _`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424 if uri_query: params.extend(urldecode(uri_query)) # * The OAuth HTTP "Authorization" header field (`Section 3.5.1`_) if # present. The header's content is parsed into a list of name/value # pairs excluding the "realm" parameter if present. The parameter # values are decoded as defined by `Section 3.5.1`_. # # .. _`Section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1 if headers: headers_lower = dict((k.lower(), v) for k, v in headers.items()) authorization_header = headers_lower.get("authorization") if authorization_header is not None: params.extend( [i for i in utils.parse_authorization_header(authorization_header) if with_realm or i[0] != "realm"] ) # * The HTTP request entity-body, but only if all of the following # conditions are met: # * The entity-body is single-part. # # * The entity-body follows the encoding requirements of the # "application/x-www-form-urlencoded" content-type as defined by # `W3C.REC-html40-19980424`_. # * The HTTP request entity-header includes the "Content-Type" # header field set to "application/x-www-form-urlencoded". # # .._`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424 # TODO: enforce header param inclusion conditions bodyparams = extract_params(body) or [] params.extend(bodyparams) # ensure all oauth params are unescaped unescaped_params = [] for k, v in params: if k.startswith("oauth_"): v = utils.unescape(v) unescaped_params.append((k, v)) # The "oauth_signature" parameter MUST be excluded from the signature # base string if present. if exclude_oauth_signature: unescaped_params = list(filter(lambda i: i[0] != "oauth_signature", unescaped_params)) return unescaped_params
resource_owner_secret = '' if client_key == '' or client_secret == '': print "Please change your client key and secret in connectXAuth.py header" sys.exit(0) if username == 'USER_NAME' or password == 'USER_PASSWORD': print "Please change username and password in connectXAuth.py header" sys.exit(0) client = Client(client_key, client_secret=client_secret, signature_type=SIGNATURE_TYPE_BODY) headers = {"Content-Type": CONTENT_TYPE_FORM_URLENCODED} body = 'x_auth_mode=client_auth&x_auth_username='******'&x_auth_password='******'oauth_token') resource_owner_secret = oauth_tokens.get('oauth_token_secret') cred = {"client_key": client_key, "client_secret": client_secret, "resource_owner_key": resource_owner_key, "resource_owner_secret": resource_owner_secret} import json with open('credentials.json', 'w') as outfile: json.dump(cred, outfile)
async def refresh_token(self, token_url, refresh_token=None, body="", auth=None, timeout=None, headers=None, verify_ssl=True, proxies=None, **kwargs): """Fetch a new access token using a refresh token. :param token_url: The token endpoint, must be HTTPS. :param refresh_token: The refresh_token to use. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by `requests`. :param timeout: Timeout of the request in seconds. :param headers: A dict of headers to be used by `requests`. :param verify: Verify SSL certificate. :param proxies: The `proxies` argument will be passed to `requests`. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not token_url: raise ValueError("No token endpoint set for auto_refresh.") if not is_secure_transport(token_url): raise InsecureTransportError() refresh_token = refresh_token or self.token.get("refresh_token") log.debug("Adding auto refresh key word arguments %s.", self.auto_refresh_kwargs) kwargs.update(self.auto_refresh_kwargs) body = self._client.prepare_refresh_body(body=body, refresh_token=refresh_token, scope=self.scope, **kwargs) log.debug("Prepared refresh token request body %s", body) if headers is None: headers = { "Accept": "application/json", "Content-Type": ("application/x-www-form-urlencoded;charset=UTF-8"), } async with self.post( token_url, data=dict(urldecode(body)), auth=auth, timeout=timeout, headers=headers, verify_ssl=verify_ssl, withhold_token=True, # proxy=proxies, ) as resp: log.debug("Request to refresh token completed with status %s.", resp.status) text = await resp.text() log.debug("Response headers were %s and content %s.", resp.headers, text) (resp, ) = self._invoke_hooks("refresh_token_response", resp) self.token = self._client.parse_request_body_response(text, scope=self.scope) if "refresh_token" not in self.token: log.debug("No new refresh token given. Re-using old.") self.token["refresh_token"] = refresh_token return self.token
async def fetch_token(self, token_url, code=None, authorization_response=None, body="", auth=None, username=None, password=None, method="POST", force_querystring=False, timeout=None, headers=None, verify_ssl=True, proxies=None, include_client_id=None, client_id=None, client_secret=None, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use `token_from_fragment` instead of `fetch_token`. The current implementation enforces the RFC guidelines. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by `requests`. :param username: Username required by LegacyApplicationClients to appear in the request body. :param password: Password required by LegacyApplicationClients to appear in the request body. :param method: The HTTP method used to make the request. Defaults to POST, but may also be GET. Other methods should be added as needed. :param force_querystring: If True, force the request body to be sent in the querystring instead. :param timeout: Timeout of the request in seconds. :param headers: Dict to default request headers with. :param verify: Verify SSL certificate. :param proxies: The `proxies` argument is passed onto `requests`. :param include_client_id: Should the request body include the `client_id` parameter. Default is `None`, which will attempt to autodetect. This can be forced to always include (True) or never include (False). :param client_secret: The `client_secret` paired to the `client_id`. This is generally required unless provided in the `auth` tuple. If the value is `None`, it will be omitted from the request, however if the value is an empty string, an empty string will be sent. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: log.debug('-- response %s', authorization_response) self._client.parse_request_uri_response( str(authorization_response), state=self._state) code = self._client.code log.debug('--code %s', code) elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError("Please supply either code or " "authorization_response parameters.") # Earlier versions of this library build an HTTPBasicAuth header out of # `username` and `password`. The RFC states, however these attributes # must be in the request body and not the header. # If an upstream server is not spec compliant and requires them to # appear as an Authorization header, supply an explicit `auth` header # to this function. # This check will allow for empty strings, but not `None`. # # Refernences # 4.3.2 - Resource Owner Password Credentials Grant # https://tools.ietf.org/html/rfc6749#section-4.3.2 if isinstance(self._client, LegacyApplicationClient): if username is None: raise ValueError("`LegacyApplicationClient` requires both the " "`username` and `password` parameters.") if password is None: raise ValueError( "The required paramter `username` was supplied, " "but `password` was not.") # merge username and password into kwargs for `prepare_request_body` if username is not None: kwargs["username"] = username if password is not None: kwargs["password"] = password # is an auth explicitly supplied? if auth is not None: # if we're dealing with the default of `include_client_id` (None): # we will assume the `auth` argument is for an RFC compliant server # and we should not send the `client_id` in the body. # This approach allows us to still force the client_id by submitting # `include_client_id=True` along with an `auth` object. if include_client_id is None: include_client_id = False # otherwise we may need to create an auth header else: # since we don't have an auth header, we MAY need to create one # it is possible that we want to send the `client_id` in the body # if so, `include_client_id` should be set to True # otherwise, we will generate an auth header if include_client_id is not True: client_id = self.client_id if client_id: log.debug( 'Encoding `client_id` "%s" with `client_secret` ' "as Basic auth credentials.", client_id, ) client_secret = client_secret if client_secret is not None else "" auth = aiohttp.BasicAuth(login=client_id, password=client_secret) if include_client_id: # this was pulled out of the params # it needs to be passed into prepare_request_body if client_secret is not None: kwargs["client_secret"] = client_secret body = self._client.prepare_request_body( code=code, body=body, redirect_uri=self.redirect_uri, include_client_id=include_client_id, **kwargs) headers = headers or { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", } self.token = {} request_kwargs = {} if method.upper() == "POST": request_kwargs["params" if force_querystring else "data"] = dict( urldecode(body)) elif method.upper() == "GET": request_kwargs["params"] = dict(urldecode(body)) else: raise ValueError("The method kwarg must be POST or GET.") async with self.request(method=method, url=token_url, timeout=timeout, headers=headers, auth=auth, verify_ssl=verify_ssl, proxy=proxies, **request_kwargs) as resp: log.debug("Request to fetch token completed with status %s.", resp.status) log.debug("Request headers were %s", headers) log.debug("Request body was %s", body) text = await resp.text() log.debug("Response headers were %s and content %s.", resp.headers, text) (resp, ) = self._invoke_hooks("access_token_response", resp) self._client.parse_request_body_response(text, scope=self.scope) self.token = self._client.token log.debug("Obtained token %s.", self.token) return self.token
def fetch_token(self, token_url, code=None, authorization_response=None, body='', auth=None, username=None, password=None, method='POST', timeout=None, headers=None, verify=True, proxies=None, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use token_from_fragment instead of fetch_token. :param token_url: Token endpoint URL, must use HTTPS. :param code: Authorization code (used by WebApplicationClients). :param authorization_response: Authorization response URL, the callback URL of the request back to you. Used by WebApplicationClients instead of code. :param body: Optional application/x-www-form-urlencoded body to add the include in the token request. Prefer kwargs over body. :param auth: An auth tuple or method as accepted by requests. :param username: Username used by LegacyApplicationClients. :param password: Password used by LegacyApplicationClients. :param method: The HTTP method used to make the request. Defaults to POST, but may also be GET. Other methods should be added as needed. :param headers: Dict to default request headers with. :param timeout: Timeout of the request in seconds. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :return: A token dict """ if not is_secure_transport(token_url): raise InsecureTransportError() if not code and authorization_response: self._client.parse_request_uri_response(authorization_response, state=self._state) code = self._client.code elif not code and isinstance(self._client, WebApplicationClient): code = self._client.code if not code: raise ValueError('Please supply either code or ' 'authorization_response parameters.') body = self._client.prepare_request_body(code=code, body=body, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) client_id = kwargs.get('client_id', '') if auth is None: if client_id: log.debug('Encoding client_id "%s" with client_secret as Basic auth credentials.', client_id) client_secret = kwargs.get('client_secret', '') client_secret = client_secret if client_secret is not None else '' auth = requests.auth.HTTPBasicAuth(client_id, client_secret) elif username: if password is None: raise ValueError('Username was supplied, but not password.') log.debug('Encoding username, password as Basic auth credentials.') auth = requests.auth.HTTPBasicAuth(username, password) headers = headers or { 'Accept': 'application/json', 'Content-Type': 'application/json', } self.token = {} if method.upper() == 'POST': r = self.post(token_url, json=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify, proxies=proxies) log.debug('Prepared fetch token request body %s', body) elif method.upper() == 'GET': # if method is not 'POST', switch body to querystring and GET r = self.get(token_url, params=dict(urldecode(body)), timeout=timeout, headers=headers, auth=auth, verify=verify, proxies=proxies) log.debug('Prepared fetch token request querystring %s', body) else: raise ValueError('The method kwarg must be POST or GET.') log.debug('Request to fetch token completed with status %s.', r.status_code) log.debug('Request headers were %s', r.request.headers) log.debug('Request body was %s', r.request.body) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', len(self.compliance_hook['access_token_response'])) for hook in self.compliance_hook['access_token_response']: log.debug('Invoking hook %s.', hook) r = hook(r) self._client.parse_request_body_response(r.text, scope=self.scope) self.token = self._client.token log.debug('Obtained token %s.', self.token) return self.token