4646from saml2 .samlp import AuthnRequest , IDPEntry , IDPList , Scoping
4747from saml2 .sigver import MissingKey
4848from saml2 .validate import ResponseLifetimeExceed , ToEarly
49- from saml2 .xmldsig import ( # support for SHA1 is required by spec
50- SIG_RSA_SHA1 , SIG_RSA_SHA256 )
5149
5250from .cache import IdentityCache , OutstandingQueriesCache , StateCache
5351from .conf import get_config
@@ -160,6 +158,8 @@ def get(self, request, *args, **kwargs):
160158 configured_idps = available_idps (conf )
161159 selected_idp = request .GET .get ('idp' , None )
162160
161+ sso_kwargs = {}
162+
163163 # Do we have a Discovery Service?
164164 if not selected_idp :
165165 discovery_service = getattr (settings , 'SAML2_DISCO_URL' , None )
@@ -193,14 +193,19 @@ def get(self, request, *args, **kwargs):
193193 selected_idp = list (configured_idps .keys ())[0 ]
194194
195195 # perform IdP Scoping if scoping param is present
196- idp_scoping = Scoping ()
197196 idp_scoping_param = request .GET .get ('scoping' , None )
198197 if idp_scoping_param :
198+ idp_scoping = Scoping ()
199199 idp_scoping .idp_list = IDPList ()
200- idp_scoping .idp_list .idp_entry .append (IDPEntry (provider_id = idp_scoping_param ))
200+ idp_scoping .idp_list .idp_entry .append (
201+ IDPEntry (provider_id = idp_scoping_param )
202+ )
203+ sso_kwargs ['scoping' ] = idp_scoping
204+
201205
202206 # choose a binding to try first
203- binding = getattr (settings , 'SAML_DEFAULT_BINDING' , saml2 .BINDING_HTTP_POST )
207+ binding = getattr (settings , 'SAML_DEFAULT_BINDING' ,
208+ saml2 .BINDING_HTTP_POST )
204209 logger .debug (f'Trying binding { binding } for IDP { selected_idp } ' )
205210
206211 # ensure our selected binding is supported by the IDP
@@ -232,18 +237,16 @@ def get(self, request, *args, **kwargs):
232237 )
233238
234239 client = Saml2Client (conf )
235- http_response = None
236240
237241 # SSO options
238242 sign_requests = getattr (conf , '_sp_authn_requests_signed' , False )
239- sso_kwargs = {}
243+
240244 if sign_requests :
241- sso_kwargs ["sigalg" ] = settings .SAML_CONFIG ['service' ]['sp' ]\
242- .get ('signing_algorithm' ,
243- saml2 .xmldsig .SIG_RSA_SHA256 )
244- sso_kwargs ["digest_alg" ] = settings .SAML_CONFIG ['service' ]['sp' ]\
245- .get ('digest_algorithm' ,
246- saml2 .xmldsig .DIGEST_SHA256 )
245+ csc = settings .SAML_CONFIG ['service' ]['sp' ]
246+ sso_kwargs ["sigalg" ] = csc .get ('signing_algorithm' ,
247+ saml2 .xmldsig .SIG_RSA_SHA256 )
248+ sso_kwargs ["digest_alg" ] = csc .get ('digest_algorithm' ,
249+ saml2 .xmldsig .DIGEST_SHA256 )
247250
248251 # pysaml needs a string otherwise: "cannot serialize True (type bool)"
249252 if getattr (conf , '_sp_force_authn' , False ):
@@ -256,17 +259,20 @@ def get(self, request, *args, **kwargs):
256259
257260 logger .debug (f'Redirecting user to the IdP via { binding } binding.' )
258261 _msg = 'Unable to know which IdP to use'
262+ http_response = None
263+
259264 if binding == saml2 .BINDING_HTTP_REDIRECT :
260265 try :
261266 session_id , result = client .prepare_for_authenticate (
262267 entityid = selected_idp , relay_state = next_path ,
263- binding = binding , sign = sign_requests , scoping = idp_scoping ,
268+ binding = binding , sign = sign_requests ,
264269 ** sso_kwargs )
265270 except TypeError as e :
266271 logger .error (f'{ _msg } : { e } ' )
267272 return HttpResponse (_msg )
268273 else :
269274 http_response = HttpResponseRedirect (get_location (result ))
275+
270276 elif binding == saml2 .BINDING_HTTP_POST :
271277 if self .post_binding_form_template :
272278 # get request XML to build our own html based on the template
@@ -275,10 +281,12 @@ def get(self, request, *args, **kwargs):
275281 except TypeError as e :
276282 logger .error (f'{ _msg } : { e } ' )
277283 return HttpResponse (_msg )
284+
278285 session_id , request_xml = client .create_authn_request (
279286 location ,
280287 binding = binding ,
281- ** sso_kwargs )
288+ ** sso_kwargs
289+ )
282290 try :
283291 if isinstance (request_xml , AuthnRequest ):
284292 # request_xml will be an instance of AuthnRequest if the message is not signed
@@ -294,14 +302,16 @@ def get(self, request, *args, **kwargs):
294302 },
295303 })
296304 except TemplateDoesNotExist as e :
297- logger .error (f'TemplateDoesNotExist: { e } ' )
305+ logger .error (
306+ f'TemplateDoesNotExist: [{ self .post_binding_form_template } ] - { e } '
307+ )
298308
299309 if not http_response :
300310 # use the html provided by pysaml2 if no template was specified or it doesn't exist
301311 try :
302312 session_id , result = client .prepare_for_authenticate (
303313 entityid = selected_idp , relay_state = next_path ,
304- binding = binding , scoping = idp_scoping )
314+ binding = binding , ** sso_kwargs )
305315 except TypeError as e :
306316 _msg = f"Can't prepare the authentication for { selected_idp } "
307317 logger .error (f'{ _msg } : { e } ' )
@@ -380,7 +390,8 @@ def post(self, request, attribute_mapping=None, create_unknown_user=None):
380390 except ResponseLifetimeExceed as e :
381391 _exception = e
382392 logger .info (
383- ("SAML Assertion is no longer valid. Possibly caused by network delay or replay attack." ), exc_info = True )
393+ ("SAML Assertion is no longer valid. Possibly caused "
394+ "by network delay or replay attack." ), exc_info = True )
384395 except SignatureError as e :
385396 _exception = e
386397 logger .info ("Invalid or malformed SAML Assertion." , exc_info = True )
@@ -435,7 +446,8 @@ def post(self, request, attribute_mapping=None, create_unknown_user=None):
435446 for sc in assertion .subject .subject_confirmation :
436447 if sc .method == SCM_BEARER :
437448 assertion_not_on_or_after = sc .subject_confirmation_data .not_on_or_after
438- assertion_info = {'assertion_id' : assertion .id , 'not_on_or_after' : assertion_not_on_or_after }
449+ assertion_info = {'assertion_id' : assertion .id ,
450+ 'not_on_or_after' : assertion_not_on_or_after }
439451 break
440452
441453 if callable (attribute_mapping ):
@@ -607,10 +619,14 @@ class LogoutView(SPConfigMixin, View):
607619 logout_error_template = 'djangosaml2/logout_error.html'
608620
609621 def get (self , request , * args , ** kwargs ):
610- return self .do_logout_service (request , request .GET , saml2 .BINDING_HTTP_REDIRECT , * args , ** kwargs )
622+ return self .do_logout_service (
623+ request , request .GET , saml2 .BINDING_HTTP_REDIRECT , * args , ** kwargs
624+ )
611625
612626 def post (self , request , * args , ** kwargs ):
613- return self .do_logout_service (request , request .POST , saml2 .BINDING_HTTP_POST , * args , ** kwargs )
627+ return self .do_logout_service (
628+ request , request .POST , saml2 .BINDING_HTTP_POST , * args , ** kwargs
629+ )
614630
615631 def do_logout_service (self , request , data , binding ):
616632 logger .debug ('Logout service started' )
0 commit comments