updates
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
from .authorization_server import BaseServer
|
||||
from .authorization_server import CacheAuthorizationServer
|
||||
from .resource_protector import ResourceProtector
|
||||
|
||||
__all__ = ["BaseServer", "CacheAuthorizationServer", "ResourceProtector"]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,128 @@
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponse
|
||||
|
||||
from authlib.common.security import generate_token
|
||||
from authlib.common.urls import url_encode
|
||||
from authlib.oauth1 import AuthorizationServer as _AuthorizationServer
|
||||
from authlib.oauth1 import OAuth1Request
|
||||
from authlib.oauth1 import TemporaryCredential
|
||||
|
||||
from .nonce import exists_nonce_in_cache
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseServer(_AuthorizationServer):
|
||||
def __init__(self, client_model, token_model, token_generator=None):
|
||||
self.client_model = client_model
|
||||
self.token_model = token_model
|
||||
|
||||
if token_generator is None:
|
||||
|
||||
def token_generator():
|
||||
return {
|
||||
"oauth_token": generate_token(42),
|
||||
"oauth_token_secret": generate_token(48),
|
||||
}
|
||||
|
||||
self.token_generator = token_generator
|
||||
self._config = getattr(settings, "AUTHLIB_OAUTH1_PROVIDER", {})
|
||||
self._nonce_expires_in = self._config.get("nonce_expires_in", 86400)
|
||||
methods = self._config.get("signature_methods")
|
||||
if methods:
|
||||
self.SUPPORTED_SIGNATURE_METHODS = methods
|
||||
|
||||
def get_client_by_id(self, client_id):
|
||||
try:
|
||||
return self.client_model.objects.get(client_id=client_id)
|
||||
except self.client_model.DoesNotExist:
|
||||
return None
|
||||
|
||||
def exists_nonce(self, nonce, request):
|
||||
return exists_nonce_in_cache(nonce, request, self._nonce_expires_in)
|
||||
|
||||
def create_token_credential(self, request):
|
||||
temporary_credential = request.credential
|
||||
token = self.token_generator()
|
||||
item = self.token_model(
|
||||
oauth_token=token["oauth_token"],
|
||||
oauth_token_secret=token["oauth_token_secret"],
|
||||
user_id=temporary_credential.get_user_id(),
|
||||
client_id=temporary_credential.get_client_id(),
|
||||
)
|
||||
item.save()
|
||||
return item
|
||||
|
||||
def check_authorization_request(self, request):
|
||||
req = self.create_oauth1_request(request)
|
||||
self.validate_authorization_request(req)
|
||||
return req
|
||||
|
||||
def create_oauth1_request(self, request):
|
||||
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)
|
||||
for k, v in headers:
|
||||
resp[k] = v
|
||||
return resp
|
||||
|
||||
|
||||
class CacheAuthorizationServer(BaseServer):
|
||||
def __init__(self, client_model, token_model, token_generator=None):
|
||||
super().__init__(client_model, token_model, token_generator)
|
||||
self._temporary_expires_in = self._config.get(
|
||||
"temporary_credential_expires_in", 86400
|
||||
)
|
||||
self._temporary_credential_key_prefix = self._config.get(
|
||||
"temporary_credential_key_prefix", "temporary_credential:"
|
||||
)
|
||||
|
||||
def create_temporary_credential(self, request):
|
||||
key_prefix = self._temporary_credential_key_prefix
|
||||
token = self.token_generator()
|
||||
|
||||
client_id = request.client_id
|
||||
redirect_uri = request.redirect_uri
|
||||
key = key_prefix + token["oauth_token"]
|
||||
token["client_id"] = client_id
|
||||
if redirect_uri:
|
||||
token["oauth_callback"] = redirect_uri
|
||||
|
||||
cache.set(key, token, timeout=self._temporary_expires_in)
|
||||
return TemporaryCredential(token)
|
||||
|
||||
def get_temporary_credential(self, request):
|
||||
if not request.token:
|
||||
return None
|
||||
|
||||
key_prefix = self._temporary_credential_key_prefix
|
||||
key = key_prefix + request.token
|
||||
value = cache.get(key)
|
||||
if value:
|
||||
return TemporaryCredential(value)
|
||||
|
||||
def delete_temporary_credential(self, request):
|
||||
if request.token:
|
||||
key_prefix = self._temporary_credential_key_prefix
|
||||
key = key_prefix + request.token
|
||||
cache.delete(key)
|
||||
|
||||
def create_authorization_verifier(self, request):
|
||||
key_prefix = self._temporary_credential_key_prefix
|
||||
verifier = generate_token(36)
|
||||
credential = request.credential
|
||||
user = request.user
|
||||
key = key_prefix + credential.get_oauth_token()
|
||||
credential["oauth_verifier"] = verifier
|
||||
credential["user_id"] = user.pk
|
||||
cache.set(key, credential, timeout=self._temporary_expires_in)
|
||||
return verifier
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
def exists_nonce_in_cache(nonce, request, timeout):
|
||||
key_prefix = "nonce:"
|
||||
timestamp = request.timestamp
|
||||
client_id = request.client_id
|
||||
token = request.token
|
||||
key = f"{key_prefix}{nonce}-{timestamp}-{client_id}"
|
||||
if token:
|
||||
key = f"{key}-{token}"
|
||||
|
||||
rv = bool(cache.get(key))
|
||||
cache.set(key, 1, timeout=timeout)
|
||||
return rv
|
||||
@@ -0,0 +1,68 @@
|
||||
import functools
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import JsonResponse
|
||||
|
||||
from authlib.oauth1 import ResourceProtector as _ResourceProtector
|
||||
from authlib.oauth1.errors import OAuth1Error
|
||||
|
||||
from .nonce import exists_nonce_in_cache
|
||||
|
||||
|
||||
class ResourceProtector(_ResourceProtector):
|
||||
def __init__(self, client_model, token_model):
|
||||
self.client_model = client_model
|
||||
self.token_model = token_model
|
||||
|
||||
config = getattr(settings, "AUTHLIB_OAUTH1_PROVIDER", {})
|
||||
methods = config.get("signature_methods", [])
|
||||
if methods and isinstance(methods, (list, tuple)):
|
||||
self.SUPPORTED_SIGNATURE_METHODS = methods
|
||||
|
||||
self._nonce_expires_in = config.get("nonce_expires_in", 86400)
|
||||
|
||||
def get_client_by_id(self, client_id):
|
||||
try:
|
||||
return self.client_model.objects.get(client_id=client_id)
|
||||
except self.client_model.DoesNotExist:
|
||||
return None
|
||||
|
||||
def get_token_credential(self, request):
|
||||
try:
|
||||
return self.token_model.objects.get(
|
||||
client_id=request.client_id, oauth_token=request.token
|
||||
)
|
||||
except self.token_model.DoesNotExist:
|
||||
return None
|
||||
|
||||
def exists_nonce(self, nonce, request):
|
||||
return exists_nonce_in_cache(nonce, request, self._nonce_expires_in)
|
||||
|
||||
def acquire_credential(self, request):
|
||||
if request.method in ["POST", "PUT"]:
|
||||
body = request.POST.dict()
|
||||
else:
|
||||
body = None
|
||||
|
||||
url = request.build_absolute_uri()
|
||||
req = self.validate_request(request.method, url, body, request.headers)
|
||||
return req.credential
|
||||
|
||||
def __call__(self, realm=None):
|
||||
def wrapper(f):
|
||||
@functools.wraps(f)
|
||||
def decorated(request, *args, **kwargs):
|
||||
try:
|
||||
credential = self.acquire_credential(request)
|
||||
request.oauth1_credential = credential
|
||||
except OAuth1Error as error:
|
||||
body = dict(error.get_body())
|
||||
resp = JsonResponse(body, status=error.status_code)
|
||||
resp["Cache-Control"] = "no-store"
|
||||
resp["Pragma"] = "no-cache"
|
||||
return resp
|
||||
return f(request, *args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
return wrapper
|
||||
Reference in New Issue
Block a user