1414from saml2 import BINDING_HTTP_POST
1515from saml2 import BINDING_SOAP
1616
17- import saml2 .xmldsig as ds
17+ from saml2 .xmldsig import DefaultSignature
1818
1919from saml2 .ident import decode , code
2020from saml2 .httpbase import HTTPError
@@ -40,10 +40,19 @@ class Saml2Client(Base):
4040 """ The basic pySAML2 service provider class """
4141
4242 def prepare_for_authenticate (
43- self , entityid = None , relay_state = "" ,
44- binding = saml2 .BINDING_HTTP_REDIRECT , vorg = "" , nameid_format = None ,
45- scoping = None , consent = None , extensions = None , sign = None ,
46- response_binding = saml2 .BINDING_HTTP_POST , ** kwargs ):
43+ self ,
44+ entityid = None ,
45+ relay_state = "" ,
46+ binding = saml2 .BINDING_HTTP_REDIRECT ,
47+ vorg = "" ,
48+ nameid_format = None ,
49+ scoping = None ,
50+ consent = None , extensions = None ,
51+ sign = None ,
52+ sigalg = None ,
53+ response_binding = saml2 .BINDING_HTTP_POST ,
54+ ** kwargs ,
55+ ):
4756 """ Makes all necessary preparations for an authentication request.
4857
4958 :param entityid: The entity ID of the IdP to send the request to
@@ -61,19 +70,20 @@ def prepare_for_authenticate(
6170 :return: session id and AuthnRequest info
6271 """
6372
64- reqid , negotiated_binding , info = \
65- self .prepare_for_negotiated_authenticate (
66- entityid = entityid ,
67- relay_state = relay_state ,
68- binding = binding ,
69- vorg = vorg ,
70- nameid_format = nameid_format ,
71- scoping = scoping ,
72- consent = consent ,
73- extensions = extensions ,
74- sign = sign ,
75- response_binding = response_binding ,
76- ** kwargs )
73+ reqid , negotiated_binding , info = self .prepare_for_negotiated_authenticate (
74+ entityid = entityid ,
75+ relay_state = relay_state ,
76+ binding = binding ,
77+ vorg = vorg ,
78+ nameid_format = nameid_format ,
79+ scoping = scoping ,
80+ consent = consent ,
81+ extensions = extensions ,
82+ sign = sign ,
83+ sigalg = sigalg ,
84+ response_binding = response_binding ,
85+ ** kwargs ,
86+ )
7787
7888 if negotiated_binding != binding :
7989 raise ValueError (
@@ -85,9 +95,20 @@ def prepare_for_authenticate(
8595 return reqid , info
8696
8797 def prepare_for_negotiated_authenticate (
88- self , entityid = None , relay_state = "" , binding = None , vorg = "" ,
89- nameid_format = None , scoping = None , consent = None , extensions = None ,
90- sign = None , response_binding = saml2 .BINDING_HTTP_POST , ** kwargs ):
98+ self ,
99+ entityid = None ,
100+ relay_state = "" ,
101+ binding = None ,
102+ vorg = "" ,
103+ nameid_format = None ,
104+ scoping = None ,
105+ consent = None ,
106+ extensions = None ,
107+ sign = None ,
108+ response_binding = saml2 .BINDING_HTTP_POST ,
109+ sigalg = None ,
110+ ** kwargs ,
111+ ):
91112 """ Makes all necessary preparations for an authentication request
92113 that negotiates which binding to use for authentication.
93114
@@ -115,27 +136,41 @@ def prepare_for_negotiated_authenticate(
115136 destination = self ._sso_location (entityid , binding )
116137 logger .info ("destination to provider: %s" , destination )
117138
139+ # XXX - sign_post will embed the signature to the xml doc
140+ # XXX ^through self.create_authn_request(...)
141+ # XXX - sign_redirect will add the signature to the query params
142+ # XXX ^through self.apply_binding(...)
143+ sign_post = (binding == BINDING_HTTP_POST and sign )
144+ sign_redirect = (binding == BINDING_HTTP_REDIRECT and sign )
145+
118146 reqid , request = self .create_authn_request (
119- destination , vorg , scoping , response_binding , nameid_format ,
120- consent = consent , extensions = extensions , sign = sign ,
121- ** kwargs )
147+ destination ,
148+ vorg ,
149+ scoping ,
150+ response_binding ,
151+ nameid_format ,
152+ consent = consent ,
153+ extensions = extensions ,
154+ sign = sign_post ,
155+ sign_alg = sigalg ,
156+ ** kwargs ,
157+ )
122158
123159 _req_str = str (request )
124-
125160 logger .info ("AuthNReq: %s" , _req_str )
126161
127- try :
128- args = {'sigalg' : kwargs ["sigalg" ]}
129- except KeyError :
130- args = {}
131-
132- http_info = self .apply_binding (binding , _req_str , destination ,
133- relay_state , sign = sign , ** args )
162+ http_info = self .apply_binding (
163+ binding ,
164+ _req_str ,
165+ destination ,
166+ relay_state ,
167+ sign = sign_redirect ,
168+ sigalg = sigalg ,
169+ )
134170
135171 return reqid , binding , http_info
136172 else :
137- raise SignOnError (
138- "No supported bindings available for authentication" )
173+ raise SignOnError ("No supported bindings available for authentication" )
139174
140175 def global_logout (self , name_id , reason = "" , expire = None , sign = None ,
141176 sign_alg = None , digest_alg = None ):
@@ -194,14 +229,13 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
194229 for entity_id in entity_ids :
195230 logger .debug ("Logout from '%s'" , entity_id )
196231 # for all where I can use the SOAP binding, do those first
197- for binding in [BINDING_SOAP , BINDING_HTTP_POST ,
198- BINDING_HTTP_REDIRECT ]:
232+ for binding in [BINDING_SOAP , BINDING_HTTP_POST , BINDING_HTTP_REDIRECT ]:
199233 if expected_binding and binding != expected_binding :
200234 continue
201235 try :
202- srvs = self .metadata .single_logout_service (entity_id ,
203- binding ,
204- "idpsso" )
236+ srvs = self .metadata .single_logout_service (
237+ entity_id , binding , "idpsso"
238+ )
205239 except :
206240 srvs = None
207241
@@ -212,63 +246,66 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
212246 destination = next (locations (srvs ), None )
213247 logger .info ("destination to provider: %s" , destination )
214248 try :
215- session_info = self .users .get_info_from (name_id ,
216- entity_id ,
217- False )
249+ session_info = self .users .get_info_from (
250+ name_id , entity_id , False
251+ )
218252 session_indexes = [session_info ['session_index' ]]
219253 except KeyError :
220254 session_indexes = None
221255 req_id , request = self .create_logout_request (
222256 destination , entity_id , name_id = name_id , reason = reason ,
223257 expire = expire , session_indexes = session_indexes )
224258
225- # to_sign = []
226- if binding .startswith ("http://" ):
227- sign = True
228-
229- if sign is None :
230- sign = self .logout_requests_signed
259+ sign = sign if sign is not None else self .logout_requests_signed
260+ def_sig = DefaultSignature ()
261+ sign_alg = def_sig .get_sign_alg () if sign_alg is None else sign_alg
262+ digest_alg = (
263+ def_sig .get_digest_alg ()
264+ if digest_alg is None
265+ else digest_alg
266+ )
231267
232- sigalg = None
233268 if sign :
234269 if binding == BINDING_HTTP_REDIRECT :
235- sigalg = kwargs .get (
236- "sigalg" , ds .DefaultSignature ().get_sign_alg ())
237- # key = kwargs.get("key", self.signkey)
238270 srequest = str (request )
239271 else :
240- srequest = self .sign (request , sign_alg = sign_alg ,
241- digest_alg = digest_alg )
272+ srequest = self .sign (
273+ request , sign_alg = sign_alg , digest_alg = digest_alg
274+ )
242275 else :
243276 srequest = str (request )
244277
245278 relay_state = self ._relay_state (req_id )
246279
247- http_info = self .apply_binding (binding , srequest , destination ,
248- relay_state , sign = sign , sigalg = sigalg )
280+ http_info = self .apply_binding (
281+ binding ,
282+ srequest ,
283+ destination ,
284+ relay_state ,
285+ sign = sign ,
286+ sigalg = sign_alg ,
287+ )
249288
250289 if binding == BINDING_SOAP :
251290 response = self .send (** http_info )
252-
253291 if response and response .status_code == 200 :
254292 not_done .remove (entity_id )
255293 response = response .text
256294 logger .info ("Response: %s" , response )
257- res = self .parse_logout_request_response (response ,
258- binding )
295+ res = self .parse_logout_request_response (response , binding )
259296 responses [entity_id ] = res
260297 else :
261298 logger .info ("NOT OK response from %s" , destination )
262-
263299 else :
264- self .state [req_id ] = {"entity_id" : entity_id ,
265- "operation" : "SLO" ,
266- "entity_ids" : entity_ids ,
267- "name_id" : code (name_id ),
268- "reason" : reason ,
269- "not_on_or_after" : expire ,
270- "sign" : sign }
271-
300+ self .state [req_id ] = {
301+ "entity_id" : entity_id ,
302+ "operation" : "SLO" ,
303+ "entity_ids" : entity_ids ,
304+ "name_id" : code (name_id ),
305+ "reason" : reason ,
306+ "not_on_or_after" : expire ,
307+ "sign" : sign ,
308+ }
272309 responses [entity_id ] = (binding , http_info )
273310 not_done .remove (entity_id )
274311
@@ -419,11 +456,22 @@ def do_authn_query(self, entity_id,
419456
420457 return None
421458
422- def do_attribute_query (self , entityid , subject_id ,
423- attribute = None , sp_name_qualifier = None ,
424- name_qualifier = None , nameid_format = None ,
425- real_id = None , consent = None , extensions = None ,
426- sign = False , binding = BINDING_SOAP , nsprefix = None ):
459+ def do_attribute_query (
460+ self ,
461+ entityid ,
462+ subject_id ,
463+ attribute = None ,
464+ sp_name_qualifier = None ,
465+ name_qualifier = None ,
466+ nameid_format = None ,
467+ real_id = None ,
468+ consent = None ,
469+ extensions = None ,
470+ sign = False ,
471+ binding = BINDING_SOAP ,
472+ nsprefix = None ,
473+ sign_alg = None ,
474+ ):
427475 """ Does a attribute request to an attribute authority, this is
428476 by default done over SOAP.
429477
@@ -482,13 +530,20 @@ def do_attribute_query(self, entityid, subject_id,
482530 "subject_id" : subject_id ,
483531 "sign" : sign }
484532 relay_state = self ._relay_state (query .id )
485- return self .apply_binding (binding , "%s" % query , destination ,
486- relay_state , sign = sign )
533+ return self .apply_binding (
534+ binding ,
535+ str (query ),
536+ destination ,
537+ relay_state ,
538+ sign = sign ,
539+ sigalg = sign_alg ,
540+ )
487541 else :
488542 raise SAMLError ("Unsupported binding" )
489543
490- def handle_logout_request (self , request , name_id , binding , sign = None ,
491- sign_alg = None , relay_state = "" ):
544+ def handle_logout_request (
545+ self , request , name_id , binding , sign = None , sign_alg = None , relay_state = ""
546+ ):
492547 """
493548 Deal with a LogoutRequest
494549
@@ -531,16 +586,22 @@ def handle_logout_request(self, request, name_id, binding, sign=None,
531586 elif binding in [BINDING_HTTP_POST , BINDING_HTTP_REDIRECT ]:
532587 response_bindings = [BINDING_HTTP_POST , BINDING_HTTP_REDIRECT ]
533588 else :
534- response_bindings = self .config .preferred_binding [
535- "single_logout_service" ]
589+ response_bindings = self .config .preferred_binding ["single_logout_service" ]
536590
537591 if sign is None :
538592 sign = self .logout_responses_signed
539593
540- response = self .create_logout_response (_req .message , response_bindings ,
541- status , sign , sign_alg = sign_alg )
594+ response = self .create_logout_response (
595+ _req .message , response_bindings , status , sign , sign_alg = sign_alg
596+ )
542597 rinfo = self .response_args (_req .message , response_bindings )
543598
544- return self .apply_binding (rinfo ["binding" ], response ,
545- rinfo ["destination" ], relay_state ,
546- response = True , sign = sign )
599+ return self .apply_binding (
600+ rinfo ["binding" ],
601+ response ,
602+ rinfo ["destination" ],
603+ relay_state ,
604+ response = True ,
605+ sign = sign ,
606+ sigalg = sign_alg ,
607+ )
0 commit comments