diff --git a/oauth2app/authorize.py b/oauth2app/authorize.py index 5b563b0..c2e0548 100644 --- a/oauth2app/authorize.py +++ b/oauth2app/authorize.py @@ -5,11 +5,15 @@ import simplejson as json -from django.http import absolute_http_url_re, HttpResponse, HttpResponseRedirect, HttpResponseBadRequest from urllib import urlencode + +from django.http import absolute_http_url_re, HttpResponse, HttpResponseRedirect, HttpResponseBadRequest +from django.core.exceptions import SuspiciousOperation + from .consts import ACCESS_TOKEN_EXPIRATION, REFRESHABLE from .consts import CODE, TOKEN, CODE_AND_TOKEN from .consts import AUTHENTICATION_METHOD, MAC, BEARER, MAC_KEY_LENGTH +from .consts import REDIRECT_CLASS from .exceptions import OAuth2Exception from .lib.uri import add_parameters, add_fragments, normalize from .models import Client, AccessRange, Code, AccessToken, KeyGenerator @@ -195,7 +199,9 @@ def _validate(self): if self.authorized_response_type & RESPONSE_TYPES[self.response_type] == 0: raise UnauthorizedClient("Response type %s not allowed." % self.response_type) - if not absolute_http_url_re.match(self.redirect_uri): + try: + REDIRECT_CLASS(self.redirect_uri) + except SuspiciousOperation: raise InvalidRequest('Absolute URI required for redirect_uri') # Scope if self.authorized_scope is not None and self.scope is None: @@ -217,7 +223,7 @@ def _check_redirect_uri(self): if self.redirect_uri is None: raise MissingRedirectURI('No redirect_uri to send response.') if not absolute_http_url_re.match(self.redirect_uri): - raise MissingRedirectURI('Absolute redirect_uri required.') + raise MissingRedirectURI('Absolute redirect_uri required.') def error_redirect(self): """In the event of an error, return a Django HttpResponseRedirect @@ -313,7 +319,7 @@ def grant_redirect(self): parameters['state'] = self.state redirect_uri = add_parameters(self.redirect_uri, parameters) redirect_uri = add_fragments(redirect_uri, fragments) - return HttpResponseRedirect(redirect_uri) + return REDIRECT_CLASS(redirect_uri) else: raise UnauthenticatedUser("Django user object associated with the " "request is not authenticated.") diff --git a/oauth2app/consts.py b/oauth2app/consts.py index 1004271..582ae72 100644 --- a/oauth2app/consts.py +++ b/oauth2app/consts.py @@ -3,8 +3,11 @@ """OAuth 2.0 Default Values.""" +import sys from django.conf import settings +from django.http import HttpResponseRedirect + from .exceptions import OAuth2Exception @@ -51,4 +54,15 @@ # Grants code style parameters. CODE = 2 # Grants both style parameters. -CODE_AND_TOKEN = CODE | TOKEN \ No newline at end of file +CODE_AND_TOKEN = CODE | TOKEN +# redirect_class +REDIRECT_CLASS = getattr(settings, "OAUTH2_REDIRECT_CLASS", HttpResponseRedirect) +if isinstance(REDIRECT_CLASS, basestring): + pos = REDIRECT_CLASS.rfind('.') + module_name = REDIRECT_CLASS[:pos] + cls_name = REDIRECT_CLASS[pos+1:] + + __import__(module_name, {}, {}, []) + module = sys.modules[module_name] + + REDIRECT_CLASS = getattr(module, cls_name) diff --git a/oauth2app/lib/uri.py b/oauth2app/lib/uri.py index 9308cb5..fdde9fb 100644 --- a/oauth2app/lib/uri.py +++ b/oauth2app/lib/uri.py @@ -4,7 +4,7 @@ """OAuth 2.0 URI Helper Functions""" -from urlparse import urlparse, urlunparse, parse_qsl +from urlparse import urlparse, urlunparse, parse_qsl, uses_netloc from urllib import urlencode from url_normalize import url_normalize @@ -19,9 +19,12 @@ def add_parameters(url, parameters): *Returns str*""" parts = list(urlparse(url)) - parts[4] = urlencode(parse_qsl(parts[4]) + parameters.items()) - return urlunparse(parts) - + if parts[0] in uses_netloc: + parts[4] = urlencode(parse_qsl(parts[4]) + parameters.items()) + return urlunparse(parts) + else: + return '%s?%s' % (url, urlencode(parse_qsl(parts[4]) + parameters.items())) + def add_fragments(url, fragments): """Parses URL and appends fragments. @@ -33,9 +36,12 @@ def add_fragments(url, fragments): *Returns str*""" parts = list(urlparse(url)) - parts[5] = urlencode(parse_qsl(parts[5]) + fragments.items()) - return urlunparse(parts) - + if parts[0] in uses_netloc: + parts[5] = urlencode(parse_qsl(parts[5]) + fragments.items()) + return urlunparse(parts) + else: + return '%s#%s' % (url, urlencode(parse_qsl(parts[5]) + fragments.items())) + def normalize(url): """Normalizes URL. diff --git a/setup.py b/setup.py index 329956f..f3761c1 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ packages = find_packages(), - install_requires = ['Django>=1.2.3', 'simplejson>=2.1.5', "django-uni-form>=0.8.0"], + install_requires = ['Django>=1.2.3', 'simplejson>=2.1.5'], include_package_data = True, # metadata for upload to PyPI