@@ -251,93 +251,122 @@ def do_logout(
251
251
not_done = entity_ids [:]
252
252
responses = {}
253
253
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
+
259
256
for entity_id in entity_ids :
260
257
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 ,
291
273
)
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
+ }
304
282
)
283
+ continue
305
284
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
+ }
314
294
)
295
+ continue
315
296
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
326
351
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 ),
335
356
}
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 )
341
370
342
371
if not_done :
343
372
# upstream should try later
0 commit comments