Skip to content

Commit 163bfcb

Browse files
committed
The software was not using the fact that it knew in advance which type of token that it was dealing with. This fixes that.
1 parent b98789b commit 163bfcb

18 files changed

+144
-74
lines changed

src/idpyoidc/server/oauth2/authorization.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,10 @@ def _unwrap_identity(self, identity):
528528
except BadSyntax:
529529
return identity
530530
else:
531-
_id = b64d(as_bytes(identity))
531+
try:
532+
_id = b64d(as_bytes(identity))
533+
except BadSyntax:
534+
return identity
532535

533536
return json.loads(as_unicode(_id))
534537

src/idpyoidc/server/oauth2/token.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
from idpyoidc.message import Message
88
from idpyoidc.message.oauth2 import AccessTokenResponse
99
from idpyoidc.message.oauth2 import ResponseMessage
10+
from idpyoidc.message.oauth2 import TokenExchangeRequest
1011
from idpyoidc.message.oidc import TokenErrorResponse
1112
from idpyoidc.server.endpoint import Endpoint
1213
from idpyoidc.server.exception import ProcessError
1314
from idpyoidc.server.oauth2.token_helper import AccessTokenHelper
1415
from idpyoidc.server.oauth2.token_helper import RefreshTokenHelper
16+
from idpyoidc.server.session.token import TOKEN_TYPES_MAPPING
1517
from idpyoidc.util import importer
1618

1719
logger = logging.getLogger(__name__)
@@ -76,7 +78,7 @@ def configure_grant_types(self, grant_types_helpers):
7678
raise ProcessError(f"Failed to initialize class {grant_class}: {e}")
7779

7880
def _post_parse_request(
79-
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
81+
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
8082
):
8183
grant_type = request["grant_type"]
8284
_helper = self.helper.get(grant_type)
@@ -125,8 +127,14 @@ def process_request(self, request: Optional[Union[Message, dict]] = None, **kwar
125127

126128
_access_token = response_args["access_token"]
127129
_context = self.server_get("endpoint_context")
130+
131+
if isinstance(request, TokenExchangeRequest):
132+
_handler_key = TOKEN_TYPES_MAPPING[request["requested_token_type"]]
133+
else:
134+
_handler_key = "access_token"
135+
128136
_session_info = _context.session_manager.get_session_info_by_token(
129-
_access_token, grant=True
137+
_access_token, grant=True, handler_key=_handler_key
130138
)
131139

132140
_cookie = _context.new_cookie(

src/idpyoidc/server/oauth2/token_helper.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Optional
33
from typing import Union
44

5+
from cryptojwt import BadSyntax
56
from cryptojwt.exception import JWKESTException
67

78
from idpyoidc.exception import ImproperlyConfigured
@@ -120,7 +121,8 @@ def process_request(self, req: Union[Message, dict], **kwargs):
120121
except KeyError: # Missing code parameter - absolutely fatal
121122
return self.error_cls(error="invalid_request", error_description="Missing code")
122123

123-
_session_info = _mngr.get_session_info_by_token(_access_code, grant=True)
124+
_session_info = _mngr.get_session_info_by_token(_access_code, grant=True,
125+
handler_key="authorization_code")
124126
client_id = _session_info["client_id"]
125127
if client_id != req["client_id"]:
126128
logger.debug("{} owner of token".format(client_id))
@@ -208,7 +210,8 @@ def post_parse_request(
208210

209211
_mngr = self.endpoint.server_get("endpoint_context").session_manager
210212
try:
211-
_session_info = _mngr.get_session_info_by_token(request["code"], grant=True)
213+
_session_info = _mngr.get_session_info_by_token(request["code"], grant=True,
214+
handler_key="authorization_code")
212215
except (KeyError, UnknownToken):
213216
logger.error("Access Code invalid")
214217
return self.error_cls(error="invalid_grant", error_description="Unknown code")
@@ -241,7 +244,8 @@ def process_request(self, req: Union[Message, dict], **kwargs):
241244
return self.error_cls(error="invalid_request", error_description="Wrong grant_type")
242245

243246
token_value = req["refresh_token"]
244-
_session_info = _mngr.get_session_info_by_token(token_value, grant=True)
247+
_session_info = _mngr.get_session_info_by_token(token_value, grant=True,
248+
handler_key="refresh_token")
245249
logger.debug("Session info: {}".format(_session_info))
246250

247251
if _session_info["client_id"] != req["client_id"]:
@@ -335,7 +339,8 @@ def post_parse_request(
335339

336340
_mngr = _context.session_manager
337341
try:
338-
_session_info = _mngr.get_session_info_by_token(request["refresh_token"], grant=True)
342+
_session_info = _mngr.get_session_info_by_token(request["refresh_token"], grant=True,
343+
handler_key="refresh_token")
339344
except (KeyError, UnknownToken):
340345
logger.error("Refresh token invalid")
341346
return self.error_cls(error="invalid_grant", error_description="Invalid refresh token")
@@ -414,13 +419,17 @@ def post_parse_request(self, request, client_id="", **kwargs):
414419

415420
_mngr = _context.session_manager
416421
try:
417-
_session_info = _mngr.get_session_info_by_token(request["subject_token"], grant=True)
418-
except (KeyError, UnknownToken):
419-
logger.error("Subject token invalid.")
422+
# token exchange is about minting one token based on another
423+
_handler_key = self.token_types_mapping[request["subject_token_type"]]
424+
_session_info = _mngr.get_session_info_by_token(
425+
request["subject_token"], grant=True, handler_key=_handler_key)
426+
except (KeyError, UnknownToken, BadSyntax) as err:
427+
logger.error(f"Subject token invalid ({err}).")
420428
return self.error_cls(
421429
error="invalid_request", error_description="Subject token invalid"
422430
)
423431

432+
# Find the token instance based on the token value
424433
token = _mngr.find_token(_session_info["session_id"], request["subject_token"])
425434
if token.is_active() is False:
426435
return self.error_cls(
@@ -511,7 +520,9 @@ def process_request(self, request, **kwargs):
511520
_context = self.endpoint.server_get("endpoint_context")
512521
_mngr = _context.session_manager
513522
try:
514-
_session_info = _mngr.get_session_info_by_token(request["subject_token"], grant=True)
523+
_handler_key = self.token_types_mapping[request["subject_token_type"]]
524+
_session_info = _mngr.get_session_info_by_token(
525+
request["subject_token"], grant=True, handler_key=_handler_key)
515526
except ToOld:
516527
logger.error("Subject token has expired.")
517528
return self.error_cls(

src/idpyoidc/server/oidc/add_on/pkce.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def post_token_parse(request, client_id, endpoint_context, **kwargs):
9999

100100
try:
101101
_session_info = endpoint_context.session_manager.get_session_info_by_token(
102-
request["code"], grant=True
102+
request["code"], grant=True, handler_key="authorization_code"
103103
)
104104
except KeyError:
105105
return TokenErrorResponse(error="invalid_grant", error_description="Unknown access grant")

src/idpyoidc/server/oidc/token_helper.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Optional
33
from typing import Union
44

5+
from cryptojwt import BadSyntax
56
from cryptojwt.jwe.exception import JWEException
67
from cryptojwt.jws.exception import NoSuitableSigningKeys
78
from cryptojwt.jwt import utc_time_sans_frac
@@ -29,7 +30,8 @@ def _get_session_info(self, request, session_manager):
2930
except KeyError: # Missing code parameter - absolutely fatal
3031
return self.error_cls(error="invalid_request", error_description="Missing code")
3132

32-
_session_info = session_manager.get_session_info_by_token(_access_code, grant=True)
33+
_session_info = session_manager.get_session_info_by_token(_access_code, grant=True,
34+
handler_key='authorization_code')
3335
logger.debug(f"Session info: {_session_info}")
3436
return _session_info, _access_code
3537

@@ -117,9 +119,9 @@ def process_request(self, req: Union[Message, dict], **kwargs):
117119
_response["expires_in"] = token.expires_at - utc_time_sans_frac()
118120

119121
if (
120-
issue_refresh
121-
and "refresh_token" in _supports_minting
122-
and "refresh_token" in grant_types_supported
122+
issue_refresh
123+
and "refresh_token" in _supports_minting
124+
and "refresh_token" in grant_types_supported
123125
):
124126
try:
125127
refresh_token = self._mint_token(
@@ -162,7 +164,7 @@ def process_request(self, req: Union[Message, dict], **kwargs):
162164
return _response
163165

164166
def post_parse_request(
165-
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
167+
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
166168
) -> Union[Message, dict]:
167169
"""
168170
This is where clients come to get their access tokens
@@ -174,7 +176,8 @@ def post_parse_request(
174176

175177
_mngr = self.endpoint.server_get("endpoint_context").session_manager
176178
try:
177-
_session_info = _mngr.get_session_info_by_token(request["code"], grant=True)
179+
_session_info = _mngr.get_session_info_by_token(request["code"], grant=True,
180+
handler_key='authorization_code')
178181
except (KeyError, UnknownToken):
179182
logger.error("Access Code invalid")
180183
return self.error_cls(error="invalid_grant", error_description="Unknown code")
@@ -211,7 +214,9 @@ def process_request(self, req: Union[Message, dict], **kwargs):
211214
return self.error_cls(error="invalid_request", error_description="Wrong grant_type")
212215

213216
token_value = req["refresh_token"]
214-
_session_info = _mngr.get_session_info_by_token(token_value, grant=True)
217+
218+
_session_info = _mngr.get_session_info_by_token(token_value, handler_key="refresh_token",
219+
grant=True)
215220
if _session_info["client_id"] != req["client_id"]:
216221
logger.debug("{} owner of token".format(_session_info["client_id"]))
217222
logger.warning("{} using token it was not given".format(req["client_id"]))
@@ -293,21 +298,21 @@ def process_request(self, req: Union[Message, dict], **kwargs):
293298
token.register_usage()
294299

295300
if (
296-
"client_id" in req
297-
and req["client_id"] in _context.cdb
298-
and "revoke_refresh_on_issue" in _context.cdb[req["client_id"]]
301+
"client_id" in req
302+
and req["client_id"] in _context.cdb
303+
and "revoke_refresh_on_issue" in _context.cdb[req["client_id"]]
299304
):
300305
revoke_refresh = _context.cdb[req["client_id"]].get("revoke_refresh_on_issue")
301306
else:
302-
revoke_refresh = revoke_refresh = self.endpoint.revoke_refresh_on_issue
307+
revoke_refresh = self.endpoint.revoke_refresh_on_issue
303308

304309
if revoke_refresh:
305310
token.revoke()
306311

307312
return _resp
308313

309314
def post_parse_request(
310-
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
315+
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
311316
):
312317
"""
313318
This is where clients come to refresh their access tokens
@@ -328,8 +333,10 @@ def post_parse_request(
328333

329334
_mngr = _context.session_manager
330335
try:
331-
_session_info = _mngr.get_session_info_by_token(request["refresh_token"], grant=True)
332-
except (KeyError, UnknownToken):
336+
_session_info = _mngr.get_session_info_by_token(request["refresh_token"],
337+
handler_key="refresh_token",
338+
grant=True)
339+
except (KeyError, UnknownToken, BadSyntax):
333340
logger.error("Refresh token invalid")
334341
return self.error_cls(error="invalid_grant", error_description="Invalid refresh token")
335342

src/idpyoidc/server/oidc/userinfo.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,16 @@ def __init__(self, server_get: Callable, add_claims_by_scope: Optional[bool] = T
4848
self.allowed_targets.append("")
4949

5050
def get_client_id_from_token(self, endpoint_context, token, request=None):
51-
_info = endpoint_context.session_manager.get_session_info_by_token(token)
51+
_info = endpoint_context.session_manager.get_session_info_by_token(
52+
token, handler_key="access_token")
5253
return _info["client_id"]
5354

5455
def do_response(
55-
self,
56-
response_args: Optional[Union[Message, dict]] = None,
57-
request: Optional[Union[Message, dict]] = None,
58-
client_id: Optional[str] = "",
59-
**kwargs
56+
self,
57+
response_args: Optional[Union[Message, dict]] = None,
58+
request: Optional[Union[Message, dict]] = None,
59+
client_id: Optional[str] = "",
60+
**kwargs
6061
) -> dict:
6162

6263
if "error" in kwargs and kwargs["error"]:
@@ -113,7 +114,8 @@ def do_response(
113114
def process_request(self, request=None, **kwargs):
114115
_mngr = self.server_get("endpoint_context").session_manager
115116
try:
116-
_session_info = _mngr.get_session_info_by_token(request["access_token"], grant=True)
117+
_session_info = _mngr.get_session_info_by_token(request["access_token"],
118+
grant=True, handler_key="access_token")
117119
except (KeyError, ValueError):
118120
return self.error_cls(error="invalid_token", error_description="Invalid Token")
119121

src/idpyoidc/server/session/manager.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from idpyoidc.server.authn_event import AuthnEvent
1515
from idpyoidc.server.exception import ConfigurationError
1616
from idpyoidc.server.session.database import NoSuchClientSession
17+
from idpyoidc.server.token import Token
1718
from idpyoidc.util import rndstr
1819

1920
from ..token import UnknownToken
@@ -559,13 +560,18 @@ def _compatible_sid(self, sid):
559560
def get_session_info_by_token(
560561
self,
561562
token_value: str,
562-
user_session_info: bool = False,
563-
client_session_info: bool = False,
564-
grant: bool = False,
565-
authentication_event: bool = False,
566-
authorization_request: bool = False,
563+
user_session_info: Optional[bool] = False,
564+
client_session_info: Optional[bool] = False,
565+
grant: Optional[bool] = False,
566+
authentication_event: Optional[bool] = False,
567+
authorization_request: Optional[bool] = False,
568+
handler_key: Optional[str] = '',
567569
) -> dict:
568-
_token_info = self.token_handler.info(token_value)
570+
if handler_key:
571+
_token_info = self.token_handler.handler[handler_key].info(token_value)
572+
else:
573+
_token_info = self.token_handler.info(token_value)
574+
569575
sid = _token_info.get("sid")
570576
# If the token is an ID Token then the sid will not be in the
571577
# _token_info

src/idpyoidc/server/session/token.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,9 @@ def __init__(
273273
"refresh_token": RefreshToken,
274274
"id_token": IDToken,
275275
}
276+
277+
TOKEN_TYPES_MAPPING = {
278+
"urn:ietf:params:oauth:token-type:access_token": "access_token",
279+
"urn:ietf:params:oauth:token-type:refresh_token": "refresh_token",
280+
"urn:ietf:params:oauth:token-type:id_token": "id_token",
281+
}

tests/request123456.jwt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNVc3dOaTFNUkZsRFQwWTJZalUxWjFSZlFsbzJTM2RFYTNGVFRrVjNMVGhGY25oRFRIRjVlbGsyVlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICJvWkpBNTRnZTVaUndNalkwOVVLVnpwYkx5MEdNUEwwaCIsICJjbGllbnRfaWQiOiAiY2xpZW50X2lkIiwgImlzcyI6ICJjbGllbnRfaWQiLCAiaWF0IjogMTYzMzU5NTc4OSwgImF1ZCI6IFsiaHR0cHM6Ly9leGFtcGxlLmNvbSJdfQ.KVMPK6leJ5pEXnJ0jXiXu21U176IU9iwkT4FkQV_33jGYTsgdqCqXw5XHR1ciixdcH2cWf0SzTPOgIzGsI4NJiPNdR9xOusYRyYKZciXHq85nrM7fr7dEPaVntWCU6uadH0MNHWCcq2FyBdz2YYDuiFPUXoxkFbfWZoo_jVMAWLxGQtGEitniI49qo0zbeSFck4hBmEtQTUOrGQvg_CjkSZb5oNb5rt_X5T-ZSK9y3AeKru4HLSQRkWj-oD-Fgd60Sm3XqfLQXrx26lk4a8ORah01BMmMsi5jeIUbOTthhhglZhMwoI9xCZ57I4SF7870-PrinIByW8d2keA1-LipQ
1+
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNIRXlZV2N3TlZrMExUZFJPVFp6WjJGVVduZElWWGRhY2sweFdVTTVTRXB3Y1MwM2RWVXhXVTR6UlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICJGYVVaSm02TDdTc251d2JEbEQ0Z20wbkg2eHpBTTVlR19nWG5sRmlhX19zIiwgImNsaWVudF9pZCI6ICJjbGllbnRfaWQiLCAiaXNzIjogImNsaWVudF9pZCIsICJpYXQiOiAxNjUwMzkzMDQ3LCAiYXVkIjogWyJodHRwczovL2V4YW1wbGUuY29tIl19.ARTBLchcBOpUX5kuvZzVyfw-ad6skc498Ll93sRwGoNrxZosNdHVTP25FtrDx8GVcBoA1OSYFq7Zmx9d7DJib-uukylEQl-5widvWmC0s-14uSRfLiSulqtB43FrCji9dXl6T5uAOgGxzoNo5dVSwfeIcenjqBuiJslxuHy4AQ7S-gRi02E_uEaqWOytkUoOwaIKcMiujbpo4VWOzDv9pK4C6C89uuHSMxfWpwi27T2vFLa6icfuQuXcxOZabs1lJUJt84Aclh_mz58E1YDlowRAuUu8RkpICAnQwxgzlCGwj3mzJxxFVVUCnRVnrB-BG7e3XXQBcf536BtYOyOfCQ

tests/test_server_10_session_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ def test_get_session_info_by_token(self):
364364

365365
grant = self.session_manager.get_grant(_session_id)
366366
code = self._mint_token("authorization_code", grant, _session_id)
367-
_session_info = self.session_manager.get_session_info_by_token(code.value)
367+
_session_info = self.session_manager.get_session_info_by_token(code.value,
368+
handler_key="authorization_code")
368369

369370
assert set(_session_info.keys()) == {
370371
"client_id",

0 commit comments

Comments
 (0)