1010
1111from saml2 .entity import Entity
1212
13+ import saml2 .attributemaps as attributemaps
14+
1315from saml2 .mdstore import destinations
1416from saml2 .profile import paos , ecp
1517from saml2 .saml import NAMEID_FORMAT_TRANSIENT
1820from saml2 .samlp import AttributeQuery
1921from saml2 .samlp import AuthzDecisionQuery
2022from saml2 .samlp import AuthnRequest
23+ from saml2 .samlp import Extensions
24+ from saml2 .extension import sp_type
25+ from saml2 .extension import requested_attributes
2126
2227import saml2
2328import time
@@ -207,7 +212,7 @@ def create_authn_request(self, destination, vorg="", scoping=None,
207212 nameid_format = None ,
208213 service_url_binding = None , message_id = 0 ,
209214 consent = None , extensions = None , sign = None ,
210- allow_create = False , sign_prepare = False , sign_alg = None ,
215+ allow_create = None , sign_prepare = False , sign_alg = None ,
211216 digest_alg = None , ** kwargs ):
212217 """ Creates an authentication request.
213218
@@ -235,26 +240,30 @@ def create_authn_request(self, destination, vorg="", scoping=None,
235240
236241 args = {}
237242
238- try :
239- args ["assertion_consumer_service_url" ] = kwargs [
240- "assertion_consumer_service_urls" ][0 ]
241- del kwargs ["assertion_consumer_service_urls" ]
242- except KeyError :
243+ if self .config .getattr ('hide_assertion_consumer_service' , 'sp' ):
244+ args ["assertion_consumer_service_url" ] = None
245+ binding = None
246+ else :
243247 try :
244248 args ["assertion_consumer_service_url" ] = kwargs [
245- "assertion_consumer_service_url" ]
246- del kwargs ["assertion_consumer_service_url " ]
249+ "assertion_consumer_service_urls" ][ 0 ]
250+ del kwargs ["assertion_consumer_service_urls " ]
247251 except KeyError :
248252 try :
249- args ["assertion_consumer_service_index " ] = str ( kwargs [
250- "assertion_consumer_service_index" ])
251- del kwargs ["assertion_consumer_service_index " ]
253+ args ["assertion_consumer_service_url " ] = kwargs [
254+ "assertion_consumer_service_url" ]
255+ del kwargs ["assertion_consumer_service_url " ]
252256 except KeyError :
253- if service_url_binding is None :
254- service_urls = self .service_urls (binding )
255- else :
256- service_urls = self .service_urls (service_url_binding )
257- args ["assertion_consumer_service_url" ] = service_urls [0 ]
257+ try :
258+ args ["assertion_consumer_service_index" ] = str (
259+ kwargs ["assertion_consumer_service_index" ])
260+ del kwargs ["assertion_consumer_service_index" ]
261+ except KeyError :
262+ if service_url_binding is None :
263+ service_urls = self .service_urls (binding )
264+ else :
265+ service_urls = self .service_urls (service_url_binding )
266+ args ["assertion_consumer_service_url" ] = service_urls [0 ]
258267
259268 try :
260269 args ["provider_name" ] = kwargs ["provider_name" ]
@@ -268,7 +277,7 @@ def create_authn_request(self, destination, vorg="", scoping=None,
268277 # all of these have cardinality 0..1
269278 _msg = AuthnRequest ()
270279 for param in ["scoping" , "requested_authn_context" , "conditions" ,
271- "subject" , "scoping" ]:
280+ "subject" ]:
272281 try :
273282 _item = kwargs [param ]
274283 except KeyError :
@@ -288,23 +297,37 @@ def create_authn_request(self, destination, vorg="", scoping=None,
288297 args ["name_id_policy" ] = kwargs ["name_id_policy" ]
289298 del kwargs ["name_id_policy" ]
290299 except KeyError :
291- if allow_create :
292- allow_create = "true"
293- else :
294- allow_create = "false"
300+ if allow_create is None :
301+ allow_create = self .config .getattr ("name_id_format_allow_create" , "sp" )
302+ if allow_create is None :
303+ allow_create = "false"
304+ else :
305+ if allow_create is True :
306+ allow_create = "true"
307+ else :
308+ allow_create = "false"
295309
296310 if nameid_format == "" :
297311 name_id_policy = None
298312 else :
299313 if nameid_format is None :
300314 nameid_format = self .config .getattr ("name_id_format" , "sp" )
301315
316+ # If no nameid_format has been set in the configuration
317+ # or passed in then transient is the default.
302318 if nameid_format is None :
303319 nameid_format = NAMEID_FORMAT_TRANSIENT
320+
321+ # If a list has been configured or passed in choose the
322+ # first since NameIDPolicy can only have one format specified.
304323 elif isinstance (nameid_format , list ):
305- # NameIDPolicy can only have one format specified
306324 nameid_format = nameid_format [0 ]
307325
326+ # Allow a deployer to signal that no format should be specified
327+ # in the NameIDPolicy by passing in or configuring the string 'None'.
328+ elif nameid_format == 'None' :
329+ nameid_format = None
330+
308331 name_id_policy = samlp .NameIDPolicy (allow_create = allow_create ,
309332 format = nameid_format )
310333
@@ -321,6 +344,75 @@ def create_authn_request(self, destination, vorg="", scoping=None,
321344 except KeyError :
322345 nsprefix = None
323346
347+ try :
348+ force_authn = kwargs ['force_authn' ]
349+ except KeyError :
350+ force_authn = self .config .getattr ('force_authn' , 'sp' )
351+ finally :
352+ if force_authn :
353+ args ['force_authn' ] = 'true'
354+
355+ conf_sp_type = self .config .getattr ('sp_type' , 'sp' )
356+ conf_sp_type_in_md = self .config .getattr ('sp_type_in_metadata' , 'sp' )
357+ if conf_sp_type and conf_sp_type_in_md is False :
358+ if not extensions :
359+ extensions = Extensions ()
360+ item = sp_type .SPType (text = conf_sp_type )
361+ extensions .add_extension_element (item )
362+
363+ requested_attrs = self .config .getattr ('requested_attributes' , 'sp' )
364+ if requested_attrs :
365+ if not extensions :
366+ extensions = Extensions ()
367+
368+ attributemapsmods = []
369+ for modname in attributemaps .__all__ :
370+ attributemapsmods .append (getattr (attributemaps , modname ))
371+
372+ items = []
373+ for attr in requested_attrs :
374+ friendly_name = attr .get ('friendly_name' )
375+ name = attr .get ('name' )
376+ name_format = attr .get ('name_format' )
377+ is_required = str (attr .get ('required' , False )).lower ()
378+
379+ if not name and not friendly_name :
380+ raise ValueError (
381+ "Missing required attribute: '{}' or '{}'" .format (
382+ 'name' , 'friendly_name' ))
383+
384+ if not name :
385+ for mod in attributemapsmods :
386+ try :
387+ name = mod .MAP ['to' ][friendly_name ]
388+ except KeyError :
389+ continue
390+ else :
391+ if not name_format :
392+ name_format = mod .MAP ['identifier' ]
393+ break
394+
395+ if not friendly_name :
396+ for mod in attributemapsmods :
397+ try :
398+ friendly_name = mod .MAP ['fro' ][name ]
399+ except KeyError :
400+ continue
401+ else :
402+ if not name_format :
403+ name_format = mod .MAP ['identifier' ]
404+ break
405+
406+ items .append (requested_attributes .RequestedAttribute (
407+ is_required = is_required ,
408+ name_format = name_format ,
409+ friendly_name = friendly_name ,
410+ name = name ))
411+
412+ item = requested_attributes .RequestedAttributes (
413+ extension_elements = items )
414+ extensions .add_extension_element (item )
415+
324416 if kwargs :
325417 _args , extensions = self ._filter_args (AuthnRequest (), extensions ,
326418 ** kwargs )
0 commit comments