def test_revoke_bad_post_request(self): endpoint = RevocationEndpoint(self.validator, supported_token_types=['access_token']) for param in ['token', 'secret', 'code', 'foo']: uri = 'http://some.endpoint?' + urlencode([(param, 'secret')]) body = urlencode([('token', 'foo'), ('token_type_hint', 'access_token')]) h, b, s = endpoint.create_revocation_response(uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b)['error'], 'invalid_request') self.assertIn('query parameters are not allowed', loads(b)['error_description']) self.assertEqual(s, 400)
def request_request_token(request): """ Checks provided client key and secret and assigns request token if all goes well. """ server = DjangoOAuthServer() if request.method == 'POST': try: is_request_valid = server.verify_request_token_request(uri=request.build_absolute_uri(), headers=request.META)[0] except ValueError as exception: return HttpResponse(exception, status=400) else: if not is_request_valid: return HttpResponse(status=401) headers = collect_parameters(headers=to_unicode(request.META, 'utf-8')) client_key = dict(headers)[u'oauth_consumer_key'] client = Client.objects.get(key=client_key) token = Token.objects.create_request_token(client) token_response = urlencode((('oauth_token', token.key), ('oauth_token_secret', token.secret))) return HttpResponse(token_response, status=200, content_type='application/x-www-form-urlencoded') return HttpResponseNotAllowed('POST', _('Only POST is allowed for this URI.'))
def _render(self, request, formencode=False): """Render a signed request according to signature type Returns a 3-tuple containing the request URI, headers, and body. If the formencode argument is True and the body contains parameters, it is escaped and returned as a valid formencoded string. """ # TODO what if there are body params on a header-type auth? # TODO what if there are query params on a body-type auth? uri, headers, body = request.uri, request.headers, request.body # TODO: right now these prepare_* methods are very narrow in scope--they # only affect their little thing. In some cases (for example, with # header auth) it might be advantageous to allow these methods to touch # other parts of the request, like the headers—so the prepare_headers # method could also set the Content-Type header to x-www-form-urlencoded # like the spec requires. This would be a fundamental change though, and # I'm not sure how I feel about it. if self.signature_type == SIGNATURE_TYPE_AUTH_HEADER: headers = parameters.prepare_headers(request.oauth_params, request.headers) elif self.signature_type == SIGNATURE_TYPE_BODY and request.decoded_body is not None: body = parameters.prepare_form_encoded_body(request.oauth_params, request.decoded_body) if formencode: body = urlencode(body) headers['Content-Type'] = u'application/x-www-form-urlencoded' elif self.signature_type == SIGNATURE_TYPE_QUERY: uri = parameters.prepare_request_uri_query(request.oauth_params, request.uri) else: raise ValueError('Unknown signature type specified.') return uri, headers, body
def oauth_error_uri(error): """ the upstream oauthlib `OAuth2Error` has a `json` property that encodes the error data this is missing on the `OAuth1Error` object in this version, the error is urlencoded """ return urlencode(error.twotuples)
def decorated(*args, **kwargs): for func in self._before_request_funcs: func() if hasattr(request, 'oauth') and request.oauth: return f(*args, **kwargs) server = self.server uri, http_method, body, headers = extract_params() try: valid, req = server.validate_protected_resource_request( uri, http_method, body, headers, realms ) except Exception as e: log.warn('Exception: %r', e) e.urlencoded = urlencode([('error', 'unknown')]) e.status_code = 400 return _error_response(e) for func in self._after_request_funcs: valid, req = func(valid, req) if not valid: return abort(401) # alias user for convenience req.user = req.access_token.user request.oauth = req return f(*args, **kwargs)
def decorated(*args, **kwargs): for func in self._before_request_funcs: func() if hasattr(request, 'oauth') and request.oauth: return f(*args, **kwargs) server = self.server uri, http_method, body, headers = extract_params() try: valid, req = server.validate_protected_resource_request( uri, http_method, body, headers, realms) except Exception as e: log.warn('Exception: %r', e) e.urlencoded = urlencode([('error', 'unknown')]) e.status_code = 400 return _error_response(e) for func in self._after_request_funcs: valid, req = func(valid, req) if not valid: return abort(401) # alias user for convenience req.user = req.access_token.user request.oauth = req return f(*args, **kwargs)
def test_invalid_post_request(self): self.validator.authenticate_client.side_effect = self.set_client for param in ['token', 'secret', 'code', 'foo']: uri = 'https://i/b/token?' + urlencode([(param, 'secret')]) try: _, body, s = self.web.create_token_response( uri, body='grant_type=access_token&code=123') self.fail('This should have failed with InvalidRequestError') except errors.InvalidRequestError as ire: self.assertIn('URL query parameters are not allowed', ire.description) try: _, body, s = self.legacy.create_token_response( uri, body='grant_type=access_token&code=123') self.fail('This should have failed with InvalidRequestError') except errors.InvalidRequestError as ire: self.assertIn('URL query parameters are not allowed', ire.description) try: _, body, s = self.backend.create_token_response( uri, body='grant_type=access_token&code=123') self.fail('This should have failed with InvalidRequestError') except errors.InvalidRequestError as ire: self.assertIn('URL query parameters are not allowed', ire.description)
def test_prepare_form_encoded_body(self): existing_body = '' form_encoded_body = 'data_param_foo=foo&data_param_1=1&oauth_consumer_key=9djdj82h48djs9d2&oauth_token=kkk9d7dh3k39sjv7&oauth_signature_method=HMAC-SHA1&oauth_timestamp=137131201&oauth_nonce=7d8f3e4a&oauth_signature=bYT5CMsGcbgUdFHObYMEfcx6bsw%3D' self.assertEqual( urlencode( prepare_form_encoded_body(self.auth_and_data, existing_body)), form_encoded_body)
def _render(self, request, formencode=False, realm=None): """Render a signed request according to signature type Returns a 3-tuple containing the request URI, headers, and body. If the formencode argument is True and the body contains parameters, it is escaped and returned as a valid formencoded string. """ # TODO what if there are body params on a header-type auth? # TODO what if there are query params on a body-type auth? uri, headers, body = request.uri, request.headers, request.body # TODO: right now these prepare_* methods are very narrow in scope--they # only affect their little thing. In some cases (for example, with # header auth) it might be advantageous to allow these methods to touch # other parts of the request, like the headers—so the prepare_headers # method could also set the Content-Type header to x-www-form-urlencoded # like the spec requires. This would be a fundamental change though, and # I'm not sure how I feel about it. if self.signature_type == SIGNATURE_TYPE_AUTH_HEADER: headers = parameters.prepare_headers(request.oauth_params, request.headers, realm=realm) elif self.signature_type == SIGNATURE_TYPE_BODY and request.decoded_body is not None: body = parameters.prepare_form_encoded_body(request.oauth_params, request.decoded_body) if formencode: body = urlencode(body) headers['Content-Type'] = 'application/x-www-form-urlencoded' elif self.signature_type == SIGNATURE_TYPE_QUERY: uri = parameters.prepare_request_uri_query(request.oauth_params, request.uri) else: raise ValueError('Unknown signature type specified.') return uri, headers, body
def test_introspect_token_nohint(self): # don't specify token_type_hint body = urlencode([('token', 'foo')]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b), self.resp_b) self.assertEqual(s, 200)
def test_introspect_token_false(self): self.validator.introspect_token.return_value = None body = urlencode([('token', 'foo')]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b), {"active": False}) self.assertEqual(s, 200)
def test_introspect_token_claims_spoof_active(self): self.validator.introspect_token.return_value = {"foo": "bar", "active": False} body = urlencode([('token', 'foo')]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b), {"active": True, "foo": "bar"}) self.assertEqual(s, 200)
def verify_request(self, request, scopes): """ Wrapper method to call `verify_request` in OAuthLib """ uri, method, data, headers = self.extract_params(request) body = urlencode(data.items()) valid, r = self.server.verify_request(uri, method, body, headers, scopes=scopes) return valid, r
def create_request_token(self, request, credentials): token = { 'oauth_token': self.token_generator()[:KEY_SIZE], 'oauth_token_secret': self.token_generator()[:SECRET_SIZE], } token.update(credentials) self.request_validator.save_request_token(token, request) return urlencode(token.items())
def test_revoke_token(self): for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_revocation_response( self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, '') self.assertEqual(s, 200) # don't specify token_type_hint body = urlencode([('token', 'foo')]) h, b, s = self.endpoint.create_revocation_response( self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, '') self.assertEqual(s, 200)
def encode_request_data(data, format): if format is None: return data, None if format == 'json': return json_dumps(data or {}), 'application/json' if format == 'urlencoded': return urlencode(data or {}), 'application/x-www-form-urlencoded' raise TypeError('Unknown format %r' % format)
def test_revoke_token(self): for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, '') self.assertEqual(s, 200) # don't specify token_type_hint body = urlencode([('token', 'foo')]) h, b, s = self.endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, '') self.assertEqual(s, 200)
def test_revoke_token_client_authentication_failed(self): self.validator.authenticate_client.return_value = False body = urlencode([('token', 'foo'), ('token_type_hint', 'access_token')]) h, b, s = self.endpoint.create_revocation_response( self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(loads(b)['error'], 'invalid_client') self.assertEqual(s, 401)
def test_introspect_token(self): for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b), self.resp_b) self.assertEqual(s, 200)
def _extract_params(self, request): """ Extract parameters from the Django request object. Such parameters will then be passed to OAuthLib to build its own Request object. The body should be encoded using OAuthLib urlencoded """ uri = self._get_escaped_full_path(request) http_method = request.method headers = self.extract_headers(request) body = urlencode(self.extract_body(request)) return uri, http_method, body, headers
def _extract_params(self, request): log.debug('Extracting parameters from request.') uri = request.build_absolute_uri() http_method = request.method headers = request.META del headers['wsgi.input'] del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(request.POST.items()) return uri, http_method, body, headers
def create_access_token(self, request, credentials): request.realms = self.request_validator.get_realms( request.resource_owner_key, request) token = { 'oauth_token': self.token_generator()[:KEY_SIZE], 'oauth_token_secret': self.token_generator()[:SECRET_SIZE], 'oauth_authorized_realms': ' '.join(request.realms) } token.update(credentials) self.request_validator.save_access_token(token, request) return urlencode(token.items())
def _extract_params(self, request): """ 提取request 中的参数 :param request: :return: """ uri = self._get_escaped_full_path(request) http_method = request.method headers = self._extract_headers(request) body = urlencode(self._extract_body(request)) return uri, http_method, body, headers
def test_revoke_with_callback(self): callback = 'package.hello_world' for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type), ('callback', callback)]) h, b, s = self.endpoint.create_revocation_response( self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, callback + '()') self.assertEqual(s, 200)
def test_introspect_token_public_client_authentication(self): self.validator.client_authentication_required.return_value = False self.validator.authenticate_client_id.return_value = True for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b), self.resp_b) self.assertEqual(s, 200)
def test_revoke_with_callback(self): callback = 'package.hello_world' for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type), ('callback', callback)]) h, b, s = self.endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, callback + '()') self.assertEqual(s, 200)
def test_revoke_token_public_client_authentication(self): self.validator.client_authentication_required.return_value = False self.validator.authenticate_client_id.return_value = True for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_revocation_response( self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, '') self.assertEqual(s, 200)
def test_revoke_token_without_client_authentication(self): self.validator.client_authentication_required.return_value = False self.validator.authenticate_client.return_value = False for token_type in ('access_token', 'refresh_token', 'invalid'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type)]) h, b, s = self.endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, None) self.assertEqual(s, 200)
def prepare_request_uri_query(oauth_params, uri): """Prepare the Request URI Query. Per `section 3.5.3`_ of the spec. .. _`section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3 """ # append OAuth params to the existing set of query components sch, net, path, par, query, fra = urlparse(uri) query = urlencode(_append_params(oauth_params, extract_params(query) or [])) return urlunparse((sch, net, path, par, query, fra))
def test_revoke_with_callback(self): endpoint = RevocationEndpoint(self.validator, enable_jsonp=True) callback = 'package.hello_world' for token_type in ('access_token', 'refresh_token'): body = urlencode([('token', 'foo'), ('token_type_hint', token_type), ('callback', callback)]) h, b, s = endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, callback + '();') self.assertEqual(s, 200) body = urlencode([('token', 'foo'), ('token_type_hint', 'invalid'), ('callback', callback)]) h, b, s = endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(b, callback + '({"error": "unsupported_token_type"});') self.assertEqual(s, 400)
def access_token(self): """Create an OAuth access token for an authorized client. Defaults to /access_token. Invoked by client applications. """ access_token = generate_token(length=self.access_token_length[1]) token_secret = generate_token(self.secret_length) client_key = request.oauth.client_key self.save_access_token(client_key, access_token, request.oauth.resource_owner_key, secret=token_secret) return urlencode([(u'oauth_token', access_token), (u'oauth_token_secret', token_secret)])
def _extract_params(self): log.debug("Extracting parameters from request.") uri = request.url http_method = request.method headers = dict(request.headers) if "wsgi.input" in headers: del headers["wsgi.input"] if "wsgi.errors" in headers: del headers["wsgi.errors"] if "HTTP_AUTHORIZATION" in headers: headers["Authorization"] = headers["HTTP_AUTHORIZATION"] body = urlencode(request.form.items()) return uri, http_method, body, headers
def extract_params(request): logger.debug('Extracting parameters from request.') uri = _get_escaped_full_path(request) http_method = request.method headers = request.META if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(request.POST.items()) return uri, http_method, body, headers
def _extract_params(self): log.debug('Extracting parameters from request.') uri = request.url http_method = request.method headers = dict(request.headers) if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(request.form.items()) return uri, http_method, body, headers
def decorated(*args, **kwargs): server = self.server uri, http_method, body, headers = extract_params() credentials = f(*args, **kwargs) try: ret = server.create_access_token_response( uri, http_method, body, headers, credentials) return create_response(*ret) except errors.OAuth1Error as e: return _error_response(e) except Exception as e: e.urlencoded = urlencode([('error', str(e))]) e.status_code = 400 return _error_response(e)
def test_revoke_token_client_authentication_failed(self): self.validator.authenticate_client.return_value = False body = urlencode([('token', 'foo'), ('token_type_hint', 'access_token')]) h, b, s = self.endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'Pragma': 'no-cache', "WWW-Authenticate": 'Bearer, error="invalid_client"' }) self.assertEqual(loads(b)['error'], 'invalid_client') self.assertEqual(s, 401)
def test_introspect_token_client_authentication_failed(self): self.validator.authenticate_client.return_value = False body = urlencode([('token', 'foo'), ('token_type_hint', 'access_token')]) h, b, s = self.endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'Pragma': 'no-cache', "WWW-Authenticate": 'Bearer, error="invalid_client"' }) self.assertEqual(loads(b)['error'], 'invalid_client') self.assertEqual(s, 401)
def test_revoke_invalid_request_method(self): endpoint = RevocationEndpoint(self.validator, supported_token_types=['access_token']) test_methods = ['GET', 'pUt', 'dEleTe', 'paTcH'] test_methods = test_methods + [x.lower() for x in test_methods] + [x.upper() for x in test_methods] for method in test_methods: body = urlencode([('token', 'foo'), ('token_type_hint', 'refresh_token')]) h, b, s = endpoint.create_revocation_response(self.uri, http_method = method, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b)['error'], 'invalid_request') self.assertIn('Unsupported request method', loads(b)['error_description']) self.assertEqual(s, 400)
def create_request_token(self, request, credentials): """Create and save a new request token. :param request: An oauthlib.common.Request object. :param credentials: A dict of extra token credentials. :returns: The token as an urlencoded string. """ token = { 'oauth_token': self.token_generator(), 'oauth_token_secret': self.token_generator(), 'oauth_callback_confirmed': 'true' } token.update(credentials) self.request_validator.save_request_token(token, request) return urlencode(token.items())
def _extract_params(self, request): """ Extract parameters from the Django request object. Such parameters will then be passed to OAuthLib to build its own Request object """ uri = request.build_absolute_uri() http_method = request.method headers = request.META.copy() if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(request.POST.items()) return uri, http_method, body, headers
def test_revoke_unsupported_token(self): endpoint = RevocationEndpoint(self.validator, supported_token_types=['access_token']) body = urlencode([('token', 'foo'), ('token_type_hint', 'refresh_token')]) h, b, s = endpoint.create_revocation_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, {}) self.assertEqual(loads(b)['error'], 'unsupported_token_type') self.assertEqual(s, 400) h, b, s = endpoint.create_revocation_response(self.uri, headers=self.headers, body='') self.assertEqual(h, {}) self.assertEqual(loads(b)['error'], 'invalid_request') self.assertEqual(s, 400)
def _extract_params(self, request): """ Extract parameters from the Django request object. Such parameters will then be passed to OAuthLib to build its own Request object """ uri = self._get_escaped_full_path(request) http_method = request.method headers = request.META.copy() if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(request.POST.items()) return uri, http_method, body, headers
def test_introspect_unsupported_token(self): endpoint = IntrospectEndpoint(self.validator, supported_token_types=['access_token']) body = urlencode([('token', 'foo'), ('token_type_hint', 'refresh_token')]) h, b, s = endpoint.create_introspect_response(self.uri, headers=self.headers, body=body) self.assertEqual(h, self.resp_h) self.assertEqual(loads(b)['error'], 'unsupported_token_type') self.assertEqual(s, 400) h, b, s = endpoint.create_introspect_response(self.uri, headers=self.headers, body='') self.assertEqual(h, self.resp_h) self.assertEqual(loads(b)['error'], 'invalid_request') self.assertEqual(s, 400)
def request_token(self): """Create an OAuth request token for a valid client request. Defaults to /request_token. Invoked by client applications. """ client_key = request.oauth.client_key realm = request.oauth.realm # TODO: fallback on default realm? callback = request.oauth.callback_uri request_token = generate_token(length=self.request_token_length[1]) token_secret = generate_token(length=self.secret_length) self.save_request_token(client_key, request_token, callback, realm=realm, secret=token_secret) return urlencode([(u'oauth_token', request_token), (u'oauth_token_secret', token_secret), (u'oauth_callback_confirmed', u'true')])
def _extract_params(self, request): """ Extract parameters from the Django request object. Such parameters will then be passed to OAuthLib to build its own Request object """ uri = self._get_escaped_full_path(request) http_method = request.method headers = request.META.copy() if "wsgi.input" in headers: del headers["wsgi.input"] if "wsgi.errors" in headers: del headers["wsgi.errors"] if "HTTP_AUTHORIZATION" in headers: headers["Authorization"] = headers["HTTP_AUTHORIZATION"] body = urlencode(request.POST.items()) return uri, http_method, body, headers
def _extract_params(self, request, post_dict): """ Extract parameters from the Django request object. Such parameters will then be passed to OAuthLib to build its own Request object """ uri = self._get_escaped_full_path(request) http_method = request.httprequest.method headers = dict(list(request.httprequest.headers.items())) if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] body = urlencode(list(post_dict.items())) return uri, http_method, body, headers
def create_access_token(self, request, credentials): """Create and save a new access token. Similar to OAuth 2, indication of granted scopes will be included as a space separated list in ``oauth_authorized_realms``. :param request: An oauthlib.common.Request object. :returns: The token as an urlencoded string. """ request.realms = self.request_validator.get_realms(request.resource_owner_key, request) token = { "oauth_token": self.token_generator(), "oauth_token_secret": self.token_generator(), # Backport the authorized scopes indication used in OAuth2 "oauth_authorized_realms": " ".join(request.realms), } token.update(credentials) self.request_validator.save_access_token(token, request) return urlencode(token.items())
def extract_params(self, request): if isinstance(request, Request): data = request.data headers = request._request.META.copy() uri = request._request.build_absolute_uri() else: data = urlencode(request.POST.items()) headers = request.META.copy() uri = request.build_absolute_uri() method = request.method if 'wsgi.input' in headers: del headers['wsgi.input'] if 'wsgi.errors' in headers: del headers['wsgi.errors'] # OAuthLib looks for 'Authorization' if 'HTTP_AUTHORIZATION' in headers: headers['Authorization'] = headers['HTTP_AUTHORIZATION'] return uri, method, data, headers