-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.py
145 lines (119 loc) · 4.24 KB
/
auth.py
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# std:
import functools
# pip-int:
import dotsi
# pip-ext:
# n/a
# loc:
import bu
from constants import K
import utils
import userMod
############################################################
# Anti-CSRF related: #
############################################################
def genXCsrfToken(userId):
return bu.hasher.signWrap(
data=userId,
secret=K.ANTI_CSRF_SECRET,
)
def validateXCsrfToken(xCsrfToken, userId):
try:
# print("xCsrfToken = ", repr(xCsrfToken));
# print(bu.getCookie("userId"));
unwrappedUserId = bu.hasher.signUnwrap(
xCsrfToken,
secret=K.ANTI_CSRF_SECRET,
# ^-- Though we use `bu.hasher`, we specify overriding secret.
maxExpiryInDays=K.REMEMBER_ME_DAY_COUNT,
# ^-- This talks about signature-expiry, not cookie expiry.
# ^-- Note: Can set to 0 or 0.0001 to see XSRF validation being enforced.
)
except bu.hasher.SignatureInvalidError as e:
return bu.abort(
"1. X-CSRF validation failed. Please log out and then log back in."
)
# ==> No unwrapping error.
if unwrappedUserId != userId:
return bu.abort(
"2. X-CSRF validation failed. Please log out and then log back in."
)
# ==> Unwrapped data is as expected.
return True
############################################################
# Success response: #
############################################################
def setLoginSuccessCookies(user, rememberMe=False):
maxAge = None # Assumption
if rememberMe: # Correction
maxAge = K.REMEMBER_ME_DAY_COUNT * 24 * 60 * 60
# ^-- N days * 24 hrs * 60 mins * 60 sec => N days in sec
### 1st cookie, 'userId':
signWrapped = bu.setCookie(
name="userId",
data=user._id,
secret=K.AUTH_COOKIE_SECRET,
maxAge=maxAge,
)
### 2nd cookie, 'xCsrfToken':
xCsrfToken = genXCsrfToken(user._id)
bu.setUnsignedCookie(
name="xCsrfToken",
value=xCsrfToken,
httpOnly=False,
maxAge=maxAge,
)
return True
def sendAuthSuccessResponse(user, rememberMe=False):
# -- Deprecated, use setLoginSuccessCookies() instead.
setLoginSuccessCookies(user, rememberMe)
return {"user": userMod.snipUser(user)}
############################################################
# Getting current user etc. #
############################################################
def getSesh(strict=True, validateCsrf=None, req=None):
"Get sesh (session-like) object with current 'user' property."
req = req or bu.request
# Defaults to (global) bu.request.
if validateCsrf is None:
validateCsrf = bool(req.method != "GET")
# Default behavior: false for GET, else true.
# Check the 'userId' cookie:
userId = bu.getCookie(
"userId",
strict=strict,
secret=K.AUTH_COOKIE_SECRET,
req=req,
)
if not userId:
assert not strict
return dotsi.fy({"user": None})
# ==> Cookie found, signature valid.
assert userId
if validateCsrf:
# Ref: https://laravel.com/docs/5.8/csrf#csrf-x-csrf-token
xCsrfToken = req.headers.get("X-Csrf-Token")
assert validateXCsrfToken(xCsrfToken, userId)
# ==> CSRF TOKEN IS VALID.
# ==> CSRF PREVENTED, if applicable.
user = userMod.getUser(userId)
assert user and user.isVerified
# User shouldn't be able to log-in if not .isVerified. Asserting here.
if user.isDeactivated:
# XXX:Note: Below 'log out' should force CLI logout.
return bu.abort(
"ACCOUNT DEACTIVATED\n\n"
+ "Your account has been deactivated by your admin. "
+ "You shall now proceed to log out." # +
)
# ==> User exists, is verified, non-deactivated.
return dotsi.fy({"user": user})
def seshful(oldFunc):
"Decorator-style wrapper around getSesh()"
@functools.wraps(oldFunc)
def newFunc(*args, **kwargs):
sesh = getSesh()
return oldFunc(sesh=sesh, *args, **kwargs)
return newFunc
# pugmark:auth-mo
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx