11import logging
22from typing import Optional
33from typing import Union
4+ from urllib .parse import urlparse
45
6+ from cryptojwt .exception import JWKESTException
57from cryptojwt .jwe .exception import JWEException
68from cryptojwt .jws .exception import NoSuitableSigningKeys
79from cryptojwt .jwt import utc_time_sans_frac
810from oidcmsg import oidc
911from oidcmsg .message import Message
12+ from oidcmsg .exception import MissingRequiredValue , MissingRequiredAttribute
1013from oidcmsg .oidc import RefreshAccessTokenRequest
1114from oidcmsg .oidc import TokenErrorResponse
12-
15+ from oidcmsg .oauth2 import (TokenExchangeRequest , ResponseMessage ,
16+ TokenExchangeResponse )
1317from oidcop import oauth2
1418from oidcop import sanitize
19+ from oidcop .oauth2 .authorization import check_unknown_scopes_policy
1520from oidcop .oauth2 .token import TokenEndpointHelper
1621from oidcop .session .grant import AuthorizationCode
1722from oidcop .session .grant import RefreshToken
1823from oidcop .session .token import MintingNotAllowed
1924from oidcop .token .exception import UnknownToken
25+ from oidcop .exception import UnAuthorizedClientScope , ToOld
26+ from oidcop .session .token import AccessToken
2027
2128logger = logging .getLogger (__name__ )
2229
@@ -376,10 +383,15 @@ def __init__(self, endpoint, config=None):
376383 def post_parse_request (self , request , client_id = "" , ** kwargs ):
377384 request = TokenExchangeRequest (** request .to_dict ())
378385
379- # if "client_id" not in request:
380- # request["client_id"] = client_id
386+ if "client_id" not in request :
387+ request ["client_id" ] = client_id
388+
389+ _context = self .endpoint .server_get ("endpoint_context" )
381390
382- keyjar = getattr (self .endpoint_context , "keyjar" , "" )
391+ try :
392+ keyjar = _context .keyjar
393+ except AttributeError :
394+ keyjar = ""
383395
384396 try :
385397 request .verify (keyjar = keyjar , opponent_id = client_id )
@@ -393,12 +405,11 @@ def post_parse_request(self, request, client_id="", **kwargs):
393405 error = "invalid_request" , error_description = "%s" % err
394406 )
395407
396-
397408 error = self .check_for_errors (request = request )
398409 if error is not None :
399410 return error
400411
401- _mngr = self . endpoint_context .session_manager
412+ _mngr = _context .session_manager
402413 try :
403414 _session_info = _mngr .get_session_info_by_token (
404415 request ["subject_token" ], grant = True
@@ -421,13 +432,12 @@ def post_parse_request(self, request, client_id="", **kwargs):
421432 return self .error_cls (
422433 error = "invalid_request" , error_description = "Subject token inactive"
423434 )
424-
425435 return request
426436
427437 def check_for_errors (self , request ):
428- context = self .endpoint .endpoint_context
438+ _context = self .endpoint .server_get ( " endpoint_context" )
429439 if "resource" in request :
430- iss = urlparse (context .issuer )
440+ iss = urlparse (_context .issuer )
431441 if any (
432442 urlparse (res ).netloc != iss .netloc for res in request ["resource" ]
433443 ):
@@ -437,7 +447,7 @@ def check_for_errors(self, request):
437447
438448 if "audience" in request :
439449 if any (
440- aud != context .issuer for aud in request ["audience" ]
450+ aud != _context .issuer for aud in request ["audience" ]
441451 ):
442452 return TokenErrorResponse (
443453 error = "invalid_target" , error_description = "Unknown audience"
@@ -468,7 +478,7 @@ def check_for_errors(self, request):
468478 def token_exchange_response (self , token ):
469479 response_args = {
470480 "issued_token_type" : "urn:ietf:params:oauth:token-type:access_token" ,
471- "token_type" : token .type ,
481+ "token_type" : token .token_type ,
472482 "access_token" : token .value ,
473483 "scope" : token .scope ,
474484 "expires_in" : token .usage_rules ["expires_in" ]
@@ -485,31 +495,61 @@ def process_request(self, request, **kwargs):
485495 # return TokenErrorResponse(
486496 # error="invalid_request", error_description="Not allowed"
487497 # )
488- _mngr = self .endpoint_context .session_manager
498+ _context = self .endpoint .server_get ("endpoint_context" )
499+ _mngr = _context .session_manager
489500 try :
490501 _session_info = _mngr .get_session_info_by_token (
491- request ["subject_token" ],
492- grant = True ,
502+ request ["subject_token" ], grant = True
493503 )
494- except KeyError :
504+ except ToOld :
505+ logger .error ("Subject token has expired." )
506+ return self .error_cls (
507+ error = "invalid_request" ,
508+ error_description = "Subject token has expired"
509+ )
510+ except (KeyError , UnknownToken ):
495511 logger .error ("Subject token invalid." )
496512 return self .error_cls (
497- error = "invalid_grant " ,
498- error_description = "Subject token invalid" ,
513+ error = "invalid_request " ,
514+ error_description = "Subject token invalid"
499515 )
500516
501517 token = _mngr .find_token (_session_info ["session_id" ], request ["subject_token" ])
518+
519+ if not isinstance (token , AccessToken ):
520+ return self .error_cls (
521+ error = "invalid_request" , error_description = "Wrong token type"
522+ )
523+
524+ if token .is_active () is False :
525+ return self .error_cls (
526+ error = "invalid_request" , error_description = "Subject token inactive"
527+ )
528+
502529 grant = _session_info ["grant" ]
503530
531+ request_info = dict (scope = request .get ("scope" , []))
532+ try :
533+ check_unknown_scopes_policy (request_info , request ["client_id" ], _context )
534+ except UnAuthorizedClientScope :
535+ logger .error ("Unauthorized scope requested." )
536+ return self .error_cls (
537+ error = "invalid_grant" ,
538+ error_description = "Unauthorized scope requested" ,
539+ )
540+
504541 try :
505- new_token = grant .mint_token (
542+ new_token = self ._mint_token (
543+ token_class = token .token_class ,
544+ grant = grant ,
506545 session_id = _session_info ["session_id" ],
507- endpoint_context = self .endpoint_context ,
508- token_type = 'access_token' ,
509- token_handler = _mngr .token_handler ["access_token" ],
546+ client_id = request ["client_id" ],
510547 based_on = token ,
511- resources = request .get ("resource" ),
512548 scope = request .get ("scope" ),
549+ token_args = {
550+ "resources" :request .get ("resource" ),
551+ },
552+ token_type = token .token_type
513553 )
514554 except MintingNotAllowed :
515555 logger .error ("Minting not allowed for 'access_token'" )
0 commit comments