@@ -251,93 +251,122 @@ def do_logout(
251251 not_done = entity_ids [:]
252252 responses = {}
253253
254- if expected_binding is None :
255- expected_binding = next (
256- iter (self .config .preferred_binding ["single_logout_service" ]),
257- None ,
258- )
254+ bindings_slo_preferred = self .config .preferred_binding ["single_logout_service" ]
255+
259256 for entity_id in entity_ids :
260257 logger .debug ("Logout from '%s'" , entity_id )
261- # for all where I can use the SOAP binding, do those first
262- for binding in [BINDING_SOAP , BINDING_HTTP_POST , BINDING_HTTP_REDIRECT ]:
263- if expected_binding and binding != expected_binding :
264- continue
265-
266- try :
267- srvs = self .metadata .single_logout_service (
268- entity_id , binding , "idpsso"
269- )
270- except :
271- srvs = None
272-
273- if not srvs :
274- logger .debug ("No SLO '%s' service" , binding )
275- continue
276-
277- destination = next (locations (srvs ), None )
278- logger .info ("destination to provider: %s" , destination )
279-
280- try :
281- session_info = self .users .get_info_from (
282- name_id , entity_id , False
283- )
284- session_indexes = [session_info ['session_index' ]]
285- except KeyError :
286- session_indexes = None
287-
288- sign = sign if sign is not None else self .logout_requests_signed
289- sign_post = sign and (
290- binding == BINDING_HTTP_POST or binding == BINDING_SOAP
258+
259+ bindings_slo_supported = self .metadata .single_logout_service (
260+ entity_id = entity_id , typ = "idpsso"
261+ )
262+ bindings_slo_preferred_and_supported = (
263+ binding
264+ for binding in bindings_slo_preferred
265+ if binding in bindings_slo_supported
266+ )
267+ bindings_slo_choices = filter (
268+ lambda x : x ,
269+ (
270+ expected_binding ,
271+ * bindings_slo_preferred_and_supported ,
272+ * bindings_slo_supported ,
291273 )
292- sign_redirect = sign and binding == BINDING_HTTP_REDIRECT
293-
294- req_id , request = self .create_logout_request (
295- destination ,
296- entity_id ,
297- name_id = name_id ,
298- reason = reason ,
299- expire = expire ,
300- session_indexes = session_indexes ,
301- sign = sign_post ,
302- sign_alg = sign_alg ,
303- digest_alg = digest_alg ,
274+ )
275+ binding = next (bindings_slo_choices , None )
276+ if not binding :
277+ logger .info (
278+ {
279+ "message" : "Entity does not support SLO" ,
280+ "entity" : entity_id ,
281+ }
304282 )
283+ continue
305284
306- relay_state = self ._relay_state (req_id )
307- http_info = self .apply_binding (
308- binding ,
309- str (request ),
310- destination ,
311- relay_state ,
312- sign = sign_redirect ,
313- sigalg = sign_alg ,
285+ service_info = bindings_slo_supported [binding ]
286+ service_location = next (locations (service_info ), None )
287+ if not service_location :
288+ logger .info (
289+ {
290+ "message" : "Entity SLO service does not have a location" ,
291+ "entity" : entity_id ,
292+ "service_location" : service_location ,
293+ }
314294 )
295+ continue
315296
316- if binding == BINDING_SOAP :
317- response = self .send (** http_info )
318- if response and response .status_code == 200 :
319- not_done .remove (entity_id )
320- response = response .text
321- logger .info ("Response: %s" , response )
322- res = self .parse_logout_request_response (response , binding )
323- responses [entity_id ] = res
324- else :
325- logger .info ("NOT OK response from %s" , destination )
297+ session_info = self .users .get_info_from (name_id , entity_id , False )
298+ session_index = session_info .get ('session_index' )
299+ session_indexes = [session_index ] if session_index else None
300+
301+ sign = sign if sign is not None else self .logout_requests_signed
302+ sign_post = sign and (
303+ binding == BINDING_HTTP_POST or binding == BINDING_SOAP
304+ )
305+ sign_redirect = sign and binding == BINDING_HTTP_REDIRECT
306+
307+ log_report = {
308+ "message" : "Invoking SLO on entity" ,
309+ "entity" : entity_id ,
310+ "binding" : binding ,
311+ "location" : service_location ,
312+ "session_indexes" : session_indexes ,
313+ "sign" : sign ,
314+ }
315+ logger .info (log_report )
316+
317+ req_id , request = self .create_logout_request (
318+ service_location ,
319+ entity_id ,
320+ name_id = name_id ,
321+ reason = reason ,
322+ expire = expire ,
323+ session_indexes = session_indexes ,
324+ sign = sign_post ,
325+ sign_alg = sign_alg ,
326+ digest_alg = digest_alg ,
327+ )
328+ relay_state = self ._relay_state (req_id )
329+ http_info = self .apply_binding (
330+ binding ,
331+ str (request ),
332+ service_location ,
333+ relay_state ,
334+ sign = sign_redirect ,
335+ sigalg = sign_alg ,
336+ )
337+
338+ if binding == BINDING_SOAP :
339+ response = self .send (** http_info )
340+ if response and response .status_code == 200 :
341+ not_done .remove (entity_id )
342+ response_text = response .text
343+ log_report_response = {
344+ ** log_report ,
345+ "message" : "Response from SLO service" ,
346+ "response_text" : response_text ,
347+ }
348+ logger .debug (log_report_response )
349+ res = self .parse_logout_request_response (response_text , binding )
350+ responses [entity_id ] = res
326351 else :
327- self .state [req_id ] = {
328- "entity_id" : entity_id ,
329- "operation" : "SLO" ,
330- "entity_ids" : entity_ids ,
331- "name_id" : code (name_id ),
332- "reason" : reason ,
333- "not_on_or_after" : expire ,
334- "sign" : sign ,
352+ log_report_response = {
353+ ** log_report ,
354+ "message" : "Bad status_code response from SLO service" ,
355+ "status_code" : (response and response .status_code ),
335356 }
336- responses [entity_id ] = (binding , http_info )
337- not_done .remove (entity_id )
338-
339- # only try one binding
340- break
357+ logger .info (log_report_response )
358+ else :
359+ self .state [req_id ] = {
360+ "entity_id" : entity_id ,
361+ "operation" : "SLO" ,
362+ "entity_ids" : entity_ids ,
363+ "name_id" : code (name_id ),
364+ "reason" : reason ,
365+ "not_on_or_after" : expire ,
366+ "sign" : sign ,
367+ }
368+ responses [entity_id ] = (binding , http_info )
369+ not_done .remove (entity_id )
341370
342371 if not_done :
343372 # upstream should try later
0 commit comments