def requested_authn_context(class_ref, comparison="minimum"): if not isinstance(class_ref, list): class_ref = [class_ref] return RequestedAuthnContext(authn_context_class_ref=[ AuthnContextClassRef(text=i) for i in class_ref ], comparison=comparison)
def create_authn_request(relay_state, selected_idp, required_loa, force_authn=False): kwargs = { "force_authn": str(force_authn).lower(), } # LOA current_app.logger.debug('Requesting AuthnContext {}'.format(required_loa)) loa_uri = current_app.config.authentication_context_map[required_loa] requested_authn_context = RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef(text=loa_uri), comparison='exact' ) kwargs['requested_authn_context'] = requested_authn_context # Authn algorithms kwargs['sign_alg'] = current_app.config.authn_sign_alg kwargs['digest_alg'] = current_app.config.authn_digest_alg client = Saml2Client(current_app.saml2_config) try: session_id, info = client.prepare_for_authenticate( entityid=selected_idp, relay_state=relay_state, binding=BINDING_HTTP_REDIRECT, **kwargs ) except TypeError: current_app.logger.error('Unable to know which IdP to use') raise oq_cache = OutstandingQueriesCache(session) oq_cache.set(session_id, relay_state) return info
def get_authn_request(config, session, came_from, selected_idp, required_loa=None, force_authn=False): # Request the right AuthnContext for workmode # (AL1 for 'personal', AL2 for 'helpdesk' and AL3 for 'admin' by default) if required_loa is None: required_loa = config.get('required_loa', {}) workmode = config.get('workmode', 'personal') required_loa = required_loa.get(workmode, '') logger.debug('Requesting AuthnContext {!r}'.format(required_loa)) kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=required_loa ) ), "force_authn": str(force_authn).lower(), } client = Saml2Client(get_saml2_config(config['SAML2_SETTINGS_MODULE'])) try: (session_id, info) = client.prepare_for_authenticate( entityid=selected_idp, relay_state=came_from, binding=BINDING_HTTP_REDIRECT, **kwargs ) except TypeError: logger.error('Unable to know which IdP to use') raise oq_cache = OutstandingQueriesCache(session) oq_cache.set(session_id, came_from) return info
def load_sso_kwargs_authn_context(self, sso_kwargs): # this would work when https://github.com/IdentityPython/pysaml2/pull/807 ac = getattr(self.conf, '_sp_requested_authn_context', {}) # this works even without https://github.com/IdentityPython/pysaml2/pull/807 # hopefully to be removed soon ! if not ac: scs = getattr(settings, 'SAML_CONFIG', {}).get('service', {}).get('sp', {}) ac = scs.get('requested_authn_context', {}) # end transitional things to be removed soon ! if ac: sso_kwargs["requested_authn_context"] = RequestedAuthnContext( authn_context_class_ref=[ AuthnContextClassRef(ac['authn_context_class_ref']), ], comparison=ac.get('comparison', "minimum"), )
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name="", dont_send=False): try: _binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) if "accr" in self.kwargs: kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=self.kwargs["accr"])) } else: kwargs = {} req = _cli.create_authn_request(destination, vorg=vorg_name, **kwargs) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req.id SESSIONDB[_sid] = self.kwargs logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError("Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response)
def requested_authn_context(class_ref, comparison="minimum"): return RequestedAuthnContext( authn_context_class_ref=[AuthnContextClassRef(text=class_ref)], comparison=comparison)
def create_authn_request(self, destination, vorg="", scoping=None, binding=saml2.BINDING_HTTP_POST, nameid_format=None, service_url_binding=None, message_id=0, consent=None, extensions=None, sign=None, allow_create=None, sign_prepare=False, sign_alg=None, digest_alg=None, **kwargs): """ Creates an authentication request. :param destination: Where the request should be sent. :param vorg: The virtual organization the service belongs to. :param scoping: The scope of the request :param binding: The protocol to use for the Response !! :param nameid_format: Format of the NameID :param service_url_binding: Where the reply should be sent dependent on reply binding. :param message_id: The identifier for this request :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the request should be signed or not. :param sign_prepare: Whether the signature should be prepared or not. :param allow_create: If the identity provider is allowed, in the course of fulfilling the request, to create a new identifier to represent the principal. :param kwargs: Extra key word arguments :return: tuple of request ID and <samlp:AuthnRequest> instance """ client_crt = None if "client_crt" in kwargs: client_crt = kwargs["client_crt"] args = {} if self.config.getattr('hide_assertion_consumer_service', 'sp'): args["assertion_consumer_service_url"] = None binding = None else: try: args["assertion_consumer_service_url"] = kwargs[ "assertion_consumer_service_urls"][0] del kwargs["assertion_consumer_service_urls"] except KeyError: try: args["assertion_consumer_service_url"] = kwargs[ "assertion_consumer_service_url"] del kwargs["assertion_consumer_service_url"] except KeyError: try: args["assertion_consumer_service_index"] = str( kwargs["assertion_consumer_service_index"]) del kwargs["assertion_consumer_service_index"] except KeyError: if service_url_binding is None: service_urls = self.service_urls(binding) else: service_urls = self.service_urls( service_url_binding) args["assertion_consumer_service_url"] = service_urls[ 0] try: args["provider_name"] = kwargs["provider_name"] except KeyError: if binding == BINDING_PAOS: pass else: args["provider_name"] = self._my_name() # Allow argument values either as class instances or as dictionaries # all of these have cardinality 0..1 _msg = AuthnRequest() for param in [ "scoping", "requested_authn_context", "conditions", "subject" ]: try: _item = kwargs[param] except KeyError: pass else: del kwargs[param] # either class instance or argument dictionary if isinstance(_item, _msg.child_class(param)): args[param] = _item elif isinstance(_item, dict): args[param] = RequestedAuthnContext(**_item) else: raise ValueError("%s or wrong type expected %s" % (_item, param)) try: args["name_id_policy"] = kwargs["name_id_policy"] del kwargs["name_id_policy"] except KeyError: if allow_create is None: allow_create = self.config.getattr( "name_id_format_allow_create", "sp") if allow_create is None: allow_create = "false" else: if allow_create is True: allow_create = "true" else: allow_create = "false" if nameid_format == "": name_id_policy = None else: if nameid_format is None: nameid_format = self.config.getattr("name_id_format", "sp") # If no nameid_format has been set in the configuration # or passed in then transient is the default. if nameid_format is None: nameid_format = NAMEID_FORMAT_TRANSIENT # If a list has been configured or passed in choose the # first since NameIDPolicy can only have one format specified. elif isinstance(nameid_format, list): nameid_format = nameid_format[0] # Allow a deployer to signal that no format should be specified # in the NameIDPolicy by passing in or configuring the string 'None'. elif nameid_format == 'None': nameid_format = None name_id_policy = samlp.NameIDPolicy(allow_create=allow_create, format=nameid_format) if name_id_policy and vorg: try: name_id_policy.sp_name_qualifier = vorg name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT except KeyError: pass args["name_id_policy"] = name_id_policy try: nsprefix = kwargs["nsprefix"] except KeyError: nsprefix = None try: force_authn = kwargs['force_authn'] except KeyError: force_authn = self.config.getattr('force_authn', 'sp') finally: if force_authn: args['force_authn'] = 'true' conf_sp_type = self.config.getattr('sp_type', 'sp') conf_sp_type_in_md = self.config.getattr('sp_type_in_metadata', 'sp') if conf_sp_type and conf_sp_type_in_md is False: if not extensions: extensions = Extensions() item = sp_type.SPType(text=conf_sp_type) extensions.add_extension_element(item) requested_attrs = self.config.getattr('requested_attributes', 'sp') if requested_attrs: if not extensions: extensions = Extensions() attributemapsmods = [] for modname in attributemaps.__all__: attributemapsmods.append(getattr(attributemaps, modname)) items = [] for attr in requested_attrs: friendly_name = attr.get('friendly_name') name = attr.get('name') name_format = attr.get('name_format') is_required = str(attr.get('required', False)).lower() if not name and not friendly_name: raise ValueError( "Missing required attribute: '{}' or '{}'".format( 'name', 'friendly_name')) if not name: for mod in attributemapsmods: try: name = mod.MAP['to'][friendly_name] except KeyError: continue else: if not name_format: name_format = mod.MAP['identifier'] break if not friendly_name: for mod in attributemapsmods: try: friendly_name = mod.MAP['fro'][name] except KeyError: continue else: if not name_format: name_format = mod.MAP['identifier'] break items.append( requested_attributes.RequestedAttribute( is_required=is_required, name_format=name_format, friendly_name=friendly_name, name=name)) item = requested_attributes.RequestedAttributes( extension_elements=items) extensions.add_extension_element(item) if kwargs: _args, extensions = self._filter_args(AuthnRequest(), extensions, **kwargs) args.update(_args) try: del args["id"] except KeyError: pass if sign is None: sign = self.authn_requests_signed if (sign and self.sec.cert_handler.generate_cert()) or \ client_crt is not None: with self.lock: self.sec.cert_handler.update_cert(True, client_crt) if client_crt is not None: sign_prepare = True return self._message(AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args) return self._message(AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args)
def create_authn_request(self, destination, vorg="", scoping=None, binding=saml2.BINDING_HTTP_POST, nameid_format=None, service_url_binding=None, message_id=0, consent=None, extensions=None, sign=None, allow_create=None, sign_prepare=False, sign_alg=None, digest_alg=None, **kwargs): """ Creates an authentication request. :param destination: Where the request should be sent. :param vorg: The virtual organization the service belongs to. :param scoping: The scope of the request :param binding: The protocol to use for the Response !! :param nameid_format: Format of the NameID :param service_url_binding: Where the reply should be sent dependent on reply binding. :param message_id: The identifier for this request :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the request should be signed or not. :param sign_prepare: Whether the signature should be prepared or not. :param allow_create: If the identity provider is allowed, in the course of fulfilling the request, to create a new identifier to represent the principal. :param kwargs: Extra key word arguments :return: tuple of request ID and <samlp:AuthnRequest> instance """ client_crt = None if "client_crt" in kwargs: client_crt = kwargs["client_crt"] args = {} try: args["assertion_consumer_service_url"] = kwargs[ "assertion_consumer_service_urls"][0] del kwargs["assertion_consumer_service_urls"] except KeyError: try: args["assertion_consumer_service_url"] = kwargs[ "assertion_consumer_service_url"] del kwargs["assertion_consumer_service_url"] except KeyError: try: args["assertion_consumer_service_index"] = str( kwargs["assertion_consumer_service_index"]) del kwargs["assertion_consumer_service_index"] except KeyError: if service_url_binding is None: service_urls = self.service_urls(binding) else: service_urls = self.service_urls(service_url_binding) args["assertion_consumer_service_url"] = service_urls[0] try: args["provider_name"] = kwargs["provider_name"] except KeyError: if binding == BINDING_PAOS: pass else: args["provider_name"] = self._my_name() # Allow argument values either as class instances or as dictionaries # all of these have cardinality 0..1 _msg = AuthnRequest() for param in [ "scoping", "requested_authn_context", "conditions", "subject" ]: try: _item = kwargs[param] except KeyError: pass else: del kwargs[param] # either class instance or argument dictionary if isinstance(_item, _msg.child_class(param)): args[param] = _item elif isinstance(_item, dict): args[param] = RequestedAuthnContext(**_item) else: raise ValueError("%s or wrong type expected %s" % (_item, param)) try: args["name_id_policy"] = kwargs["name_id_policy"] del kwargs["name_id_policy"] except KeyError: if allow_create is None: allow_create = self.config.getattr( "name_id_format_allow_create", "sp") if allow_create is None: allow_create = "false" else: if allow_create is True: allow_create = "true" else: allow_create = "false" if nameid_format == "": name_id_policy = None else: if nameid_format is None: nameid_format = self.config.getattr("name_id_format", "sp") if nameid_format is None: nameid_format = NAMEID_FORMAT_TRANSIENT elif isinstance(nameid_format, list): # NameIDPolicy can only have one format specified nameid_format = nameid_format[0] name_id_policy = samlp.NameIDPolicy(allow_create=allow_create, format=nameid_format) if name_id_policy and vorg: try: name_id_policy.sp_name_qualifier = vorg name_id_policy.format = saml.NAMEID_FORMAT_PERSISTENT except KeyError: pass args["name_id_policy"] = name_id_policy try: nsprefix = kwargs["nsprefix"] except KeyError: nsprefix = None if kwargs: _args, extensions = self._filter_args(AuthnRequest(), extensions, **kwargs) args.update(_args) try: del args["id"] except KeyError: pass if sign is None: sign = self.authn_requests_signed if (sign and self.sec.cert_handler.generate_cert()) or \ client_crt is not None: with self.lock: self.sec.cert_handler.update_cert(True, client_crt) if client_crt is not None: sign_prepare = True return self._message(AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args) return self._message(AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args)
from saml2.authn_context import AL1 from saml2.authn_context import AL2 from saml2.authn_context import AL3 from saml2.authn_context import AL4 from saml2.authn_context import AuthnBroker from saml2.authn_context import authn_context_decl_from_extension_elements from saml2.authn_context import authn_context_factory length = pword.Length(min="4") restricted_password = pword.RestrictedPassword(length=length) authenticator = pword.Authenticator(restricted_password=restricted_password) authn_method = pword.AuthnMethod(authenticator=authenticator) ACD = pword.AuthenticationContextDeclaration(authn_method=authn_method) AUTHNCTXT = AuthnContext(authn_context_decl=ACD) REQAUTHNCTXT = RequestedAuthnContext(authn_context_decl_ref=ACD.c_namespace) def test_passwd(): inst = ACD inst2 = pword.authentication_context_declaration_from_string(ex1) assert inst == inst2 def test_factory(): inst_pw = pword.authentication_context_declaration_from_string(ex1) inst = authn_context_factory(ex1) assert inst_pw == inst
def create_authn_request(self, destination, vorg="", scoping=None, binding=saml2.BINDING_HTTP_POST, nameid_format=None, service_url_binding=None, message_id=0, consent=None, extensions=None, sign=None, allow_create=None, sign_prepare=False, sign_alg=None, digest_alg=None, requested_attributes=None, **kwargs): """ Creates an authentication request. :param destination: Where the request should be sent. :param vorg: The virtual organization the service belongs to. :param scoping: The scope of the request :param binding: The protocol to use for the Response !! :param nameid_format: Format of the NameIDPolicy :param service_url_binding: Where the reply should be sent dependent on reply binding. :param message_id: The identifier for this request :param consent: Whether the principal have given her consent :param extensions: Possible extensions :param sign: Whether the request should be signed or not. :param sign_prepare: Whether the signature should be prepared or not. :param allow_create: If the identity provider is allowed, in the course of fulfilling the request, to create a new identifier to represent the principal. :param requested_attributes: A list of dicts which define attributes to be used as eIDAS Requested Attributes for this request. If not defined the configuration option requested_attributes will be used, if defined. The format is the same as the requested_attributes configuration option. :param kwargs: Extra key word arguments :return: either a tuple of request ID and <samlp:AuthnRequest> instance or a tuple of request ID and str when sign is set to True """ args = {} # AssertionConsumerServiceURL # AssertionConsumerServiceIndex hide_assertion_consumer_service = self.config.getattr( 'hide_assertion_consumer_service', 'sp') assertion_consumer_service_url = ( kwargs.pop("assertion_consumer_service_urls", [None])[0] or kwargs.pop("assertion_consumer_service_url", None)) assertion_consumer_service_index = kwargs.pop( "assertion_consumer_service_index", None) service_url = (self.service_urls(service_url_binding or binding) or [None])[0] if hide_assertion_consumer_service: args["assertion_consumer_service_url"] = None binding = None elif assertion_consumer_service_url: args[ "assertion_consumer_service_url"] = assertion_consumer_service_url elif assertion_consumer_service_index: args[ "assertion_consumer_service_index"] = assertion_consumer_service_index elif service_url: args["assertion_consumer_service_url"] = service_url # ProviderName provider_name = kwargs.get("provider_name") if not provider_name and binding != BINDING_PAOS: provider_name = self._my_name() args["provider_name"] = provider_name # Allow argument values either as class instances or as dictionaries # all of these have cardinality 0..1 _msg = AuthnRequest() for param in [ "scoping", "requested_authn_context", "conditions", "subject" ]: _item = kwargs.pop(param, None) if not _item: continue if isinstance(_item, _msg.child_class(param)): args[param] = _item elif isinstance(_item, dict): args[param] = RequestedAuthnContext(**_item) else: raise ValueError( "Wrong type for param {name}".format(name=param)) # NameIDPolicy nameid_policy_format_config = self.config.getattr( "name_id_policy_format", "sp") nameid_policy_format = (nameid_format or nameid_policy_format_config or None) allow_create_config = self.config.getattr( "name_id_format_allow_create", "sp") allow_create = ( None # SAML 2.0 errata says AllowCreate MUST NOT be used for transient ids if nameid_policy_format == NAMEID_FORMAT_TRANSIENT else allow_create if allow_create else str( bool(allow_create_config)).lower()) name_id_policy = ( kwargs.pop("name_id_policy", None) if "name_id_policy" in kwargs else None if not nameid_policy_format else samlp.NameIDPolicy( allow_create=allow_create, format=nameid_policy_format)) if name_id_policy and vorg: name_id_policy.sp_name_qualifier = vorg name_id_policy.format = nameid_policy_format or NAMEID_FORMAT_PERSISTENT args["name_id_policy"] = name_id_policy # eIDAS SPType conf_sp_type = self.config.getattr('sp_type', 'sp') conf_sp_type_in_md = self.config.getattr('sp_type_in_metadata', 'sp') if conf_sp_type and conf_sp_type_in_md is False: if not extensions: extensions = Extensions() item = sp_type.SPType(text=conf_sp_type) extensions.add_extension_element(item) # eIDAS RequestedAttributes requested_attrs = (requested_attributes or self.config.getattr('requested_attributes', 'sp') or []) if requested_attrs: req_attrs_node = create_requested_attribute_node( requested_attrs, self.config.attribute_converters) if not extensions: extensions = Extensions() extensions.add_extension_element(req_attrs_node) # ForceAuthn force_authn = str( kwargs.pop("force_authn", None) or self.config.getattr("force_authn", "sp")).lower() in [ "true", "1" ] if force_authn: kwargs["force_authn"] = "true" if kwargs: _args, extensions = self._filter_args(AuthnRequest(), extensions, **kwargs) args.update(_args) args.pop("id", None) client_crt = kwargs.get("client_crt") nsprefix = kwargs.get("nsprefix") sign = self.authn_requests_signed if sign is None else sign if (sign and self.sec.cert_handler.generate_cert() ) or client_crt is not None: with self.lock: self.sec.cert_handler.update_cert(True, client_crt) if client_crt is not None: sign_prepare = True msg = self._message( AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args, ) else: msg = self._message( AuthnRequest, destination, message_id, consent, extensions, sign, sign_prepare, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, sign_alg=sign_alg, digest_alg=digest_alg, **args, ) return msg