Skip to content
This repository was archived by the owner on Jun 12, 2021. It is now read-only.

Commit e58d139

Browse files
committed
Merge branch 'master' of github.com:IdentityPython/oidcendpoint
2 parents f4b217a + 059636d commit e58d139

File tree

12 files changed

+85
-174
lines changed

12 files changed

+85
-174
lines changed

src/oidcendpoint/endpoint.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535
- _parse_args
3636
- post_construct (*)
3737
- update_http_args
38-
38+
3939
do_response returns a dictionary that can look like this:
4040
{
41-
'response':
42-
_response as a string or as a Message instance_
41+
'response':
42+
_response as a string or as a Message instance_
4343
'http_headers': [
44-
('Content-type', 'application/json'),
45-
('Pragma', 'no-cache'),
44+
('Content-type', 'application/json'),
45+
('Pragma', 'no-cache'),
4646
('Cache-Control', 'no-store')
4747
],
4848
'cookie': _list of cookies_,
@@ -51,8 +51,8 @@
5151
5252
"response" MUST be present
5353
"http_headers" MAY be present
54-
"cookie": MAY be present
55-
"response_placement": If absent defaults to the endpoints response_placement
54+
"cookie": MAY be present
55+
"response_placement": If absent defaults to the endpoints response_placement
5656
parameter value or if that is also missing 'url'
5757
"""
5858

src/oidcendpoint/jwt_token.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class JWTToken(Token):
1414
def __init__(
1515
self,
1616
typ,
17-
black_list=None,
1817
keyjar=None,
1918
issuer=None,
2019
aud=None,
@@ -24,7 +23,7 @@ def __init__(
2423
token_type="Bearer",
2524
**kwargs
2625
):
27-
Token.__init__(self, typ, black_list, **kwargs)
26+
Token.__init__(self, typ, **kwargs)
2827
self.token_type = token_type
2928
self.lifetime = lifetime
3029
self.args = kwargs
@@ -105,7 +104,6 @@ def info(self, token):
105104
"type": _payload["ttype"],
106105
"exp": _payload["exp"],
107106
"handler": self,
108-
"black_listed": self.is_black_listed(token),
109107
}
110108
return _res
111109

src/oidcendpoint/oauth2/introspection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Introspection(Endpoint):
1818
response_cls = oauth2.TokenIntrospectionResponse
1919
request_format = "urlencoded"
2020
response_format = "json"
21-
endpoint_name = "introspection"
21+
endpoint_name = "introspection_endpoint"
2222
name = "introspection"
2323

2424
def get_client_id_from_token(self, endpoint_context, token, request=None):

src/oidcendpoint/oidc/token.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def _access_token(self, req, **kwargs):
111111
return resp
112112

113113
_sdb.update_by_token(_access_code, id_token=_idtoken)
114-
_info = _sdb[_access_code]
114+
_info = _sdb[_info['sid']]
115115

116116
return by_schema(AccessTokenResponse, **_info)
117117

@@ -155,6 +155,8 @@ def process_request(self, request=None, **kwargs):
155155
:param kwargs:
156156
:return: Dictionary with response information
157157
"""
158+
if isinstance(request, self.error_cls):
159+
return request
158160
try:
159161
response_args = self._access_token(request, **kwargs)
160162
except JWEException as err:
@@ -163,9 +165,9 @@ def process_request(self, request=None, **kwargs):
163165
if isinstance(response_args, ResponseMessage):
164166
return response_args
165167

166-
_access_code = request["code"].replace(" ", "+")
168+
_access_token = response_args["access_token"]
167169
_cookie = new_cookie(
168-
self.endpoint_context, sub=self.endpoint_context.sdb[_access_code]["sub"]
170+
self.endpoint_context, sub=self.endpoint_context.sdb[_access_token]["sub"]
169171
)
170172
_headers = [("Content-type", "application/json")]
171173
resp = {"response_args": response_args, "http_headers": _headers}

src/oidcendpoint/oidc/token_coop.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def _access_token(self, req, **kwargs):
126126
return resp
127127

128128
_sdb.update_by_token(_access_code, id_token=_idtoken)
129-
_info = _sdb[_access_code]
129+
_info = _sdb[_info['sid']]
130130

131131
return by_schema(AccessTokenResponse, **_info)
132132

@@ -212,6 +212,8 @@ def process_request(self, request=None, **kwargs):
212212
:param kwargs:
213213
:return: Dictionary with response information
214214
"""
215+
if isinstance(request, self.error_cls):
216+
return request
215217
try:
216218
if request["grant_type"] == "authorization_code":
217219
logger.debug("Access Token Request")
@@ -234,8 +236,9 @@ def process_request(self, request=None, **kwargs):
234236
else:
235237
_token = request["refresh_token"].replace(" ", "+")
236238

239+
_access_token = response_args["access_token"]
237240
_cookie = new_cookie(
238-
self.endpoint_context, sub=self.endpoint_context.sdb[_token]["sub"]
241+
self.endpoint_context, sub=self.endpoint_context.sdb[_access_token]["sub"]
239242
)
240243

241244
_headers = [("Content-type", "application/json")]

src/oidcendpoint/session.py

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from oidcmsg.message import OPTIONAL_LIST_OF_STRINGS
88
from oidcmsg.message import SINGLE_OPTIONAL_STRING
99
from oidcmsg.message import SINGLE_REQUIRED_STRING
10+
from oidcmsg.message import SINGLE_OPTIONAL_JSON
1011
from oidcmsg.message import msg_ser
1112
from oidcmsg.oidc import AuthorizationRequest
1213

@@ -144,12 +145,16 @@ def __getitem__(self, item):
144145
if _info is None:
145146
sid = self.handler.sid(item)
146147
_info = self._db.get(sid)
147-
148-
if _info:
148+
if _info:
149+
_si = SessionInfo().from_json(_info)
150+
if any(item == val for val in _si.values()):
151+
_si['sid'] = sid
152+
return _si
153+
else:
149154
_si = SessionInfo().from_json(_info)
155+
_si['sid'] = item
150156
return _si
151-
else:
152-
return None
157+
raise KeyError
153158

154159
def __setitem__(self, sid, instance):
155160
try:
@@ -268,9 +273,9 @@ def do_sub(
268273

269274
return sub
270275

271-
def is_valid(self, item):
276+
def is_valid(self, typ, item):
272277
try:
273-
return not self.handler.is_black_listed(item)
278+
return typ in self[item]
274279
except KeyError:
275280
return False
276281

@@ -295,9 +300,8 @@ def replace_token(self, sid, sinfo, token_type):
295300

296301
if token_type in self.handler:
297302
refresh_token = self.handler[token_type](sid, sinfo=sinfo)
298-
# blacklist the old is there is one
299-
if sinfo.get(token_type):
300-
self.handler[token_type].black_list(sinfo[token_type])
303+
# blacklist the old
304+
self.revoke_token(sid, token_type, sinfo)
301305

302306
sinfo[token_type] = refresh_token
303307
return sinfo
@@ -333,25 +337,17 @@ def upgrade_to_token(
333337
:return: The session information as a SessionInfo instance
334338
"""
335339
if grant:
340+
# The caller is responsible for checking if the access code exists.
336341
_tinfo = self.handler["code"].info(grant)
337342

338-
session_info = self[_tinfo["sid"]]
339-
340-
if self.handler["code"].is_black_listed(grant):
341-
# invalidate the released access token and refresh token
342-
for item in ["access_token", "refresh_token"]:
343-
try:
344-
self.handler[item].black_list(session_info[item])
345-
except KeyError:
346-
pass
347-
raise AccessCodeUsed(grant)
343+
key = _tinfo["sid"]
344+
session_info = self[key]
348345

349346
# mint a new access token
350347
_at = self._make_at(_tinfo["sid"], session_info)
351348

352349
# make sure the code can't be used again
353-
self.handler["code"].black_list(grant)
354-
key = _tinfo["sid"]
350+
self.revoke_token(key, "code", session_info)
355351
else:
356352
session_info = self[key]
357353
_at = self._make_at(key, session_info)
@@ -386,17 +382,15 @@ def refresh_token(self, token, new_refresh=False):
386382
:raises: ExpiredToken for invalid refresh token
387383
WrongTokenType for wrong token type
388384
"""
389-
390385
try:
391386
_tinfo = self.handler["refresh_token"].info(token)
392387
except KeyError:
393388
return False
394389

395-
if is_expired(int(_tinfo["exp"])) or _tinfo["black_listed"]:
396-
raise ExpiredToken()
397-
398390
_sid = _tinfo["sid"]
399391
session_info = self[_sid]
392+
if is_expired(int(_tinfo["exp"])):
393+
raise ExpiredToken()
400394

401395
session_info = self.replace_token(_sid, session_info, "access_token")
402396

@@ -420,11 +414,10 @@ def is_token_valid(self, token):
420414
except KeyError:
421415
return False
422416

423-
if is_expired(int(_tinfo["exp"])) or _tinfo["black_listed"]:
424-
return False
425-
426417
# Dependent on what state the session is in.
427418
session_info = self[_tinfo["sid"]]
419+
if is_expired(int(_tinfo["exp"])):
420+
return False
428421

429422
if session_info["oauth_state"] == "authz":
430423
if _tinfo["handler"] != self.handler["code"]:
@@ -435,22 +428,25 @@ def is_token_valid(self, token):
435428

436429
return True
437430

438-
def revoke_token(self, token, token_type=""):
431+
def revoke_token(self, sid, token_type, session_info=None):
439432
"""
440-
Revokes access token
433+
Revokes token
441434
442-
:param token: access token
435+
:param sid: session id
436+
:param token_type: token type, one of "code", "access_token" or
437+
"refresh_token"
443438
"""
444-
if token_type:
445-
self.handler[token_type].black_list(token)
446-
else:
447-
self.handler.black_list(token)
439+
if not session_info:
440+
session_info = self[sid]
441+
session_info.pop(token_type, None)
442+
self[sid] = session_info
448443

449444
def revoke_all_tokens(self, token):
450-
_sinfo = self[token]
451-
for typ in self.handler.keys():
452-
if _sinfo.get(typ):
453-
self.revoke_token(_sinfo[typ], typ)
445+
sid = self.handler.sid(token)
446+
_sinfo = self[sid]
447+
for token_type in self.handler.keys():
448+
_sinfo.pop(token_type, None)
449+
self[sid] = _sinfo
454450

455451
def revoke_session(self, sid="", token=""):
456452
"""
@@ -465,11 +461,9 @@ def revoke_session(self, sid="", token=""):
465461
else:
466462
raise ValueError('Need one of "sid" or "token"')
467463

468-
for typ in ["access_token", "refresh_token", "code"]:
469-
try:
470-
self.revoke_token(self[sid][typ], typ)
471-
except KeyError: # If no such token has been issued
472-
pass
464+
_sinfo = self[sid]
465+
for token_type in self.handler.keys():
466+
_sinfo.pop(token_type, None)
473467

474468
self.update(sid, revoked=True)
475469

src/oidcendpoint/token_handler.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,10 @@ def decrypt(self, ciphertext):
6969

7070

7171
class Token(object):
72-
def __init__(self, typ, black_list=None, lifetime=300, **kwargs):
72+
def __init__(self, typ, lifetime=300, **kwargs):
7373
self.type = typ
7474
self.lifetime = lifetime
7575
self.args = kwargs
76-
self.blist = [] if black_list is None else black_list
7776

7877
def __call__(self, sid, *args, **kwargs):
7978
"""
@@ -113,19 +112,12 @@ def is_expired(self, token, when=0):
113112
def gather_args(self, *args, **kwargs):
114113
return {}
115114

116-
def black_list(self, token):
117-
if token:
118-
self.blist.append(token)
119-
120-
def is_black_listed(self, token):
121-
return token in self.blist
122-
123115

124116
class DefaultToken(Token):
125117
def __init__(
126-
self, password, typ="", black_list=None, token_type="Bearer", **kwargs
118+
self, password, typ="", token_type="Bearer", **kwargs
127119
):
128-
Token.__init__(self, typ, black_list, **kwargs)
120+
Token.__init__(self, typ, **kwargs)
129121
self.crypt = Crypt(password)
130122
self.token_type = token_type
131123

@@ -189,7 +181,6 @@ def info(self, token):
189181
raise WrongTokenType(_res["type"])
190182
else:
191183
_res["handler"] = self
192-
_res["black_listed"] = self.is_black_listed(token)
193184
return _res
194185

195186
def is_expired(self, token, when=0):
@@ -239,10 +230,6 @@ def sid(self, token, order=None):
239230
def type(self, token, order=None):
240231
return self.info(token, order)["type"]
241232

242-
def is_black_listed(self, token, order=None):
243-
_handler = self.get_handler(token, order)
244-
return _handler.is_black_listed(token)
245-
246233
def get_handler(self, token, order=None):
247234
if order is None:
248235
order = self.handler_order
@@ -257,10 +244,6 @@ def get_handler(self, token, order=None):
257244

258245
return None
259246

260-
def black_list(self, token, order=None):
261-
_handler = self.get_handler(token, order)
262-
_handler.black_list(token)
263-
264247
def keys(self):
265248
return self.handler.keys()
266249

tests/test_04_token_handler.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,8 @@ def test_default_token_info(self):
8383
"sid",
8484
"exp",
8585
"handler",
86-
"black_listed",
8786
}
8887
assert _info["handler"] == self.th
89-
assert _info["black_listed"] is False
9088

9189
def test_is_expired(self):
9290
_token = self.th("another_id")
@@ -95,14 +93,6 @@ def test_is_expired(self):
9593
when = time.time() + 900
9694
assert self.th.is_expired(_token, when)
9795

98-
def test_blacklist(self):
99-
_token = self.th("another_id")
100-
self.th.black_list(_token)
101-
assert self.th.is_black_listed(_token)
102-
103-
_info = self.th.info(_token)
104-
assert _info["black_listed"] is True
105-
10696

10797
class TestTokenHandler(object):
10898
@pytest.fixture(autouse=True)
@@ -160,11 +150,5 @@ def test_get_handler(self):
160150
th = self.handler.get_handler(_token)
161151
assert th.type == "A"
162152

163-
def test_blacklist(self):
164-
_token = self.handler["code"]("another_id")
165-
self.handler.black_list(_token)
166-
_info = self.handler.info(_token)
167-
assert _info["black_listed"]
168-
169153
def test_keys(self):
170154
assert set(self.handler.keys()) == {"access_token", "code", "refresh_token"}

0 commit comments

Comments
 (0)