From 4aed1bbdac2f774c3ef2debc0be61b37bb66f37e Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Tue, 10 Sep 2013 14:23:09 +0200 Subject: [PATCH 1/2] added testcase --- oauth2_provider/backends.py | 10 +++++++++- oauth2_provider/tests/__init__.py | 1 + oauth2_provider/tests/test_oauth2_backends.py | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 oauth2_provider/tests/test_oauth2_backends.py diff --git a/oauth2_provider/backends.py b/oauth2_provider/backends.py index 24d15fe66..5b74ecfec 100644 --- a/oauth2_provider/backends.py +++ b/oauth2_provider/backends.py @@ -4,6 +4,10 @@ from .exceptions import OAuthToolkitError, FatalClientError from .oauth2_validators import OAuth2Validator +import urlparse +from django.utils.http import urlquote +from django.utils.encoding import iri_to_uri + class OAuthLibCore(object): """ @@ -15,12 +19,16 @@ def __init__(self, server=None): """ self.server = server or oauth2.Server(OAuth2Validator()) + def _get_escaped_full_path(self, request): + uri = request.get_full_path() + return uri + 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() + uri = self._get_escaped_full_path(request) http_method = request.method headers = request.META.copy() if 'wsgi.input' in headers: diff --git a/oauth2_provider/tests/__init__.py b/oauth2_provider/tests/__init__.py index 51ff6bdd1..fbe760a7a 100644 --- a/oauth2_provider/tests/__init__.py +++ b/oauth2_provider/tests/__init__.py @@ -10,3 +10,4 @@ from .test_rest_framework import * from .test_application_views import * from .test_decorators import * +from .test_oauth2_backends import * diff --git a/oauth2_provider/tests/test_oauth2_backends.py b/oauth2_provider/tests/test_oauth2_backends.py new file mode 100644 index 000000000..44ec8145f --- /dev/null +++ b/oauth2_provider/tests/test_oauth2_backends.py @@ -0,0 +1,18 @@ +from django.test import TestCase, RequestFactory + + +from ..backends import get_oauthlib_core + + +class TestOAuthLibCore(TestCase): + def setUp(self): + self.factory = RequestFactory() + + def test_validate_authorization_request_unsafe_query(self): + auth_headers = { + 'HTTP_AUTHORIZATION': 'Bearer ' + "a_casual_token", + } + request = self.factory.get("/fake-resource?next=/fake", **auth_headers) + + oauthlib_core = get_oauthlib_core() + oauthlib_core.verify_request(request, scopes=[]) From f7437007686b8bff1dec48da233b5421fd56b430 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Tue, 10 Sep 2013 15:46:21 +0200 Subject: [PATCH 2/2] added method to quote oauthlib unsafe characters --- oauth2_provider/backends.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/oauth2_provider/backends.py b/oauth2_provider/backends.py index 5b74ecfec..fbe31b592 100644 --- a/oauth2_provider/backends.py +++ b/oauth2_provider/backends.py @@ -1,12 +1,13 @@ from oauthlib import oauth2 -from oauthlib.common import urlencode +from oauthlib.common import urlencode, urlencoded, quote from .exceptions import OAuthToolkitError, FatalClientError from .oauth2_validators import OAuth2Validator -import urlparse -from django.utils.http import urlquote -from django.utils.encoding import iri_to_uri +try: + from urlparse import urlparse, urlunparse +except ImportError: + from urllib.parse import urlparse, urlunparse class OAuthLibCore(object): @@ -20,13 +21,21 @@ def __init__(self, server=None): self.server = server or oauth2.Server(OAuth2Validator()) def _get_escaped_full_path(self, request): - uri = request.get_full_path() - return uri + """ + Django considers "safe" some characters that aren't so for oauthlib. We have to search for + them and properly escape. + """ + parsed = list(urlparse(request.get_full_path())) + unsafe = set(c for c in parsed[4]).difference(urlencoded) + for c in unsafe: + parsed[4] = parsed[4].replace(c, quote(c, safe='')) + + return urlunparse(parsed) 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 + 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 @@ -94,7 +103,8 @@ def create_token_response(self, request): """ uri, http_method, body, headers = self._extract_params(request) - url, headers, body, status = self.server.create_token_response(uri, http_method, body, headers) + url, headers, body, status = self.server.create_token_response(uri, http_method, body, + headers) return url, headers, body, status def verify_request(self, request, scopes): @@ -112,7 +122,8 @@ def verify_request(self, request, scopes): def get_oauthlib_core(): """ - Utility function that take a request and returns an instance of `oauth2_provider.backends.OAuthLibCore` + Utility function that take a request and returns an instance of + `oauth2_provider.backends.OAuthLibCore` """ from oauth2_provider.oauth2_validators import OAuth2Validator from oauthlib.oauth2 import Server