root / snf-astakos-app / astakos / oa2 / backends / base.py @ 75e0551c
History | View | Annotate | Download (21 kB)
1 | 3fc7fd80 | Kostas Papadimitriou | import urllib |
---|---|---|---|
2 | 3fc7fd80 | Kostas Papadimitriou | import urlparse |
3 | 3fc7fd80 | Kostas Papadimitriou | import uuid |
4 | 3fc7fd80 | Kostas Papadimitriou | import datetime |
5 | 3fc7fd80 | Kostas Papadimitriou | import json |
6 | 3fc7fd80 | Kostas Papadimitriou | |
7 | 3fc7fd80 | Kostas Papadimitriou | from base64 import b64encode, b64decode |
8 | 3fc7fd80 | Kostas Papadimitriou | from hashlib import sha512 |
9 | e28a4841 | Sofia Papagiannaki | from time import time, mktime |
10 | e28a4841 | Sofia Papagiannaki | |
11 | 3fc7fd80 | Kostas Papadimitriou | |
12 | 3fc7fd80 | Kostas Papadimitriou | import logging |
13 | 3fc7fd80 | Kostas Papadimitriou | logger = logging.getLogger(__name__) |
14 | 3fc7fd80 | Kostas Papadimitriou | |
15 | 3fc7fd80 | Kostas Papadimitriou | |
16 | 3fc7fd80 | Kostas Papadimitriou | def handles_oa2_requests(func): |
17 | 3fc7fd80 | Kostas Papadimitriou | def wrapper(self, *args, **kwargs): |
18 | 3fc7fd80 | Kostas Papadimitriou | if not self._errors_to_http: |
19 | 3fc7fd80 | Kostas Papadimitriou | return func(self, *args, **kwargs) |
20 | 3fc7fd80 | Kostas Papadimitriou | try:
|
21 | 3fc7fd80 | Kostas Papadimitriou | return func(self, *args, **kwargs) |
22 | 3fc7fd80 | Kostas Papadimitriou | except OA2Error, e:
|
23 | 3fc7fd80 | Kostas Papadimitriou | return self.build_response_from_error(e) |
24 | 3fc7fd80 | Kostas Papadimitriou | return wrapper
|
25 | 3fc7fd80 | Kostas Papadimitriou | |
26 | 3fc7fd80 | Kostas Papadimitriou | |
27 | 3fc7fd80 | Kostas Papadimitriou | class OA2Error(Exception): |
28 | 3fc7fd80 | Kostas Papadimitriou | error = None
|
29 | 3fc7fd80 | Kostas Papadimitriou | |
30 | 3fc7fd80 | Kostas Papadimitriou | |
31 | 3fc7fd80 | Kostas Papadimitriou | class InvalidClientID(OA2Error): |
32 | 3fc7fd80 | Kostas Papadimitriou | pass
|
33 | 3fc7fd80 | Kostas Papadimitriou | |
34 | 3fc7fd80 | Kostas Papadimitriou | |
35 | 3fc7fd80 | Kostas Papadimitriou | class NotAuthenticatedError(OA2Error): |
36 | 3fc7fd80 | Kostas Papadimitriou | pass
|
37 | 3fc7fd80 | Kostas Papadimitriou | |
38 | 3fc7fd80 | Kostas Papadimitriou | |
39 | 3fc7fd80 | Kostas Papadimitriou | class InvalidClientRedirectUrl(OA2Error): |
40 | 3fc7fd80 | Kostas Papadimitriou | pass
|
41 | 3fc7fd80 | Kostas Papadimitriou | |
42 | 3fc7fd80 | Kostas Papadimitriou | |
43 | 3fc7fd80 | Kostas Papadimitriou | class InvalidAuthorizationRequest(OA2Error): |
44 | 3fc7fd80 | Kostas Papadimitriou | pass
|
45 | 3fc7fd80 | Kostas Papadimitriou | |
46 | 3fc7fd80 | Kostas Papadimitriou | |
47 | 3fc7fd80 | Kostas Papadimitriou | class Response(object): |
48 | 3fc7fd80 | Kostas Papadimitriou | |
49 | 3fc7fd80 | Kostas Papadimitriou | def __init__(self, status, body='', headers=None, |
50 | 3fc7fd80 | Kostas Papadimitriou | content_type='plain/text'):
|
51 | 3fc7fd80 | Kostas Papadimitriou | if not body: |
52 | 3fc7fd80 | Kostas Papadimitriou | body = ''
|
53 | 3fc7fd80 | Kostas Papadimitriou | if not headers: |
54 | 3fc7fd80 | Kostas Papadimitriou | headers = {} |
55 | 3fc7fd80 | Kostas Papadimitriou | |
56 | 3fc7fd80 | Kostas Papadimitriou | self.status = status
|
57 | 3fc7fd80 | Kostas Papadimitriou | self.body = body
|
58 | 3fc7fd80 | Kostas Papadimitriou | self.headers = headers
|
59 | 3fc7fd80 | Kostas Papadimitriou | self.content_type = content_type
|
60 | 3fc7fd80 | Kostas Papadimitriou | |
61 | 3fc7fd80 | Kostas Papadimitriou | def __repr__(self): |
62 | 3fc7fd80 | Kostas Papadimitriou | return "%d RESPONSE (BODY: %r, HEADERS: %r)" % (self.status, |
63 | 3fc7fd80 | Kostas Papadimitriou | self.body,
|
64 | 3fc7fd80 | Kostas Papadimitriou | self.headers)
|
65 | 3fc7fd80 | Kostas Papadimitriou | |
66 | 3fc7fd80 | Kostas Papadimitriou | |
67 | 3fc7fd80 | Kostas Papadimitriou | class Request(object): |
68 | 3fc7fd80 | Kostas Papadimitriou | |
69 | e28a4841 | Sofia Papagiannaki | def __init__(self, method, path, GET=None, POST=None, META=None, |
70 | e28a4841 | Sofia Papagiannaki | secure=False, user=None): |
71 | 3fc7fd80 | Kostas Papadimitriou | self.method = method
|
72 | e28a4841 | Sofia Papagiannaki | self.path = path
|
73 | 3fc7fd80 | Kostas Papadimitriou | |
74 | 3fc7fd80 | Kostas Papadimitriou | if not GET: |
75 | 3fc7fd80 | Kostas Papadimitriou | GET = {} |
76 | 3fc7fd80 | Kostas Papadimitriou | if not POST: |
77 | 3fc7fd80 | Kostas Papadimitriou | POST = {} |
78 | 3fc7fd80 | Kostas Papadimitriou | if not META: |
79 | 3fc7fd80 | Kostas Papadimitriou | META = {} |
80 | 3fc7fd80 | Kostas Papadimitriou | |
81 | 3fc7fd80 | Kostas Papadimitriou | self.secure = secure
|
82 | 3fc7fd80 | Kostas Papadimitriou | self.GET = GET
|
83 | 3fc7fd80 | Kostas Papadimitriou | self.POST = POST
|
84 | 3fc7fd80 | Kostas Papadimitriou | self.META = META
|
85 | 3fc7fd80 | Kostas Papadimitriou | self.user = user
|
86 | 3fc7fd80 | Kostas Papadimitriou | |
87 | 3fc7fd80 | Kostas Papadimitriou | def __repr__(self): |
88 | 3fc7fd80 | Kostas Papadimitriou | prepend = ""
|
89 | 3fc7fd80 | Kostas Papadimitriou | if self.secure: |
90 | 3fc7fd80 | Kostas Papadimitriou | prepend = "SECURE "
|
91 | 3fc7fd80 | Kostas Papadimitriou | return "%s%s REQUEST (POST: %r, GET:%r, HEADERS:%r, " % (prepend, |
92 | 3fc7fd80 | Kostas Papadimitriou | self.method,
|
93 | 3fc7fd80 | Kostas Papadimitriou | self.POST,
|
94 | 3fc7fd80 | Kostas Papadimitriou | self.GET,
|
95 | 3fc7fd80 | Kostas Papadimitriou | self.META)
|
96 | 3fc7fd80 | Kostas Papadimitriou | |
97 | 3fc7fd80 | Kostas Papadimitriou | |
98 | 3fc7fd80 | Kostas Papadimitriou | class ORMAbstractBase(type): |
99 | 3fc7fd80 | Kostas Papadimitriou | |
100 | 3fc7fd80 | Kostas Papadimitriou | def __new__(cls, name, bases, attrs): |
101 | 3fc7fd80 | Kostas Papadimitriou | attrs['ENTRIES'] = {}
|
102 | 3fc7fd80 | Kostas Papadimitriou | return super(ORMAbstractBase, cls).__new__(cls, name, bases, attrs) |
103 | 3fc7fd80 | Kostas Papadimitriou | |
104 | 3fc7fd80 | Kostas Papadimitriou | |
105 | 3fc7fd80 | Kostas Papadimitriou | class ORMAbstract(object): |
106 | 3fc7fd80 | Kostas Papadimitriou | |
107 | 3fc7fd80 | Kostas Papadimitriou | ENTRIES = {} |
108 | 3fc7fd80 | Kostas Papadimitriou | |
109 | 3fc7fd80 | Kostas Papadimitriou | __metaclass__ = ORMAbstractBase |
110 | 3fc7fd80 | Kostas Papadimitriou | |
111 | 3fc7fd80 | Kostas Papadimitriou | def __init__(self, **kwargs): |
112 | 3fc7fd80 | Kostas Papadimitriou | for key, value in kwargs.iteritems(): |
113 | 3fc7fd80 | Kostas Papadimitriou | setattr(self, key, value) |
114 | 3fc7fd80 | Kostas Papadimitriou | |
115 | 3fc7fd80 | Kostas Papadimitriou | @classmethod
|
116 | 3fc7fd80 | Kostas Papadimitriou | def create(cls, id, **params): |
117 | 3fc7fd80 | Kostas Papadimitriou | params = cls.clean_params(params) |
118 | 3fc7fd80 | Kostas Papadimitriou | params['id'] = id |
119 | 3fc7fd80 | Kostas Papadimitriou | cls.ENTRIES[id] = cls(**params)
|
120 | 3fc7fd80 | Kostas Papadimitriou | return cls.get(id) |
121 | 3fc7fd80 | Kostas Papadimitriou | |
122 | 3fc7fd80 | Kostas Papadimitriou | @classmethod
|
123 | 3fc7fd80 | Kostas Papadimitriou | def get(cls, pk): |
124 | 3fc7fd80 | Kostas Papadimitriou | return cls.ENTRIES.get(pk)
|
125 | 3fc7fd80 | Kostas Papadimitriou | |
126 | 3fc7fd80 | Kostas Papadimitriou | @classmethod
|
127 | 3fc7fd80 | Kostas Papadimitriou | def clean_params(cls, params): |
128 | 3fc7fd80 | Kostas Papadimitriou | return params
|
129 | 3fc7fd80 | Kostas Papadimitriou | |
130 | 3fc7fd80 | Kostas Papadimitriou | |
131 | 3fc7fd80 | Kostas Papadimitriou | class Client(ORMAbstract): |
132 | 3fc7fd80 | Kostas Papadimitriou | |
133 | 3fc7fd80 | Kostas Papadimitriou | def get_id(self): |
134 | 3fc7fd80 | Kostas Papadimitriou | return self.id |
135 | 3fc7fd80 | Kostas Papadimitriou | |
136 | 3fc7fd80 | Kostas Papadimitriou | def get_redirect_uris(self): |
137 | 3fc7fd80 | Kostas Papadimitriou | return self.uris |
138 | 3fc7fd80 | Kostas Papadimitriou | |
139 | 3fc7fd80 | Kostas Papadimitriou | def get_default_redirect_uri(self): |
140 | 3fc7fd80 | Kostas Papadimitriou | return self.uris[0] |
141 | 3fc7fd80 | Kostas Papadimitriou | |
142 | 3fc7fd80 | Kostas Papadimitriou | def redirect_uri_is_valid(self, redirect_uri): |
143 | 3fc7fd80 | Kostas Papadimitriou | split = urlparse.urlsplit(redirect_uri) |
144 | 3fc7fd80 | Kostas Papadimitriou | if split.scheme not in urlparse.uses_query: |
145 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid redirect url scheme") |
146 | 3fc7fd80 | Kostas Papadimitriou | uris = self.get_redirect_uris()
|
147 | 3fc7fd80 | Kostas Papadimitriou | return redirect_uri in uris |
148 | 3fc7fd80 | Kostas Papadimitriou | |
149 | 3fc7fd80 | Kostas Papadimitriou | def requires_auth(self): |
150 | 3fc7fd80 | Kostas Papadimitriou | if self.client_type == 'confidential': |
151 | 3fc7fd80 | Kostas Papadimitriou | return True |
152 | 3fc7fd80 | Kostas Papadimitriou | return 'secret' in dir(self) |
153 | 3fc7fd80 | Kostas Papadimitriou | |
154 | 3fc7fd80 | Kostas Papadimitriou | def check_credentials(self, username, secret): |
155 | 3fc7fd80 | Kostas Papadimitriou | return username == self.id and secret == self.secret |
156 | 3fc7fd80 | Kostas Papadimitriou | |
157 | 3fc7fd80 | Kostas Papadimitriou | |
158 | 3fc7fd80 | Kostas Papadimitriou | class Token(ORMAbstract): |
159 | 3fc7fd80 | Kostas Papadimitriou | |
160 | 3fc7fd80 | Kostas Papadimitriou | def to_dict(self): |
161 | 3fc7fd80 | Kostas Papadimitriou | params = { |
162 | 3fc7fd80 | Kostas Papadimitriou | 'access_token': self.token, |
163 | 3fc7fd80 | Kostas Papadimitriou | 'token_type': self.token_type, |
164 | 3fc7fd80 | Kostas Papadimitriou | 'expires_in': self.expires, |
165 | 3fc7fd80 | Kostas Papadimitriou | } |
166 | 3fc7fd80 | Kostas Papadimitriou | if self.refresh_token: |
167 | 3fc7fd80 | Kostas Papadimitriou | params['refresh_token'] = self.refresh_token |
168 | 3fc7fd80 | Kostas Papadimitriou | return params
|
169 | 3fc7fd80 | Kostas Papadimitriou | |
170 | 3fc7fd80 | Kostas Papadimitriou | |
171 | 3fc7fd80 | Kostas Papadimitriou | class AuthorizationCode(ORMAbstract): |
172 | 3fc7fd80 | Kostas Papadimitriou | pass
|
173 | 3fc7fd80 | Kostas Papadimitriou | |
174 | 3fc7fd80 | Kostas Papadimitriou | |
175 | 3fc7fd80 | Kostas Papadimitriou | class User(ORMAbstract): |
176 | 3fc7fd80 | Kostas Papadimitriou | pass
|
177 | 3fc7fd80 | Kostas Papadimitriou | |
178 | 3fc7fd80 | Kostas Papadimitriou | |
179 | 3fc7fd80 | Kostas Papadimitriou | class BackendBase(type): |
180 | 3fc7fd80 | Kostas Papadimitriou | |
181 | 3fc7fd80 | Kostas Papadimitriou | def __new__(cls, name, bases, attrs): |
182 | 3fc7fd80 | Kostas Papadimitriou | super_new = super(BackendBase, cls).__new__
|
183 | e28a4841 | Sofia Papagiannaki | #parents = [b for b in bases if isinstance(b, BackendBase)]
|
184 | e28a4841 | Sofia Papagiannaki | #meta = attrs.pop('Meta', None)
|
185 | 3fc7fd80 | Kostas Papadimitriou | return super_new(cls, name, bases, attrs)
|
186 | 3fc7fd80 | Kostas Papadimitriou | |
187 | 3fc7fd80 | Kostas Papadimitriou | @classmethod
|
188 | 3fc7fd80 | Kostas Papadimitriou | def get_orm_options(cls, attrs): |
189 | 3fc7fd80 | Kostas Papadimitriou | meta = attrs.pop('ORM', None) |
190 | 3fc7fd80 | Kostas Papadimitriou | orm = {} |
191 | 3fc7fd80 | Kostas Papadimitriou | if meta:
|
192 | 3fc7fd80 | Kostas Papadimitriou | for attr in dir(meta): |
193 | 3fc7fd80 | Kostas Papadimitriou | orm[attr] = getattr(meta, attr)
|
194 | 3fc7fd80 | Kostas Papadimitriou | return orm
|
195 | 3fc7fd80 | Kostas Papadimitriou | |
196 | 3fc7fd80 | Kostas Papadimitriou | |
197 | 3fc7fd80 | Kostas Papadimitriou | class SimpleBackend(object): |
198 | 3fc7fd80 | Kostas Papadimitriou | |
199 | 3fc7fd80 | Kostas Papadimitriou | __metaclass__ = BackendBase |
200 | 3fc7fd80 | Kostas Papadimitriou | |
201 | 3fc7fd80 | Kostas Papadimitriou | base_url = ''
|
202 | 3fc7fd80 | Kostas Papadimitriou | endpoints_prefix = '/oa2/'
|
203 | 3fc7fd80 | Kostas Papadimitriou | |
204 | 3fc7fd80 | Kostas Papadimitriou | token_endpoint = 'token/'
|
205 | 3fc7fd80 | Kostas Papadimitriou | token_length = 30
|
206 | e28a4841 | Sofia Papagiannaki | token_expires = 300
|
207 | 3fc7fd80 | Kostas Papadimitriou | |
208 | 3fc7fd80 | Kostas Papadimitriou | authorization_endpoint = 'auth/'
|
209 | 3fc7fd80 | Kostas Papadimitriou | authorization_code_length = 60
|
210 | 3fc7fd80 | Kostas Papadimitriou | authorization_response_types = ['code', 'token'] |
211 | 3fc7fd80 | Kostas Papadimitriou | |
212 | e28a4841 | Sofia Papagiannaki | grant_types = ['authorization_code']
|
213 | 3fc7fd80 | Kostas Papadimitriou | |
214 | 3fc7fd80 | Kostas Papadimitriou | response_cls = Response |
215 | 3fc7fd80 | Kostas Papadimitriou | request_cls = Request |
216 | 3fc7fd80 | Kostas Papadimitriou | |
217 | 3fc7fd80 | Kostas Papadimitriou | client_model = Client |
218 | 3fc7fd80 | Kostas Papadimitriou | token_model = Token |
219 | 3fc7fd80 | Kostas Papadimitriou | code_model = AuthorizationCode |
220 | 3fc7fd80 | Kostas Papadimitriou | user_model = User |
221 | 3fc7fd80 | Kostas Papadimitriou | |
222 | 3fc7fd80 | Kostas Papadimitriou | def __init__(self, base_url='', endpoints_prefix='/oa2/', id='oa2', |
223 | 3fc7fd80 | Kostas Papadimitriou | **kwargs): |
224 | 3fc7fd80 | Kostas Papadimitriou | self.base_url = base_url
|
225 | 3fc7fd80 | Kostas Papadimitriou | self.endpoints_prefix = endpoints_prefix
|
226 | 3fc7fd80 | Kostas Papadimitriou | self.id = id |
227 | 3fc7fd80 | Kostas Papadimitriou | self._errors_to_http = kwargs.get('errors_to_http', True) |
228 | 3fc7fd80 | Kostas Papadimitriou | |
229 | 3fc7fd80 | Kostas Papadimitriou | # Request/response builders
|
230 | 3fc7fd80 | Kostas Papadimitriou | def build_request(self, method, get, post, meta): |
231 | 3fc7fd80 | Kostas Papadimitriou | return self.request_cls(method=method, GET=get, POST=post, META=meta) |
232 | 3fc7fd80 | Kostas Papadimitriou | |
233 | 3fc7fd80 | Kostas Papadimitriou | def build_response(self, status, headers=None, body=''): |
234 | 3fc7fd80 | Kostas Papadimitriou | return self.response_cls(status=status, headers=headers, body=body) |
235 | 3fc7fd80 | Kostas Papadimitriou | |
236 | 3fc7fd80 | Kostas Papadimitriou | # ORM Methods
|
237 | e28a4841 | Sofia Papagiannaki | def create_authorization_code(self, user, client, code, redirect_uri, |
238 | e28a4841 | Sofia Papagiannaki | scope, state, **kwargs): |
239 | 3fc7fd80 | Kostas Papadimitriou | code_params = { |
240 | 3fc7fd80 | Kostas Papadimitriou | 'code': code,
|
241 | 3fc7fd80 | Kostas Papadimitriou | 'redirect_uri': redirect_uri,
|
242 | e28a4841 | Sofia Papagiannaki | 'client': client,
|
243 | 3fc7fd80 | Kostas Papadimitriou | 'scope': scope,
|
244 | e28a4841 | Sofia Papagiannaki | 'state': state,
|
245 | e28a4841 | Sofia Papagiannaki | 'user': user
|
246 | 3fc7fd80 | Kostas Papadimitriou | } |
247 | 3fc7fd80 | Kostas Papadimitriou | code_params.update(kwargs) |
248 | e28a4841 | Sofia Papagiannaki | code_instance = self.code_model.create(**code_params)
|
249 | e28a4841 | Sofia Papagiannaki | logger.info('%r created' % code_instance)
|
250 | e28a4841 | Sofia Papagiannaki | return code_instance
|
251 | 3fc7fd80 | Kostas Papadimitriou | |
252 | e28a4841 | Sofia Papagiannaki | def _token_params(self, value, token_type, authorization, scope): |
253 | 3fc7fd80 | Kostas Papadimitriou | created_at = datetime.datetime.now() |
254 | 3fc7fd80 | Kostas Papadimitriou | expires = self.token_expires
|
255 | 3fc7fd80 | Kostas Papadimitriou | expires_at = created_at + datetime.timedelta(seconds=expires) |
256 | 3fc7fd80 | Kostas Papadimitriou | token_params = { |
257 | e28a4841 | Sofia Papagiannaki | 'code': value,
|
258 | 3fc7fd80 | Kostas Papadimitriou | 'token_type': token_type,
|
259 | 3fc7fd80 | Kostas Papadimitriou | 'created_at': created_at,
|
260 | e28a4841 | Sofia Papagiannaki | 'expires_at': expires_at,
|
261 | e28a4841 | Sofia Papagiannaki | 'user': authorization.user,
|
262 | e28a4841 | Sofia Papagiannaki | 'redirect_uri': authorization.redirect_uri,
|
263 | e28a4841 | Sofia Papagiannaki | 'client': authorization.client,
|
264 | e28a4841 | Sofia Papagiannaki | 'scope': authorization.scope,
|
265 | 3fc7fd80 | Kostas Papadimitriou | } |
266 | 3fc7fd80 | Kostas Papadimitriou | return token_params
|
267 | 3fc7fd80 | Kostas Papadimitriou | |
268 | e28a4841 | Sofia Papagiannaki | def create_token(self, value, token_type, authorization, scope, |
269 | e28a4841 | Sofia Papagiannaki | refresh=False):
|
270 | e28a4841 | Sofia Papagiannaki | params = self._token_params(value, token_type, authorization, scope)
|
271 | 3fc7fd80 | Kostas Papadimitriou | if refresh:
|
272 | 3fc7fd80 | Kostas Papadimitriou | refresh_token = self.generate_token()
|
273 | 3fc7fd80 | Kostas Papadimitriou | params['refresh_token'] = refresh_token
|
274 | 3fc7fd80 | Kostas Papadimitriou | # TODO: refresh token expires ???
|
275 | e28a4841 | Sofia Papagiannaki | token = self.token_model.create(**params)
|
276 | e28a4841 | Sofia Papagiannaki | logger.info('%r created' % token)
|
277 | e28a4841 | Sofia Papagiannaki | return token
|
278 | 3fc7fd80 | Kostas Papadimitriou | |
279 | e28a4841 | Sofia Papagiannaki | # def delete_authorization_code(self, code):
|
280 | e28a4841 | Sofia Papagiannaki | # del self.code_model.ENTRIES[code]
|
281 | 3fc7fd80 | Kostas Papadimitriou | |
282 | 3fc7fd80 | Kostas Papadimitriou | def get_client_by_id(self, client_id): |
283 | 3fc7fd80 | Kostas Papadimitriou | return self.client_model.get(client_id) |
284 | 3fc7fd80 | Kostas Papadimitriou | |
285 | 3fc7fd80 | Kostas Papadimitriou | def get_client_by_credentials(self, username, password): |
286 | 3fc7fd80 | Kostas Papadimitriou | return None |
287 | 3fc7fd80 | Kostas Papadimitriou | |
288 | 3fc7fd80 | Kostas Papadimitriou | def get_authorization_code(self, code): |
289 | 3fc7fd80 | Kostas Papadimitriou | return self.code_model.get(code) |
290 | 3fc7fd80 | Kostas Papadimitriou | |
291 | 3fc7fd80 | Kostas Papadimitriou | def get_client_authorization_code(self, client, code): |
292 | 3fc7fd80 | Kostas Papadimitriou | code_instance = self.get_authorization_code(code)
|
293 | 3fc7fd80 | Kostas Papadimitriou | if not code_instance: |
294 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid code", code) |
295 | 3fc7fd80 | Kostas Papadimitriou | |
296 | e28a4841 | Sofia Papagiannaki | if client.get_id() != code_instance.client.get_id():
|
297 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid code for client", code, client) |
298 | 3fc7fd80 | Kostas Papadimitriou | return code_instance
|
299 | 3fc7fd80 | Kostas Papadimitriou | |
300 | 3fc7fd80 | Kostas Papadimitriou | def client_id_exists(self, client_id): |
301 | 3fc7fd80 | Kostas Papadimitriou | return bool(self.get_client_by_id(client_id)) |
302 | 3fc7fd80 | Kostas Papadimitriou | |
303 | 3fc7fd80 | Kostas Papadimitriou | def build_site_url(self, prefix='', **params): |
304 | 3fc7fd80 | Kostas Papadimitriou | params = urllib.urlencode(params) |
305 | 3fc7fd80 | Kostas Papadimitriou | return "%s%s%s%s" % (self.base_url, self.endpoints_prefix, prefix, |
306 | 3fc7fd80 | Kostas Papadimitriou | params) |
307 | 3fc7fd80 | Kostas Papadimitriou | |
308 | 3fc7fd80 | Kostas Papadimitriou | def _get_uri_base(self, uri): |
309 | 3fc7fd80 | Kostas Papadimitriou | split = urlparse.urlsplit(uri) |
310 | 3fc7fd80 | Kostas Papadimitriou | return "%s://%s%s" % (split.scheme, split.netloc, split.path) |
311 | 3fc7fd80 | Kostas Papadimitriou | |
312 | 3fc7fd80 | Kostas Papadimitriou | def build_client_redirect_uri(self, client, uri, **params): |
313 | 3fc7fd80 | Kostas Papadimitriou | if not client.redirect_uri_is_valid(uri): |
314 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid redirect uri") |
315 | 3fc7fd80 | Kostas Papadimitriou | params = urllib.urlencode(params) |
316 | 3fc7fd80 | Kostas Papadimitriou | uri = self._get_uri_base(uri)
|
317 | 3fc7fd80 | Kostas Papadimitriou | return "%s?%s" % (uri, params) |
318 | 3fc7fd80 | Kostas Papadimitriou | |
319 | 3fc7fd80 | Kostas Papadimitriou | def generate_authorization_code(self): |
320 | 3fc7fd80 | Kostas Papadimitriou | dg64 = b64encode(sha512(str(uuid.uuid4())).hexdigest())
|
321 | 3fc7fd80 | Kostas Papadimitriou | return dg64[:self.authorization_code_length] |
322 | 3fc7fd80 | Kostas Papadimitriou | |
323 | 3fc7fd80 | Kostas Papadimitriou | def generate_token(self, *args, **kwargs): |
324 | 3fc7fd80 | Kostas Papadimitriou | dg64 = b64encode(sha512(str(uuid.uuid4())).hexdigest())
|
325 | 3fc7fd80 | Kostas Papadimitriou | return dg64[:self.token_length] |
326 | 3fc7fd80 | Kostas Papadimitriou | |
327 | 3fc7fd80 | Kostas Papadimitriou | def add_authorization_code(self, user, client, redirect_uri, scope, state, |
328 | 3fc7fd80 | Kostas Papadimitriou | **kwargs): |
329 | 3fc7fd80 | Kostas Papadimitriou | code = self.generate_authorization_code()
|
330 | 3fc7fd80 | Kostas Papadimitriou | self.create_authorization_code(user, client, code, redirect_uri, scope,
|
331 | 3fc7fd80 | Kostas Papadimitriou | state, **kwargs) |
332 | 3fc7fd80 | Kostas Papadimitriou | return code
|
333 | 3fc7fd80 | Kostas Papadimitriou | |
334 | e28a4841 | Sofia Papagiannaki | def add_token_for_client(self, token_type, authorization, refresh=False): |
335 | e28a4841 | Sofia Papagiannaki | token = self.generate_token()
|
336 | e28a4841 | Sofia Papagiannaki | self.create_token(token, token_type, authorization, refresh)
|
337 | e28a4841 | Sofia Papagiannaki | return token
|
338 | e28a4841 | Sofia Papagiannaki | |
339 | 3fc7fd80 | Kostas Papadimitriou | #
|
340 | 3fc7fd80 | Kostas Papadimitriou | # Response helpers
|
341 | 3fc7fd80 | Kostas Papadimitriou | #
|
342 | 3fc7fd80 | Kostas Papadimitriou | |
343 | e28a4841 | Sofia Papagiannaki | def grant_accept_response(self, client, redirect_uri, scope, state): |
344 | 3fc7fd80 | Kostas Papadimitriou | context = {'client': client.get_id(), 'redirect_uri': redirect_uri, |
345 | e28a4841 | Sofia Papagiannaki | 'scope': scope, 'state': state, |
346 | e28a4841 | Sofia Papagiannaki | #'url': url,
|
347 | e28a4841 | Sofia Papagiannaki | } |
348 | e28a4841 | Sofia Papagiannaki | json_content = json.dumps(context) |
349 | e28a4841 | Sofia Papagiannaki | return self.response_cls(status=200, body=json_content) |
350 | e28a4841 | Sofia Papagiannaki | |
351 | e28a4841 | Sofia Papagiannaki | def grant_token_response(self, token, token_type): |
352 | e28a4841 | Sofia Papagiannaki | context = {'access_token': token, 'token_type': token_type, |
353 | e28a4841 | Sofia Papagiannaki | 'expires_in': self.token_expires} |
354 | 3fc7fd80 | Kostas Papadimitriou | json_content = json.dumps(context) |
355 | 3fc7fd80 | Kostas Papadimitriou | return self.response_cls(status=200, body=json_content) |
356 | 3fc7fd80 | Kostas Papadimitriou | |
357 | e28a4841 | Sofia Papagiannaki | def redirect_to_login_response(self, request, params): |
358 | e28a4841 | Sofia Papagiannaki | parts = list(urlparse.urlsplit(request.path))
|
359 | e28a4841 | Sofia Papagiannaki | parts[3] = urllib.urlencode(params)
|
360 | e28a4841 | Sofia Papagiannaki | query = {'next': urlparse.urlunsplit(parts)}
|
361 | e28a4841 | Sofia Papagiannaki | return Response(302, |
362 | e28a4841 | Sofia Papagiannaki | headers={'Location': '%s?%s' % |
363 | e28a4841 | Sofia Papagiannaki | (self.get_login_uri(),
|
364 | e28a4841 | Sofia Papagiannaki | urllib.urlencode(query))}) |
365 | e28a4841 | Sofia Papagiannaki | |
366 | e28a4841 | Sofia Papagiannaki | def redirect_to_uri(self, redirect_uri, code, state=None): |
367 | e28a4841 | Sofia Papagiannaki | parts = list(urlparse.urlsplit(redirect_uri))
|
368 | e28a4841 | Sofia Papagiannaki | params = dict(urlparse.parse_qsl(parts[3], keep_blank_values=True)) |
369 | e28a4841 | Sofia Papagiannaki | params['code'] = code
|
370 | e28a4841 | Sofia Papagiannaki | if state is not None: |
371 | e28a4841 | Sofia Papagiannaki | params['state'] = state
|
372 | e28a4841 | Sofia Papagiannaki | parts[3] = urllib.urlencode(params)
|
373 | e28a4841 | Sofia Papagiannaki | return Response(302, |
374 | e28a4841 | Sofia Papagiannaki | headers={'Location': '%s' % |
375 | e28a4841 | Sofia Papagiannaki | urlparse.urlunsplit(parts)}) |
376 | 3fc7fd80 | Kostas Papadimitriou | |
377 | 3fc7fd80 | Kostas Papadimitriou | def build_response_from_error(self, exception): |
378 | 3fc7fd80 | Kostas Papadimitriou | response = Response(400)
|
379 | 3fc7fd80 | Kostas Papadimitriou | logger.exception(exception) |
380 | 3fc7fd80 | Kostas Papadimitriou | error = 'generic_error'
|
381 | 3fc7fd80 | Kostas Papadimitriou | if exception.error:
|
382 | 3fc7fd80 | Kostas Papadimitriou | error = exception.error |
383 | 3fc7fd80 | Kostas Papadimitriou | body = { |
384 | 3fc7fd80 | Kostas Papadimitriou | 'error': error,
|
385 | 3fc7fd80 | Kostas Papadimitriou | 'exception': exception.message,
|
386 | 3fc7fd80 | Kostas Papadimitriou | } |
387 | 3fc7fd80 | Kostas Papadimitriou | response.body = json.dumps(body) |
388 | 3fc7fd80 | Kostas Papadimitriou | response.content_type = "application/json"
|
389 | 3fc7fd80 | Kostas Papadimitriou | return response
|
390 | 3fc7fd80 | Kostas Papadimitriou | |
391 | 3fc7fd80 | Kostas Papadimitriou | #
|
392 | 3fc7fd80 | Kostas Papadimitriou | # Processor methods
|
393 | 3fc7fd80 | Kostas Papadimitriou | #
|
394 | 3fc7fd80 | Kostas Papadimitriou | |
395 | e28a4841 | Sofia Papagiannaki | def process_code_request(self, user, client, uri, scope, state): |
396 | e28a4841 | Sofia Papagiannaki | code = self.add_authorization_code(user, client, uri, scope, state)
|
397 | e28a4841 | Sofia Papagiannaki | return self.redirect_to_uri(uri, code, state) |
398 | 3fc7fd80 | Kostas Papadimitriou | |
399 | 3fc7fd80 | Kostas Papadimitriou | #
|
400 | 3fc7fd80 | Kostas Papadimitriou | # Helpers
|
401 | 3fc7fd80 | Kostas Papadimitriou | #
|
402 | 3fc7fd80 | Kostas Papadimitriou | |
403 | e28a4841 | Sofia Papagiannaki | def grant_authorization_code(self, client, code_instance, redirect_uri, |
404 | e28a4841 | Sofia Papagiannaki | scope=None, token_type="Bearer"): |
405 | e28a4841 | Sofia Papagiannaki | if scope and code_instance.scope != scope: |
406 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Invalid scope") |
407 | e28a4841 | Sofia Papagiannaki | if redirect_uri != code_instance.redirect_uri:
|
408 | e28a4841 | Sofia Papagiannaki | raise OA2Error("The redirect uri does not match " |
409 | e28a4841 | Sofia Papagiannaki | "the one used during authorization")
|
410 | e28a4841 | Sofia Papagiannaki | token = self.add_token_for_client(token_type, code_instance)
|
411 | e28a4841 | Sofia Papagiannaki | self.delete_authorization_code(code_instance) # use only once |
412 | e28a4841 | Sofia Papagiannaki | return token, token_type
|
413 | e28a4841 | Sofia Papagiannaki | |
414 | e28a4841 | Sofia Papagiannaki | def consume_token(self, token): |
415 | e28a4841 | Sofia Papagiannaki | token_instance = self.get_token(token)
|
416 | e28a4841 | Sofia Papagiannaki | expires_at = mktime(token_instance.expires_at.timetuple()) |
417 | e28a4841 | Sofia Papagiannaki | if time() > expires_at:
|
418 | e28a4841 | Sofia Papagiannaki | self.delete_token(token_instance) # delete expired token |
419 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Token has expired") |
420 | e28a4841 | Sofia Papagiannaki | # TODO: delete token?
|
421 | e28a4841 | Sofia Papagiannaki | return token_instance
|
422 | e28a4841 | Sofia Papagiannaki | |
423 | 3fc7fd80 | Kostas Papadimitriou | def _get_credentials(self, params, headers): |
424 | 3fc7fd80 | Kostas Papadimitriou | if 'HTTP_AUTHORIZATION' in headers: |
425 | 3fc7fd80 | Kostas Papadimitriou | scheme, b64credentials = headers.get( |
426 | 3fc7fd80 | Kostas Papadimitriou | 'HTTP_AUTHORIZATION').split(" ") |
427 | e28a4841 | Sofia Papagiannaki | if scheme != 'Basic': |
428 | e28a4841 | Sofia Papagiannaki | # TODO: raise 401 + WWW-Authenticate
|
429 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Unsupported authorization scheme") |
430 | 3fc7fd80 | Kostas Papadimitriou | credentials = b64decode(b64credentials).split(":")
|
431 | 3fc7fd80 | Kostas Papadimitriou | return scheme, credentials
|
432 | 3fc7fd80 | Kostas Papadimitriou | else:
|
433 | 3fc7fd80 | Kostas Papadimitriou | return None, None |
434 | 3fc7fd80 | Kostas Papadimitriou | pass
|
435 | 3fc7fd80 | Kostas Papadimitriou | |
436 | e28a4841 | Sofia Papagiannaki | def _get_authorization(self, params, headers): |
437 | e28a4841 | Sofia Papagiannaki | scheme, client_credentials = self._get_credentials(params, headers)
|
438 | e28a4841 | Sofia Papagiannaki | no_authorization = scheme is None and client_credentials is None |
439 | e28a4841 | Sofia Papagiannaki | if no_authorization:
|
440 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Missing authorization header") |
441 | e28a4841 | Sofia Papagiannaki | return client_credentials
|
442 | e28a4841 | Sofia Papagiannaki | |
443 | 3fc7fd80 | Kostas Papadimitriou | def get_redirect_uri_from_params(self, client, params, default=True): |
444 | 3fc7fd80 | Kostas Papadimitriou | """
|
445 | 3fc7fd80 | Kostas Papadimitriou | Accepts a client instance and request parameters.
|
446 | 3fc7fd80 | Kostas Papadimitriou | """
|
447 | 3fc7fd80 | Kostas Papadimitriou | redirect_uri = params.get('redirect_uri', None) |
448 | 3fc7fd80 | Kostas Papadimitriou | if not redirect_uri and default: |
449 | 3fc7fd80 | Kostas Papadimitriou | redirect_uri = client.get_default_redirect_uri() |
450 | 3fc7fd80 | Kostas Papadimitriou | else:
|
451 | 3fc7fd80 | Kostas Papadimitriou | # TODO: sanitize redirect_uri (self.clean_redirect_uri ???)
|
452 | 3fc7fd80 | Kostas Papadimitriou | # clean and validate
|
453 | 3fc7fd80 | Kostas Papadimitriou | if not client.redirect_uri_is_valid(redirect_uri): |
454 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid client redirect uri") |
455 | 3fc7fd80 | Kostas Papadimitriou | return redirect_uri
|
456 | 3fc7fd80 | Kostas Papadimitriou | |
457 | 3fc7fd80 | Kostas Papadimitriou | #
|
458 | e28a4841 | Sofia Papagiannaki | # Request identifiers
|
459 | 3fc7fd80 | Kostas Papadimitriou | #
|
460 | 3fc7fd80 | Kostas Papadimitriou | |
461 | e28a4841 | Sofia Papagiannaki | def identify_authorize_request(self, params, headers): |
462 | e28a4841 | Sofia Papagiannaki | return params.get('response_type'), params |
463 | 3fc7fd80 | Kostas Papadimitriou | |
464 | e28a4841 | Sofia Papagiannaki | def identify_token_request(self, headers, params): |
465 | e28a4841 | Sofia Papagiannaki | content_type = headers.get('CONTENT_TYPE')
|
466 | e28a4841 | Sofia Papagiannaki | if content_type != 'application/x-www-form-urlencoded': |
467 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Invalid Content-Type header") |
468 | e28a4841 | Sofia Papagiannaki | return params.get('grant_type') |
469 | 3fc7fd80 | Kostas Papadimitriou | |
470 | e28a4841 | Sofia Papagiannaki | #
|
471 | e28a4841 | Sofia Papagiannaki | # Parameters validation methods
|
472 | e28a4841 | Sofia Papagiannaki | #
|
473 | 3fc7fd80 | Kostas Papadimitriou | |
474 | e28a4841 | Sofia Papagiannaki | def validate_client(self, params, meta, requires_auth=True, |
475 | e28a4841 | Sofia Papagiannaki | client_id_required=True):
|
476 | e28a4841 | Sofia Papagiannaki | client_id = params.get('client_id')
|
477 | e28a4841 | Sofia Papagiannaki | if client_id is None and client_id_required: |
478 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Client identification is required") |
479 | e28a4841 | Sofia Papagiannaki | |
480 | e28a4841 | Sofia Papagiannaki | client_credentials = None
|
481 | e28a4841 | Sofia Papagiannaki | try: # check authorization header |
482 | e28a4841 | Sofia Papagiannaki | client_credentials = self._get_authorization(params, meta)
|
483 | e28a4841 | Sofia Papagiannaki | if client_credentials is not None: |
484 | e28a4841 | Sofia Papagiannaki | _client_id = client_credentials[0]
|
485 | e28a4841 | Sofia Papagiannaki | if client_id is not None and client_id != _client_id: |
486 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Client identification conflicts " |
487 | e28a4841 | Sofia Papagiannaki | "with client authorization")
|
488 | e28a4841 | Sofia Papagiannaki | client_id = _client_id |
489 | e28a4841 | Sofia Papagiannaki | except:
|
490 | e28a4841 | Sofia Papagiannaki | pass
|
491 | e28a4841 | Sofia Papagiannaki | |
492 | e28a4841 | Sofia Papagiannaki | if client_id is None: |
493 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Missing client identification") |
494 | e28a4841 | Sofia Papagiannaki | |
495 | e28a4841 | Sofia Papagiannaki | client = self.get_client_by_id(client_id)
|
496 | e28a4841 | Sofia Papagiannaki | |
497 | e28a4841 | Sofia Papagiannaki | if requires_auth and client.requires_auth: |
498 | e28a4841 | Sofia Papagiannaki | if client_credentials is None: |
499 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Client authentication in required") |
500 | e28a4841 | Sofia Papagiannaki | |
501 | e28a4841 | Sofia Papagiannaki | if client_credentials is not None: |
502 | e28a4841 | Sofia Papagiannaki | self.check_credentials(client, *client_credentials)
|
503 | e28a4841 | Sofia Papagiannaki | return client
|
504 | e28a4841 | Sofia Papagiannaki | |
505 | e28a4841 | Sofia Papagiannaki | def validate_redirect_uri(self, client, params, headers, |
506 | e28a4841 | Sofia Papagiannaki | allow_default=True, is_required=False, |
507 | e28a4841 | Sofia Papagiannaki | expected_value=None):
|
508 | e28a4841 | Sofia Papagiannaki | redirect_uri = params.get('redirect_uri')
|
509 | e28a4841 | Sofia Papagiannaki | if is_required and redirect_uri is None: |
510 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Missing redirect uri") |
511 | e28a4841 | Sofia Papagiannaki | if redirect_uri is not None: |
512 | e28a4841 | Sofia Papagiannaki | if not bool(urlparse.urlparse(redirect_uri).scheme): |
513 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Redirect uri should be an absolute URI") |
514 | e28a4841 | Sofia Papagiannaki | if not client.redirect_uri_is_valid(redirect_uri): |
515 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Mismatching redirect uri") |
516 | e28a4841 | Sofia Papagiannaki | if expected_value is not None and redirect_uri != expected_value: |
517 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Invalid redirect uri") |
518 | e28a4841 | Sofia Papagiannaki | return redirect_uri
|
519 | e28a4841 | Sofia Papagiannaki | |
520 | e28a4841 | Sofia Papagiannaki | def validate_state(self, client, params, headers): |
521 | e28a4841 | Sofia Papagiannaki | return params.get('state') |
522 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid state") |
523 | 3fc7fd80 | Kostas Papadimitriou | |
524 | e28a4841 | Sofia Papagiannaki | def validate_scope(self, client, params, headers): |
525 | e28a4841 | Sofia Papagiannaki | scope = params.get('scope')
|
526 | e28a4841 | Sofia Papagiannaki | if scope is not None: |
527 | e28a4841 | Sofia Papagiannaki | scope = scope.split(' ')[0] # keep only the first |
528 | e28a4841 | Sofia Papagiannaki | # TODO: check for invalid characters
|
529 | e28a4841 | Sofia Papagiannaki | return scope
|
530 | e28a4841 | Sofia Papagiannaki | |
531 | e28a4841 | Sofia Papagiannaki | def validate_code(self, client, params, headers): |
532 | e28a4841 | Sofia Papagiannaki | code = params.get('code')
|
533 | e28a4841 | Sofia Papagiannaki | if code is None: |
534 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Missing authorization code") |
535 | e28a4841 | Sofia Papagiannaki | return self.get_client_authorization_code(client, code) |
536 | e28a4841 | Sofia Papagiannaki | |
537 | 3fc7fd80 | Kostas Papadimitriou | #
|
538 | 3fc7fd80 | Kostas Papadimitriou | # Requests validation methods
|
539 | 3fc7fd80 | Kostas Papadimitriou | #
|
540 | 3fc7fd80 | Kostas Papadimitriou | |
541 | e28a4841 | Sofia Papagiannaki | def validate_code_request(self, params, headers): |
542 | e28a4841 | Sofia Papagiannaki | client = self.validate_client(params, headers, requires_auth=False) |
543 | 3fc7fd80 | Kostas Papadimitriou | redirect_uri = self.validate_redirect_uri(client, params, headers)
|
544 | 3fc7fd80 | Kostas Papadimitriou | scope = self.validate_scope(client, params, headers)
|
545 | 3fc7fd80 | Kostas Papadimitriou | state = self.validate_state(client, params, headers)
|
546 | 3fc7fd80 | Kostas Papadimitriou | return client, redirect_uri, scope, state
|
547 | 3fc7fd80 | Kostas Papadimitriou | |
548 | e28a4841 | Sofia Papagiannaki | def validate_token_request(self, params, headers, requires_auth=False): |
549 | e28a4841 | Sofia Papagiannaki | client = self.validate_client(params, headers)
|
550 | 3fc7fd80 | Kostas Papadimitriou | redirect_uri = self.validate_redirect_uri(client, params, headers)
|
551 | 3fc7fd80 | Kostas Papadimitriou | scope = self.validate_scope(client, params, headers)
|
552 | 3fc7fd80 | Kostas Papadimitriou | state = self.validate_state(client, params, headers)
|
553 | 3fc7fd80 | Kostas Papadimitriou | return client, redirect_uri, scope, state
|
554 | 3fc7fd80 | Kostas Papadimitriou | |
555 | e28a4841 | Sofia Papagiannaki | def validate_code_grant(self, params, headers): |
556 | e28a4841 | Sofia Papagiannaki | client = self.validate_client(params, headers,
|
557 | e28a4841 | Sofia Papagiannaki | client_id_required=False)
|
558 | e28a4841 | Sofia Papagiannaki | code_instance = self.validate_code(client, params, headers)
|
559 | e28a4841 | Sofia Papagiannaki | redirect_uri = self.validate_redirect_uri(
|
560 | e28a4841 | Sofia Papagiannaki | client, params, headers, |
561 | e28a4841 | Sofia Papagiannaki | expected_value=code_instance.redirect_uri) |
562 | e28a4841 | Sofia Papagiannaki | return client, redirect_uri, code_instance
|
563 | e28a4841 | Sofia Papagiannaki | |
564 | 3fc7fd80 | Kostas Papadimitriou | #
|
565 | 3fc7fd80 | Kostas Papadimitriou | # Endpoint methods
|
566 | 3fc7fd80 | Kostas Papadimitriou | #
|
567 | 3fc7fd80 | Kostas Papadimitriou | |
568 | 3fc7fd80 | Kostas Papadimitriou | @handles_oa2_requests
|
569 | 3fc7fd80 | Kostas Papadimitriou | def authorize(self, request, **extra): |
570 | 3fc7fd80 | Kostas Papadimitriou | """
|
571 | 3fc7fd80 | Kostas Papadimitriou | Used in the following cases
|
572 | 3fc7fd80 | Kostas Papadimitriou | """
|
573 | 3fc7fd80 | Kostas Papadimitriou | if not request.secure: |
574 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Secure request required") |
575 | 3fc7fd80 | Kostas Papadimitriou | |
576 | 3fc7fd80 | Kostas Papadimitriou | # identify
|
577 | 3fc7fd80 | Kostas Papadimitriou | request_params = request.GET |
578 | 3fc7fd80 | Kostas Papadimitriou | if request.method == "POST": |
579 | 3fc7fd80 | Kostas Papadimitriou | request_params = request.POST |
580 | 3fc7fd80 | Kostas Papadimitriou | |
581 | 3fc7fd80 | Kostas Papadimitriou | auth_type, params = self.identify_authorize_request(request_params,
|
582 | 3fc7fd80 | Kostas Papadimitriou | request.META) |
583 | 3fc7fd80 | Kostas Papadimitriou | |
584 | 3fc7fd80 | Kostas Papadimitriou | if auth_type == 'code': |
585 | 3fc7fd80 | Kostas Papadimitriou | client, uri, scope, state = \ |
586 | e28a4841 | Sofia Papagiannaki | self.validate_code_request(params, request.META)
|
587 | 3fc7fd80 | Kostas Papadimitriou | elif auth_type == 'token': |
588 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Unsupported response type") |
589 | e28a4841 | Sofia Papagiannaki | # client, uri, scope, state = \
|
590 | e28a4841 | Sofia Papagiannaki | # self.validate_token_request(params, request.META)
|
591 | 3fc7fd80 | Kostas Papadimitriou | else:
|
592 | 3fc7fd80 | Kostas Papadimitriou | #TODO: handle custom type
|
593 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid authorization type") |
594 | 3fc7fd80 | Kostas Papadimitriou | |
595 | e28a4841 | Sofia Papagiannaki | user = getattr(request, 'user', None) |
596 | 3fc7fd80 | Kostas Papadimitriou | if not user: |
597 | e28a4841 | Sofia Papagiannaki | return self.redirect_to_login_response(request, params) |
598 | 3fc7fd80 | Kostas Papadimitriou | |
599 | 3fc7fd80 | Kostas Papadimitriou | if request.method == 'POST': |
600 | 3fc7fd80 | Kostas Papadimitriou | if auth_type == 'code': |
601 | 3fc7fd80 | Kostas Papadimitriou | return self.process_code_request(user, client, uri, scope, |
602 | 3fc7fd80 | Kostas Papadimitriou | state) |
603 | 3fc7fd80 | Kostas Papadimitriou | elif auth_type == 'token': |
604 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Unsupported response type") |
605 | e28a4841 | Sofia Papagiannaki | # return self.process_token_request(user, client, uri, scope,
|
606 | e28a4841 | Sofia Papagiannaki | # state)
|
607 | 3fc7fd80 | Kostas Papadimitriou | else:
|
608 | 3fc7fd80 | Kostas Papadimitriou | #TODO: handle custom type
|
609 | 3fc7fd80 | Kostas Papadimitriou | raise OA2Error("Invalid authorization type") |
610 | 3fc7fd80 | Kostas Papadimitriou | else:
|
611 | e28a4841 | Sofia Papagiannaki | if client.is_trusted:
|
612 | e28a4841 | Sofia Papagiannaki | return self.process_code_request(user, client, uri, scope, |
613 | e28a4841 | Sofia Papagiannaki | state) |
614 | e28a4841 | Sofia Papagiannaki | else:
|
615 | e28a4841 | Sofia Papagiannaki | return self.grant_accept_response(client, uri, scope, state) |
616 | e28a4841 | Sofia Papagiannaki | |
617 | e28a4841 | Sofia Papagiannaki | @handles_oa2_requests
|
618 | e28a4841 | Sofia Papagiannaki | def grant_token(self, request, **extra): |
619 | e28a4841 | Sofia Papagiannaki | """
|
620 | e28a4841 | Sofia Papagiannaki | Used in the following cases
|
621 | e28a4841 | Sofia Papagiannaki | """
|
622 | e28a4841 | Sofia Papagiannaki | if not request.secure: |
623 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Secure request required") |
624 | e28a4841 | Sofia Papagiannaki | |
625 | e28a4841 | Sofia Papagiannaki | grant_type = self.identify_token_request(request.META, request.POST)
|
626 | e28a4841 | Sofia Papagiannaki | |
627 | e28a4841 | Sofia Papagiannaki | if grant_type == 'authorization_code': |
628 | e28a4841 | Sofia Papagiannaki | client, redirect_uri, code = \ |
629 | e28a4841 | Sofia Papagiannaki | self.validate_code_grant(request.POST, request.META)
|
630 | e28a4841 | Sofia Papagiannaki | token, token_type = \ |
631 | e28a4841 | Sofia Papagiannaki | self.grant_authorization_code(client, code, redirect_uri)
|
632 | e28a4841 | Sofia Papagiannaki | return self.grant_token_response(token, token_type) |
633 | e28a4841 | Sofia Papagiannaki | elif (grant_type in ['client_credentials', 'token'] or |
634 | e28a4841 | Sofia Papagiannaki | self.is_uri(grant_type)):
|
635 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Unsupported grant type") |
636 | e28a4841 | Sofia Papagiannaki | else:
|
637 | e28a4841 | Sofia Papagiannaki | #TODO: handle custom type
|
638 | e28a4841 | Sofia Papagiannaki | raise OA2Error("Invalid grant type") |