/
validators.py
168 lines (142 loc) · 4.88 KB
/
validators.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
"""
validators.py
App validators.
"""
import logging
import re
from datetime import datetime, timedelta
from flask_login import current_user
from flask_oauthlib.provider import OAuth2RequestValidator
from flask_oauthlib.utils import decode_base64
from mongoengine import DoesNotExist
from oauthlib.common import to_unicode
from app.models.user import User
from app.models.facebook import Facebook
from app.models.auth import Client, Grant, Token
def load_client(client_id):
try:
return Client.objects.get(client_id=client_id)
except DoesNotExist:
logging.info("Client not found.")
return None
def load_user(username, password, client, request, *args, **kwargs):
if re.match(r"[^@]+@[^@]+\.[^@]+", username):
if not client.has_password_credential_permission:
return None
try:
user = User.objects.get(email=username)
except DoesNotExist:
logging.info("User not found.")
return None
if not user.validate_password(password):
return None
return user
elif username.isdigit():
if not client.has_facebook_credential_permission:
return None
try:
facebook = Facebook(password)
me = facebook.get('/me', params={'fields': 'id,name,email,link'})
except client.OAuthException:
return None
try:
user = User.objects.get(facebook_id=username)
user.facebook_access_token = password
user.save()
except DoesNotExist:
facebook_id = me['id']
email = me['email']
name = me['name']
user = User(
facebook_id=facebook_id,
email=email,
name=name,
facebook_access_token=password,
password=None,
salt=None,
)
user.save()
return user
else:
logging.warning("Username not recognized.")
return None
def load_grant(client_id, code, *args, **kwargs):
return Grant.objects.get(client_id=client_id, code=code)
def save_grant(client_id, code, request, *args, **kwargs):
expires = datetime.utcnow() + timedelta(weeks=52)
user = User.objects.get(user_id=current_user.user_id)
grant = Grant(
client_id=client_id,
code=code['code'],
redirect_uri=request.redirect_uri,
_scopes=' '.join(request.scopes),
user=user,
user_id=user.user_id,
expires=expires
)
grant.save()
return grant
def load_token(access_token=None, refresh_token=None):
if access_token:
try:
return Token.objects.get(access_token=access_token)
except DoesNotExist:
logging.info("Access token not found.")
elif refresh_token:
try:
return Token.objects.get(refresh_token=refresh_token)
except DoesNotExist:
logging.info("Refresh token not found.")
return None
def save_token(token, request, *args, **kwargs):
user = request.user
toks = Token.objects(
client_id=request.client.client_id,
user_id=user.user_id
)
# make sure that every client has only one token connected to a user
for t in toks:
t.delete()
expires_in = token.pop('expires_in')
expires = datetime.utcnow() + timedelta(seconds=expires_in)
tok = Token(
access_token=token['access_token'],
refresh_token=token['refresh_token'],
token_type=token['token_type'],
_scopes=token['scope'],
expires=expires,
client_id=request.client.client_id,
user_id=user.user_id,
user=user
)
tok.save()
return tok
class RequestValidator(OAuth2RequestValidator):
def __init__(self):
self._usergetter = load_user
self._clientgetter = load_client
self._tokengetter = load_token
self._tokensetter = save_token
self._grantgetter = load_grant
self._grantsetter = save_grant
def authenticate_client(self, request, *args, **kwargs):
auth = request.headers.get('Authorization', None)
if auth:
try:
_, s = auth.split(' ')
client_id, client_secret = decode_base64(s).split(':')
client_id = to_unicode(client_id, 'utf-8')
except Exception as e:
logging.info('Authenticate client failed with exception: %r', e)
return False
else:
client_id = request.client_id
client = self._clientgetter(client_id)
if not client:
logging.info('Authenticate client failed, client not found.')
return False
if client.client_type == 'public':
return self.authenticate_client_id(client_id, request)
else:
return OAuth2RequestValidator.authenticate_client(
self, request, *args, **kwargs)