forked from tobami/codespeed
-
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathauth.py
More file actions
80 lines (69 loc) · 3.14 KB
/
auth.py
File metadata and controls
80 lines (69 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import logging
import types
from functools import wraps
from django.contrib.auth import authenticate, login
from django.http import HttpResponse, HttpResponseForbidden
from django.conf import settings
from base64 import b64decode
__ALL__ = ['basic_auth_required']
logger = logging.getLogger(__name__)
def is_authenticated(request):
# NOTE: We do type check so we also support newer versions of Django when
# is_authenticated and some other methods have been properties
if isinstance(request.user.is_authenticated, (types.FunctionType,
types.MethodType)):
return request.user.is_authenticated()
elif isinstance(request.user.is_authenticated, bool):
return request.user.is_authenticated
else:
logger.info('Got unexpected type for request.user.is_authenticated '
'variable')
return False
def basic_auth_required(realm='default'):
def _helper(func):
@wraps(func)
def _decorator(request, *args, **kwargs):
allowed = False
logger.info('request is secure? {}'.format(request.is_secure()))
if settings.ALLOW_ANONYMOUS_POST:
logger.debug('allowing anonymous post')
allowed = True
elif hasattr(request, 'user') and is_authenticated(request=request):
allowed = True
elif 'HTTP_AUTHORIZATION' in request.META:
logger.debug('checking for http authorization header')
if settings.REQUIRE_SECURE_AUTH and not request.is_secure():
return insecure_connection_response()
http_auth = request.META['HTTP_AUTHORIZATION']
authmeth, auth = http_auth.split(' ', 1)
if authmeth.lower() == 'basic':
username, password = decode_basic_auth(auth)
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
logger.info(
'Authentication succeeded for {}'.format(username))
login(request, user)
allowed = True
else:
logger.info(
'Failed auth for {}'.format(username))
return HttpResponseForbidden()
if allowed:
return func(request, *args, **kwargs)
if settings.REQUIRE_SECURE_AUTH and not request.is_secure():
logger.debug('not requesting auth over an insecure channel')
return insecure_connection_response()
else:
res = HttpResponse()
res.status_code = 401
res.reason_phrase = 'Unauthorized'
res['WWW-Authenticate'] = 'Basic realm="{}"'.format(realm)
return res
return _decorator
return _helper
def insecure_connection_response():
return HttpResponseForbidden('Secure connection required')
def decode_basic_auth(auth):
authb = b64decode(auth.strip())
auth = authb.decode()
return auth.split(':', 1)