Skip to content

Commit

Permalink
Refactor Request object in OAuth 2
Browse files Browse the repository at this point in the history
- redesign OAuth2Request
- HttpRequest to JsonRequest
  • Loading branch information
lepture committed Dec 27, 2022
1 parent 2486f52 commit c060dab
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 177 deletions.
17 changes: 0 additions & 17 deletions authlib/integrations/django_helpers.py

This file was deleted.

8 changes: 6 additions & 2 deletions authlib/integrations/django_oauth1/authorization_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.conf import settings
from django.http import HttpResponse
from .nonce import exists_nonce_in_cache
from ..django_helpers import create_oauth_request

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -61,7 +60,12 @@ def check_authorization_request(self, request):
return req

def create_oauth1_request(self, request):
return create_oauth_request(request, OAuth1Request)
if request.method == 'POST':
body = request.POST.dict()
else:
body = None
url = request.build_absolute_uri()
return OAuth1Request(request.method, url, body, request.headers)

def handle_response(self, status_code, payload, headers):
resp = HttpResponse(url_encode(payload), status=status_code)
Expand Down
10 changes: 3 additions & 7 deletions authlib/integrations/django_oauth2/authorization_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
from django.utils.module_loading import import_string
from django.conf import settings
from authlib.oauth2 import (
OAuth2Request,
HttpRequest,
AuthorizationServer as _AuthorizationServer,
)
from authlib.oauth2.rfc6750 import BearerTokenGenerator
from authlib.common.security import generate_token as _generate_token
from authlib.common.encoding import json_dumps
from .requests import DjangoOAuth2Request, DjangoJsonRequest
from .signals import client_authenticated, token_revoked
from ..django_helpers import create_oauth_request


class AuthorizationServer(_AuthorizationServer):
Expand Down Expand Up @@ -59,12 +57,10 @@ def save_token(self, token, request):
return item

def create_oauth2_request(self, request):
return create_oauth_request(request, OAuth2Request)
return DjangoOAuth2Request(request)

def create_json_request(self, request):
req = create_oauth_request(request, HttpRequest, True)
req.user = request.user
return req
return DjangoJsonRequest(request)

def handle_response(self, status_code, payload, headers):
if isinstance(payload, dict):
Expand Down
35 changes: 35 additions & 0 deletions authlib/integrations/django_oauth2/requests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from django.http import HttpRequest
from django.utils.functional import cached_property
from authlib.common.encoding import json_loads
from authlib.oauth2.rfc6749 import OAuth2Request, JsonRequest


class DjangoOAuth2Request(OAuth2Request):
def __init__(self, request: HttpRequest):
super().__init__(request.method, request.build_absolute_uri(), None, request.headers)
self._request = request

@property
def args(self):
return self._request.GET

@property
def form(self):
return self._request.POST

@cached_property
def data(self):
data = {}
data.update(self._request.GET.dict())
data.update(self._request.POST.dict())
return data


class DjangoJsonRequest(JsonRequest):
def __init__(self, request: HttpRequest):
super().__init__(request.method, request.build_absolute_uri(), None, request.headers)
self._request = request

@cached_property
def data(self):
return json_loads(self._request.body)
6 changes: 2 additions & 4 deletions authlib/integrations/django_oauth2/resource_protector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
)
from authlib.oauth2.rfc6749 import (
MissingAuthorizationError,
HttpRequest,
)
from authlib.oauth2.rfc6750 import (
BearerTokenValidator as _BearerTokenValidator
)
from .requests import DjangoJsonRequest
from .signals import token_authenticated


Expand All @@ -22,9 +22,7 @@ def acquire_token(self, request, scopes=None):
:param scopes: a list of scope values
:return: token object
"""
url = request.build_absolute_uri()
req = HttpRequest(request.method, url, None, request.headers)
req.req = request
req = DjangoJsonRequest(request)
if isinstance(scopes, str):
scopes = [scopes]
token = self.validate_request(scopes, req)
Expand Down
25 changes: 0 additions & 25 deletions authlib/integrations/flask_helpers.py

This file was deleted.

14 changes: 8 additions & 6 deletions authlib/integrations/flask_oauth1/authorization_server.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import logging
from werkzeug.utils import import_string
from flask import Response
from flask import request as flask_req
from authlib.oauth1 import (
OAuth1Request,
AuthorizationServer as _AuthorizationServer,
)
from authlib.common.security import generate_token
from authlib.common.urls import url_encode
from ..flask_helpers import create_oauth_request

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -153,10 +153,6 @@ def create_token_credential(self, request):
'"create_token_credential" hook is required.'
)

def create_temporary_credentials_response(self, request=None):
return super(AuthorizationServer, self)\
.create_temporary_credentials_response(request)

def check_authorization_request(self):
req = self.create_oauth1_request(None)
self.validate_authorization_request(req)
Expand All @@ -170,7 +166,13 @@ def create_token_response(self, request=None):
return super(AuthorizationServer, self).create_token_response(request)

def create_oauth1_request(self, request):
return create_oauth_request(request, OAuth1Request)
if request is None:
request = flask_req
if request.method in ('POST', 'PUT'):
body = request.form.to_dict(flat=True)
else:
body = None
return OAuth1Request(request.method, request.url, body, request.headers)

def handle_response(self, status_code, payload, headers):
return Response(
Expand Down
9 changes: 4 additions & 5 deletions authlib/integrations/flask_oauth2/authorization_server.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from werkzeug.utils import import_string
from flask import Response, json
from flask import request as flask_req
from authlib.oauth2 import (
OAuth2Request,
HttpRequest,
AuthorizationServer as _AuthorizationServer,
)
from authlib.oauth2.rfc6750 import BearerTokenGenerator
from authlib.common.security import generate_token
from .requests import FlaskOAuth2Request, FlaskJsonRequest
from .signals import client_authenticated, token_revoked
from ..flask_helpers import create_oauth_request


class AuthorizationServer(_AuthorizationServer):
Expand Down Expand Up @@ -70,10 +69,10 @@ def get_error_uri(self, request, error):
return uris.get(error.error)

def create_oauth2_request(self, request):
return create_oauth_request(request, OAuth2Request)
return FlaskOAuth2Request(flask_req)

def create_json_request(self, request):
return create_oauth_request(request, HttpRequest, True)
return FlaskJsonRequest(flask_req)

def handle_response(self, status_code, payload, headers):
if isinstance(payload, dict):
Expand Down
30 changes: 30 additions & 0 deletions authlib/integrations/flask_oauth2/requests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from flask.wrappers import Request
from authlib.oauth2.rfc6749 import OAuth2Request, JsonRequest


class FlaskOAuth2Request(OAuth2Request):
def __init__(self, request: Request):
super().__init__(request.method, request.url, None, request.headers)
self._request = request

@property
def args(self):
return self._request.args

@property
def form(self):
return self._request.form

@property
def data(self):
return self._request.values


class FlaskJsonRequest(JsonRequest):
def __init__(self, request: Request):
super().__init__(request.method, request.url, None, request.headers)
self._request = request

@property
def data(self):
return self._request.get_json()
10 changes: 2 additions & 8 deletions authlib/integrations/flask_oauth2/resource_protector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
)
from authlib.oauth2.rfc6749 import (
MissingAuthorizationError,
HttpRequest,
)
from .requests import FlaskJsonRequest
from .signals import token_authenticated
from .errors import raise_http_exception

Expand Down Expand Up @@ -66,13 +66,7 @@ def acquire_token(self, scopes=None):
:param scopes: a list of scope values
:return: token object
"""
request = HttpRequest(
_req.method,
_req.full_path,
None,
_req.headers
)
request.req = _req
request = FlaskJsonRequest(_req)
# backward compatible
if isinstance(scopes, str):
scopes = [scopes]
Expand Down
7 changes: 4 additions & 3 deletions authlib/oauth2/rfc6749/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
https://tools.ietf.org/html/rfc6749
"""

from .requests import OAuth2Request
from .wrappers import OAuth2Token, HttpRequest
from .requests import OAuth2Request, JsonRequest
from .wrappers import OAuth2Token
from .errors import (
OAuth2Error,
AccessDeniedError,
Expand Down Expand Up @@ -48,7 +48,8 @@
from .util import scope_to_list, list_to_scope

__all__ = [
'OAuth2Request', 'OAuth2Token', 'HttpRequest',
'OAuth2Token',
'OAuth2Request', 'JsonRequest',
'OAuth2Error',
'AccessDeniedError',
'MissingAuthorizationError',
Expand Down
4 changes: 2 additions & 2 deletions authlib/oauth2/rfc6749/authorization_server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .authenticate_client import ClientAuthentication
from .requests import OAuth2Request
from .requests import OAuth2Request, JsonRequest
from .errors import (
OAuth2Error,
InvalidScopeError,
Expand Down Expand Up @@ -137,7 +137,7 @@ def create_oauth2_request(self, request) -> OAuth2Request:
"""
raise NotImplementedError()

def create_json_request(self, request):
def create_json_request(self, request) -> JsonRequest:
"""This method MUST be implemented in framework integrations. It is
used to create an HttpRequest instance.
Expand Down
28 changes: 18 additions & 10 deletions authlib/oauth2/rfc6749/requests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from authlib.common.encoding import json_loads
from authlib.common.urls import urlparse, url_decode
from .errors import InsecureTransportError

Expand All @@ -19,13 +20,10 @@ def __init__(self, method: str, uri: str, body=None, headers=None):
self.refresh_token = None
self.credential = None

@property
def query(self):
return urlparse.urlparse(self.uri).query

@property
def args(self):
return dict(url_decode(self.query))
query = urlparse.urlparse(self.uri).query
return dict(url_decode(query))

@property
def form(self):
Expand All @@ -47,13 +45,11 @@ def client_id(self) -> str:
:return: string
"""
if self.method == 'GET':
return self.args.get('client_id')
return self.form.get('client_id')
return self.data.get('client_id')

@property
def response_type(self) -> str:
rt = self.args.get('response_type')
rt = self.data.get('response_type')
if rt and ' ' in rt:
# sort multiple response types
return ' '.join(sorted(rt.split()))
Expand All @@ -73,4 +69,16 @@ def scope(self) -> str:

@property
def state(self):
return self.args.get('state')
return self.data.get('state')


class JsonRequest(object):
def __init__(self, method, uri, body=None, headers=None):
self.method = method
self.uri = uri
self.body = body
self.headers = headers or {}

@property
def data(self):
return json_loads(self.body)
Loading

0 comments on commit c060dab

Please sign in to comment.