44import traceback
55from importlib import import_module
66
7- from cryptojwt .utils import as_bytes
7+ from cryptojwt .utils import as_bytes , as_unicode
8+ from oidcmsg .exception import MessageException , NotForMe
89from oidcmsg .oauth2 import ResponseMessage
910from oidcmsg .oauth2 import is_error_message
10- from oidcmsg .oidc import AccessTokenResponse
11+ from oidcmsg .oidc import AccessTokenResponse , verified_claim_name
1112from oidcmsg .oidc import AuthorizationRequest
1213from oidcmsg .oidc import AuthorizationResponse
1314from oidcmsg .oidc import OpenIDSchema
15+ from oidcmsg .oidc .session import BackChannelLogoutRequest
1416from oidcmsg .time_util import time_sans_frac
1517from oidcservice import rndstr
1618from oidcservice .exception import OidcServiceError
@@ -732,7 +734,6 @@ def finalize(self, issuer, response):
732734 state = _state , client = client )
733735
734736 if 'userinfo' in client .service and token ['access_token' ]:
735-
736737 inforesp = self .get_user_info (
737738 state = authorization_response ['state' ], client = client ,
738739 access_token = token ['access_token' ])
@@ -750,10 +751,32 @@ def finalize(self, issuer, response):
750751
751752 logger .debug ("UserInfo: %s" , inforesp )
752753
754+ try :
755+ _sid_support = client .service_context .provider_info [
756+ 'backchannel_logout_session_supported' ]
757+ except KeyError :
758+ try :
759+ _sid_support = client .service_context .provider_info [
760+ 'frontchannel_logout_session_supported' ]
761+ except :
762+ _sid_support = False
763+
764+ if _sid_support :
765+ try :
766+ sid = token ['id_token' ]['sid' ]
767+ except KeyError :
768+ pass
769+ else :
770+ client .session_interface .store_sid2state (sid , _state )
771+
772+ client .session_interface .store_sub2state (token ['id_token' ]['sub' ],
773+ _state )
774+
753775 return {
754776 'userinfo' : inforesp ,
755777 'state' : authorization_response ['state' ],
756- 'token' : token ['access_token' ]
778+ 'token' : token ['access_token' ],
779+ 'id_token' : token ['id_token' ]
757780 }
758781
759782 def has_active_authentication (self , state ):
@@ -830,7 +853,7 @@ def logout(self, state, client=None, post_logout_redirect_uri=''):
830853 :param client: Which client to use
831854 :param post_logout_redirect_uri: If a special post_logout_redirect_uri
832855 should be used
833- :return:
856+ :return: A US
834857 """
835858 if client is None :
836859 client = self .get_client_from_session_key (state )
@@ -847,13 +870,54 @@ def logout(self, state, client=None, post_logout_redirect_uri=''):
847870 else :
848871 request_args = {}
849872
850- resp = client .do_request ('end_session' , state = state ,
851- request_args = request_args )
852- if is_error_message (resp ):
853- raise OidcServiceError (resp ['error' ])
873+ resp = srv .get_request_parameters (state = state ,
874+ request_args = request_args )
854875
855876 return resp
856877
878+ def backchannel_logout (self , client , request = '' , request_args = None ):
879+ """
880+
881+ :param request: URL encoded logout request
882+ :return:
883+ """
884+
885+ if request :
886+ req = BackChannelLogoutRequest ().from_urlencoded (as_unicode (request ))
887+ else :
888+ req = BackChannelLogoutRequest (** request_args )
889+
890+ kwargs = {
891+ 'aud' : client .service_context .client_id ,
892+ 'iss' : client .service_context .issuer ,
893+ 'keyjar' : client .service_context .keyjar
894+ }
895+
896+ try :
897+ req .verify (** kwargs )
898+ except (MessageException , ValueError , NotForMe ) as err :
899+ raise MessageException ('Bogus logout request: {}' .format (err ))
900+
901+ # Find the subject through 'sid' or 'sub'
902+
903+ try :
904+ sub = req [verified_claim_name ('logout_token' )]['sub' ]
905+ except KeyError :
906+ try :
907+ sid = req [verified_claim_name ('logout_token' )]['sid' ]
908+ except KeyError :
909+ raise MessageException ('Neither "sid" nor "sub"' )
910+ else :
911+ _state = client .session_interface .get_state_by_sid (sid )
912+ else :
913+ _state = client .session_interface .get_state_by_sub (sub )
914+
915+ return _state
916+
917+ def clear_session (self , state ):
918+ client = self .get_client_from_session_key (state )
919+ client .session_interface .remove_state (state )
920+
857921
858922def get_provider_specific_service (service_provider , service , ** kwargs ):
859923 """
0 commit comments