Exemple #1
0
    def outgoing(self, response, org_response, instance):
        """
        An authentication response has been received and now an authentication
        response from this server should be constructed.

        :param response: The Authentication response
        :param instance: SP instance that received the authentication response
        :return: response
        """

        _idp = self.create_SamlIDP(instance.environ, instance.start_response, self.outgoing)

        _state = instance.sp.state[response.in_response_to]
        orig_authn_req, relay_state, req_args = instance.sp.state[_state]

        # The Subject NameID
        try:
            subject = response.get_subject()
        except:
            pass

        resp_args = _idp.idp.response_args(orig_authn_req)


        try:
            _authn_info = response.authn_info()[0]
            AUTHN_BROKER = AuthnBroker()
            AUTHN_BROKER.add(authn_context_class_ref(_authn_info[0]), username_password_authn_dummy, 0, self.issuer)
            _authn = AUTHN_BROKER.get_authn_by_accr(_authn_info[0])
            #_authn = {"class_ref": _authn_info[0], "authn_auth": self.issuer}
        except:
            AUTHN_BROKER = AuthnBroker()
            AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), username_password_authn_dummy, 0, self.issuer)
            _authn = AUTHN_BROKER.get_authn_by_accr(UNSPECIFIED)

        identity = response.ava

        if identity is None and response.response.encrypted_assertion is not None:
            #Add dummy value
            identity = {"uid": "dummyuser"}

        # Will signed the response by default
        resp = _idp.construct_authn_response(identity, userid="dummyuser",
                                             authn=_authn, name_id=None, resp_args=resp_args,
                                             relay_state=relay_state, sign_response=True,
                                             org_resp=response, org_xml_response=org_response)

        return resp
Exemple #2
0
 def _prepare_server(self):
     """
     Setup server
     """
     self.idp_config = Saml2Config()
     self.BASE = '{}://{}:{}'.format(self._mode, self._config.get('host'),
                                     self._config.get('port'))
     if 'entityid' not in self._config:
         # as fallback for entityid use host:port string
         self._config['entityid'] = self.BASE
     self.idp_config.load(cnf=self._idp_config())
     setattr(
         self.idp_config, 'attribute_converters',
         ac_factory('testenv/attributemaps',
                    **{'override_types': self._all_attributes}))
     self.server = SpidServer(config=self.idp_config)
     self._setup_app_routes()
     # setup custom methods in order to
     # prepare the login form and verify the challenge (optional)
     # for every spid level (1-2-3)
     self.authn_broker = AuthnBroker()
     for index, _level in enumerate(self._spid_levels):
         self.authn_broker.add(
             authn_context_class_ref(_level),
             getattr(self, '_verify_spid_{}'.format(index + 1)))
Exemple #3
0
    def handle_authn_request(self, saml_request, relay_state, binding, userid):

        self.authn_req = self.idp.parse_authn_request(saml_request, binding)
        _encrypt_cert = encrypt_cert_from_item(self.authn_req.message)

        self.binding_out, self.destination = self.idp.pick_binding(
                                                                    "assertion_consumer_service",
                                                                    bindings=None,
                                                                    entity_id=self.authn_req.message.issuer.text,
                                                                    request=self.authn_req.message)
        resp_args = self.idp.response_args(self.authn_req.message)
        AUTHN_BROKER = AuthnBroker()
        AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                         username_password_authn_dummy,
                         10,
                         "http://test.idp.se")
        AUTHN_BROKER.get_authn_by_accr(PASSWORD)
        resp_args["authn"] = AUTHN_BROKER.get_authn_by_accr(PASSWORD)
        _resp = self.idp.create_authn_response(TestIdP.USERS[userid],
                                               userid=userid,
                                               encrypt_cert=_encrypt_cert,
                                               encrypt_assertion_self_contained=True,
                                               encrypted_advice_attributes=True,
                                               **resp_args)
        kwargs = {}
        http_args = self.idp.apply_binding(BINDING_HTTP_POST,
                                           "%s" % _resp,
                                           self.destination,
                                           relay_state,
                                           response=True,
                                           **kwargs)
        action, body = get_post_action_body(http_args["data"][3])
        return action, urllib.urlencode(body)
Exemple #4
0
    def handle_auth_req(self, saml_request, relay_state, binding, userid):
        auth_req = self.parse_authn_request(saml_request, binding)
        binding_out, destination = self.pick_binding(
            'assertion_consumer_service',
            entity_id=auth_req.message.issuer.text,
            request=auth_req.message)

        resp_args = self.response_args(auth_req.message)
        authn_broker = AuthnBroker()
        authn_broker.add(authn_context_class_ref(PASSWORD), lambda: None, 10,
                         'unittest_idp.xml')
        authn_broker.get_authn_by_accr(PASSWORD)
        resp_args['authn'] = authn_broker.get_authn_by_accr(PASSWORD)

        _resp = self.create_authn_response(self.user_db[userid],
                                           userid=userid,
                                           **resp_args)

        http_args = self.apply_binding(BINDING_HTTP_POST,
                                       '%s' % _resp,
                                       destination,
                                       relay_state,
                                       response=True)
        url = http_args['url']
        saml_response = base64.b64encode(str(_resp).encode("utf-8"))
        resp = {'SAMLResponse': saml_response, 'RelayState': relay_state}
        return url, resp
    def get_authn_response(self, idp_config, identity):
        with closing(SamlServer(idp_config)) as server:
            name_id = server.ident.transient_nameid(
                "urn:mace:example.com:saml:roland:idp", "id12")

            authn_context_ref = authn_context_class_ref(
                AUTHN_PASSWORD_PROTECTED)
            authn_context = AuthnContext(
                authn_context_class_ref=authn_context_ref)

            locality = saml.SubjectLocality()
            locality.address = "172.31.25.30"

            authn_statement = AuthnStatement(
                subject_locality=locality,
                authn_instant=datetime.now().isoformat(),
                authn_context=authn_context,
                session_index="id12")

            return server.create_authn_response(
                identity,
                "id12",  # in_response_to
                self.
                sp_acs_location,  # consumer_url. config.sp.endpoints.assertion_consumer_service:["acs_endpoint"]
                self.sp_acs_location,  # sp_entity_id
                name_id=name_id,
                sign_assertion=True,
                sign_response=True,
                authn_statement=authn_statement)
Exemple #6
0
    def get(self, request, *args, **kwargs):
        passed_data = request.POST if request.method == 'POST' else request.GET

        # get sp information from the parameters
        try:
            sp_entity_id = passed_data['sp']
        except KeyError as e:
            return HttpResponseBadRequest(e)

        try:
            sp_config = settings.SAML_IDP_SPCONFIG[sp_entity_id]
        except Exception:
            raise ImproperlyConfigured("No config for SP %s defined in SAML_IDP_SPCONFIG" % sp_entity_id)

        binding_out, destination = self.IDP.pick_binding(
            service="assertion_consumer_service",
            entity_id=sp_entity_id)

        processor = self.get_processor(sp_config)

        # Check if user has access to the service of this SP
        if not processor.has_access(request.user):
            raise PermissionDenied("You do not have access to this resource")

        identity = self.get_identity(processor, request.user, sp_config)

        req_authn_context = PASSWORD
        AUTHN_BROKER = AuthnBroker()
        AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

        # Construct SamlResponse messages
        try:
            name_id_formats = self.IDP.config.getattr("name_id_format", "idp") or [NAMEID_FORMAT_UNSPECIFIED]
            name_id = NameID(format=name_id_formats[0], text=request.user.username)
            authn = AUTHN_BROKER.get_authn_by_accr(req_authn_context)
            sign_response = self.IDP.config.getattr("sign_response", "idp") or False
            sign_assertion = self.IDP.config.getattr("sign_assertion", "idp") or False
            authn_resp = self.IDP.create_authn_response(
                identity=identity,
                in_response_to="IdP_Initiated_Login",
                destination=destination,
                sp_entity_id=sp_entity_id,
                userid=request.user.username,
                name_id=name_id,
                authn=authn,
                sign_response=sign_response,
                sign_assertion=sign_assertion,
                **passed_data)
        except Exception as excp:
            return HttpResponseServerError(excp)

        # Return as html with self-submitting form.
        http_args = self.IDP.apply_binding(
            binding=binding_out,
            msg_str="%s" % authn_resp,
            destination=destination,
            relay_state=passed_data['RelayState'],
            response=True)
        return HttpResponse(http_args['data'])
Exemple #7
0
 def get_authn(self, req_info=None):
     if req_info:
         req_authn_context = req_info.message.requested_authn_context
     else:
          req_authn_context = PASSWORD
     broker = AuthnBroker()
     broker.add(authn_context_class_ref(req_authn_context), "")
     return broker.get_authn_by_accr(req_authn_context)
Exemple #8
0
def main():
    global IDP
    global AUTHN_BROKER
    global LOOKUP
    global args
    sys.path.insert(0, os.getcwd())
    from wsgiref.simple_server import make_server

    parser = argparse.ArgumentParser()
    parser.add_argument('-p', dest='path', help='Path to configuration file.')
    parser.add_argument('-v', dest='valid',
                        help="How long, in days, the metadata is valid from the time of creation")
    parser.add_argument('-c', dest='cert', help='certificate')
    parser.add_argument('-i', dest='id',
                        help="The ID of the entities descriptor")
    parser.add_argument('-k', dest='keyfile',
                        help="A file with a key to sign the metadata with")
    parser.add_argument('-n', dest='name')
    parser.add_argument('-s', dest='sign', action='store_true',
                        help="sign the metadata")
    parser.add_argument('-m', dest='mako_root', default="./")
    parser.add_argument(dest="config")
    args = parser.parse_args()

    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                     username_password_authn, 10,
                     "http://%s" % socket.gethostname())
    AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED),
                     "", 0, "http://%s" % socket.gethostname())
    CONFIG = importlib.import_module(args.config)
    IDP = server.Server(args.config, cache=Cache())
    IDP.ticket = {}

    _rot = args.mako_root
    LOOKUP = TemplateLookup(directories=[_rot + 'templates', _rot + 'htdocs'],
                            module_directory=_rot + 'modules',
                            input_encoding='utf-8', output_encoding='utf-8')

    HOST = CONFIG.HOST
    PORT = CONFIG.PORT

    SRV = make_server(HOST, PORT, application)
    print "IdP listening on %s:%s" % (HOST, PORT)
    SRV.serve_forever()
Exemple #9
0
 def setup_authn_broker(self, base_url, sphandler, authorization):
     ab = AuthnBroker()
     sphandler.sp_authentication = SpAuthentication(self, sphandler)
     cas_auth = CasAuth(self, self.cas_server, self.service_url)
     password_auth = PasswordYubikeyAuth(self,
                                         self.passwd,
                                         password=True,
                                         yubikey=False)
     yubikey_auth = PasswordYubikeyAuth(self,
                                        self.passwd,
                                        password=False,
                                        yubikey=True)
     password_yubikey_auth = PasswordYubikeyAuth(self,
                                                 self.passwd,
                                                 password=True,
                                                 yubikey=True)
     for authkey, value in authorization.items():
         level = str(value[IdPHandler.AUTHORIZATION_WEIGHT])
         url = value[IdPHandler.AUTHORIZATION_URL]
         acr = value[IdPHandler.AUTHORIZATION_ACR]
         user_info = value[IdPHandler.AUTHORIZATION_USER_INFO]
         if authkey == IdPHandler.AUTHORIZATION_SAML:
             sphandler.sp_authentication.user_info(user_info)
             ab.add(acr, sphandler.sp_authentication, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_CAS:
             cas_auth.user_info(user_info)
             ab.add(acr, cas_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_PASSWORD_YUBIKEY:
             password_yubikey_auth.user_info(user_info)
             ab.add(acr, password_yubikey_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_PASSWORD:
             password_auth.user_info(user_info)
             ab.add(acr, password_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_YUBIKEY:
             yubikey_auth.user_info(user_info)
             ab.add(acr, yubikey_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_MULTIPLEAUTHN:
             authn_list = []
             for m_items in value[IdPHandler.AUTHENTICATION_AUTHNLIST]:
                 m_authkey = m_items[IdPHandler.AUTHORIZATION_ACR]
                 if m_authkey == IdPHandler.AUTHORIZATION_SAML:
                     authn_list.append(sphandler.sp_authentication)
                 elif m_authkey == IdPHandler.AUTHORIZATION_CAS:
                     authn_list.append(cas_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_PASSWORD_YUBIKEY:
                     authn_list.append(password_yubikey_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_PASSWORD:
                     authn_list.append(password_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_YUBIKEY:
                     authn_list.append(yubikey_auth)
             ab.add(acr, MultipleAuthentication(self, authn_list,
                                                user_info), level, url)
         else:
             ab.add(authn_context_class_ref(UNSPECIFIED),
                    UnspecifiedAuth(self), level, url)
     return ab
def test_authn_1():
    ac = authn_context_class_ref(PASSWORDPROTECTEDTRANSPORT)
    rac = requested_authn_context(PASSWORDPROTECTEDTRANSPORT)
    authn = AuthnBroker()
    target = "https://example.org/login"
    authn.add(ac, target, 1, "http://www.example.com")

    result = authn.pick(rac)
    assert len(result) == 1
    method, reference = result[0]
    assert target == method
Exemple #11
0
def test_authn_1():
    ac = authn_context_class_ref(PASSWORDPROTECTEDTRANSPORT)
    rac = requested_authn_context(PASSWORDPROTECTEDTRANSPORT)
    authn = AuthnBroker()
    target = "https://example.org/login"
    authn.add(ac, target, 1, "http://www.example.com")

    result = authn.pick(rac)
    assert len(result) == 1
    method, reference = result[0]
    assert target == method
def test_authn_3():
    authn = AuthnBroker()
    level = 0
    for ref in [AL1, AL2, AL3, AL4]:
        level += 4
        ac = authn_context_class_ref(ref)

        authn.add(ac, REF2METHOD[ref], level,
                  "https://www.example.com/%s" % "al%d" % level)

    rac = requested_authn_context(AL1, "minimum")

    info = authn.pick(rac)
    assert len(info) == 4
    method, ref = info[0]
    assert REF2METHOD[AL1] == method

    rac = requested_authn_context(AL2, "minimum")

    info = authn.pick(rac)
    assert len(info) == 3
    method, ref = info[0]
    assert REF2METHOD[AL2] == method

    rac = requested_authn_context(AL3, "minimum")

    info = authn.pick(rac)
    assert len(info) == 2
    method, ref = info[0]
    assert REF2METHOD[AL3] == method

    rac = requested_authn_context(AL4, "minimum")

    info = authn.pick(rac)
    assert len(info) == 1
    method, ref = info[0]
    assert REF2METHOD[AL4] == method

    rac = requested_authn_context(AL1, "exact")

    info = authn.pick(rac)
    assert len(info) == 1
    method, ref = info[0]
    assert REF2METHOD[AL1] == method

    rac = requested_authn_context(AL1, "better")

    info = authn.pick(rac)
    assert len(info) == 3
def test_authn_3():
    authn = AuthnBroker()
    level = 0
    for ref in [AL1, AL2, AL3, AL4]:
        level += 4
        ac = authn_context_class_ref(ref)

        authn.add(ac, REF2METHOD[ref], level,
                  "https://www.example.com/%s" % "al%d" % level)

    rac = requested_authn_context(AL1, "minimum")

    info = authn.pick(rac)
    assert len(info) == 4
    method, ref = info[0]
    assert REF2METHOD[AL1] == method

    rac = requested_authn_context(AL2, "minimum")

    info = authn.pick(rac)
    assert len(info) == 3
    method, ref = info[0]
    assert REF2METHOD[AL2] == method

    rac = requested_authn_context(AL3, "minimum")

    info = authn.pick(rac)
    assert len(info) == 2
    method, ref = info[0]
    assert REF2METHOD[AL3] == method

    rac = requested_authn_context(AL4, "minimum")

    info = authn.pick(rac)
    assert len(info) == 1
    method, ref = info[0]
    assert REF2METHOD[AL4] == method

    rac = requested_authn_context(AL1, "exact")

    info = authn.pick(rac)
    assert len(info) == 1
    method, ref = info[0]
    assert REF2METHOD[AL1] == method

    rac = requested_authn_context(AL1, "better")

    info = authn.pick(rac)
    assert len(info) == 3
Exemple #14
0
 def setup_authn_broker(self, base_url, sphandler, authorization):
     ab = AuthnBroker()
     sphandler.sp_authentication = SpAuthentication(self, sphandler)
     cas_auth = CasAuth(self, self.cas_server, self.service_url)
     password_auth = PasswordYubikeyAuth(self, self.passwd, password=True,
                                         yubikey=False)
     yubikey_auth = PasswordYubikeyAuth(self, self.passwd, password=False,
                                        yubikey=True)
     password_yubikey_auth = PasswordYubikeyAuth(self, self.passwd, password=True,
                                                 yubikey=True)
     for authkey, value in authorization.items():
         level = str(value[IdPHandler.AUTHORIZATION_WEIGHT])
         url = value[IdPHandler.AUTHORIZATION_URL]
         acr = value[IdPHandler.AUTHORIZATION_ACR]
         user_info = value[IdPHandler.AUTHORIZATION_USER_INFO]
         if authkey == IdPHandler.AUTHORIZATION_SAML:
             sphandler.sp_authentication.user_info(user_info)
             ab.add(acr, sphandler.sp_authentication, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_CAS:
             cas_auth.user_info(user_info)
             ab.add(acr, cas_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_PASSWORD_YUBIKEY:
             password_yubikey_auth.user_info(user_info)
             ab.add(acr, password_yubikey_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_PASSWORD:
             password_auth.user_info(user_info)
             ab.add(acr, password_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_YUBIKEY:
             yubikey_auth.user_info(user_info)
             ab.add(acr, yubikey_auth, level, url)
         elif authkey == IdPHandler.AUTHORIZATION_MULTIPLEAUTHN:
             authn_list = []
             for m_items in value[IdPHandler.AUTHENTICATION_AUTHNLIST]:
                 m_authkey = m_items[IdPHandler.AUTHORIZATION_ACR]
                 if m_authkey == IdPHandler.AUTHORIZATION_SAML:
                     authn_list.append(sphandler.sp_authentication)
                 elif m_authkey == IdPHandler.AUTHORIZATION_CAS:
                     authn_list.append(cas_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_PASSWORD_YUBIKEY:
                     authn_list.append(password_yubikey_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_PASSWORD:
                     authn_list.append(password_auth)
                 elif m_authkey == IdPHandler.AUTHORIZATION_YUBIKEY:
                     authn_list.append(yubikey_auth)
             ab.add(acr, MultipleAuthentication(self, authn_list, user_info), level, url)
         else:
             ab.add(authn_context_class_ref(UNSPECIFIED), UnspecifiedAuth(self), level, url)
     return ab
Exemple #15
0
    def handle_auth_req(self, saml_request, relay_state, binding, userid,
                        response_binding=BINDING_HTTP_POST):
        """
        Handles a SAML request, validates and creates a SAML response.
        :type saml_request: str
        :type relay_state: str
        :type binding: str
        :type userid: str
        :rtype:

        :param saml_request:
        :param relay_state: RelayState is a parameter used by some SAML protocol implementations to
        identify the specific resource at the resource provider in an IDP initiated single sign on
        scenario.
        :param binding:
        :param userid: The user identification.
        :return: A tuple with
        """
        auth_req = self.parse_authn_request(saml_request, binding)
        binding_out, destination = self.pick_binding(
            'assertion_consumer_service',
            bindings=[response_binding],
            entity_id=auth_req.message.issuer.text, request=auth_req.message)

        resp_args = self.response_args(auth_req.message)
        authn_broker = AuthnBroker()
        authn_broker.add(authn_context_class_ref(PASSWORD), lambda: None, 10,
                         'unittest_idp.xml')
        authn_broker.get_authn_by_accr(PASSWORD)
        resp_args['authn'] = authn_broker.get_authn_by_accr(PASSWORD)

        _resp = self.create_authn_response(self.user_db[userid],
                                           userid=userid,
                                           **resp_args)

        if response_binding == BINDING_HTTP_POST:
            saml_response = base64.b64encode(str(_resp).encode("utf-8"))
            resp = {"SAMLResponse": saml_response, "RelayState": relay_state}
        elif response_binding == BINDING_HTTP_REDIRECT:
            http_args = self.apply_binding(response_binding, '%s' % _resp,
                                           destination, relay_state, response=True)
            resp = dict(parse_qsl(urlparse(dict(http_args["headers"])["Location"]).query))

        return destination, resp
Exemple #16
0
    def __create_authn_response(self,
                                saml_request,
                                relay_state,
                                binding,
                                userid,
                                response_binding=BINDING_HTTP_POST):
        """
        Handles a SAML request, validates and creates a SAML response but
        does not apply the binding to encode it.
        :type saml_request: str
        :type relay_state: str
        :type binding: str
        :type userid: str
        :rtype: tuple [string, saml2.samlp.Response]

        :param saml_request:
        :param relay_state: RelayState is a parameter used by some SAML
        protocol implementations to identify the specific resource at the
        resource provider in an IDP initiated single sign on scenario.
        :param binding:
        :param userid: The user identification.
        :return: A tuple containing the destination and instance of
        saml2.samlp.Response
        """
        auth_req = self.parse_authn_request(saml_request, binding)
        binding_out, destination = self.pick_binding(
            'assertion_consumer_service',
            bindings=[response_binding],
            entity_id=auth_req.message.issuer.text,
            request=auth_req.message)

        resp_args = self.response_args(auth_req.message)
        authn_broker = AuthnBroker()
        authn_broker.add(authn_context_class_ref(PASSWORD), lambda: None, 10,
                         'unittest_idp.xml')
        authn_broker.get_authn_by_accr(PASSWORD)
        resp_args['authn'] = authn_broker.get_authn_by_accr(PASSWORD)

        resp = self.create_authn_response(self.user_db[userid],
                                          userid=userid,
                                          **resp_args)

        return destination, resp
    def __init__(self, config):
        baseurl = config['protocol'] + "://" + config['url']
        log.info("Application baseurl: " + baseurl)

        # Update URLs with base
        for pro in SSIXASAMLProvider_SERVICE_EP:
            for serv in SSIXASAMLProvider_SERVICE_EP[pro]['endpoints']:
                if 'service' in serv:
                    for ep in SSIXASAMLProvider_SERVICE_EP[pro]['endpoints'][
                            serv]:
                        SSIXASAMLProvider_SERVICE_EP[pro]['endpoints'][serv][
                            0] = baseurl + ep[0]

        # Update SAML config
        config['saml_config'].update({'service': SSIXASAMLProvider_SERVICE_EP})
        cfg = SAMLIdpConfig(config['saml_config'])

        # Create SAML IdP server - Init super class after config preparation
        super(SSIXASAMLProvider, self).__init__(config=cfg, cache=Cache())

        # Add authn broker
        self.authn_broker = AuthnBroker()
        self.userinfodb = SAMLUserInfoDB()
        i = BlockchainAuthMethod(baseurl + "/saml", config['proxymode'],
                                 config, self.userinfodb, config['trustmodel'])
        self.authn_broker.add(authn_context_class_ref(UNSPECIFIED), i, 3,
                              {i.acr})

        # Add attribute converters
        self.config.attribute_converters = ac_factory()

        # Add metadata
        self.metadata = self.create_metadata(config['saml_config']['metadata'])

        # Response bindings that are offered
        self.response_bindings = [BINDING_HTTP_POST, BINDING_HTTP_REDIRECT]

        # Default claims
        self.defaul_claims = copy.deepcopy(
            config['saml_config']['default_claims'])
Exemple #18
0
    def __create_authn_response(self, saml_request, relay_state, binding,
                                userid, response_binding=BINDING_HTTP_POST):
        """
        Handles a SAML request, validates and creates a SAML response but
        does not apply the binding to encode it.
        :type saml_request: str
        :type relay_state: str
        :type binding: str
        :type userid: str
        :rtype: tuple [string, saml2.samlp.Response]

        :param saml_request:
        :param relay_state: RelayState is a parameter used by some SAML
        protocol implementations to identify the specific resource at the
        resource provider in an IDP initiated single sign on scenario.
        :param binding:
        :param userid: The user identification.
        :return: A tuple containing the destination and instance of
        saml2.samlp.Response
        """
        auth_req = self.parse_authn_request(saml_request, binding)
        binding_out, destination = self.pick_binding(
            'assertion_consumer_service',
            bindings=[response_binding],
            entity_id=auth_req.message.issuer.text, request=auth_req.message)

        resp_args = self.response_args(auth_req.message)
        authn_broker = AuthnBroker()
        authn_broker.add(authn_context_class_ref(PASSWORD), lambda: None, 10,
                         'unittest_idp.xml')
        authn_broker.get_authn_by_accr(PASSWORD)
        resp_args['authn'] = authn_broker.get_authn_by_accr(PASSWORD)

        resp = self.create_authn_response(self.user_db[userid],
                                          userid=userid,
                                          **resp_args)

        return destination, resp
Exemple #19
0
    def handle_auth_req(self, saml_request, relay_state, binding, userid):
        auth_req = self.parse_authn_request(saml_request, binding)
        binding_out, destination = self.pick_binding(
            'assertion_consumer_service',
            entity_id=auth_req.message.issuer.text, request=auth_req.message)

        resp_args = self.response_args(auth_req.message)
        authn_broker = AuthnBroker()
        authn_broker.add(authn_context_class_ref(PASSWORD), lambda: None, 10,
                         'unittest_idp.xml')
        authn_broker.get_authn_by_accr(PASSWORD)
        resp_args['authn'] = authn_broker.get_authn_by_accr(PASSWORD)

        _resp = self.create_authn_response(self.user_db[userid],
                                           userid=userid,
                                           **resp_args)

        http_args = self.apply_binding(BINDING_HTTP_POST, '%s' % _resp,
                                       destination, relay_state, response=True)
        url = http_args['url']
        saml_response = base64.b64encode(str(_resp).encode("utf-8"))
        resp = {'SAMLResponse': saml_response, 'RelayState': relay_state}
        return url, resp
Exemple #20
0
    def test_acs_with_authn_response_includes_subjectLocality(self):
        self._skip_if_xmlsec_binary_missing()
        self.config.use_signed_authn_request = True
        self.config.save()

        with override_settings(SAML_KEY_FILE=self.ipd_key_path,
                               SAML_CERT_FILE=self.ipd_cert_path):
            saml2config = self.config
            sp_config = config.SPConfig()
            sp_config.load(create_saml_config_for(saml2config))
            sp_metadata = create_metadata_string('',
                                                 config=sp_config,
                                                 sign=True)

        idp_config = self.get_idp_config(sp_metadata)

        identity = {
            "eduPersonAffiliation": ["staff", "member"],
            "surName": ["Jeter"],
            "givenName": ["Derek"],
            "mail": ["*****@*****.**"],
            "title": ["shortstop"]
        }

        with closing(SamlServer(idp_config)) as server:
            name_id = server.ident.transient_nameid(
                "urn:mace:example.com:saml:roland:idp", "id12")

            authn_context_ref = authn_context_class_ref(
                AUTHN_PASSWORD_PROTECTED)
            authn_context = AuthnContext(
                authn_context_class_ref=authn_context_ref)

            locality = saml.SubjectLocality()
            locality.address = "172.31.25.30"

            authn_statement = AuthnStatement(
                subject_locality=locality,
                authn_instant=datetime.now().isoformat(),
                authn_context=authn_context,
                session_index="id12")

            authn_response = server.create_authn_response(
                identity,
                "id12",  # in_response_to
                self.
                sp_acs_location,  # consumer_url. config.sp.endpoints.assertion_consumer_service:["acs_endpoint"]
                self.sp_acs_location,  # sp_entity_id
                name_id=name_id,
                sign_assertion=True,
                sign_response=True,
                authn_statement=authn_statement)

        base64_encoded_response_metadata = base64.b64encode(
            authn_response.encode('utf-8'))
        base_64_utf8_response_metadata = base64_encoded_response_metadata.decode(
            'utf-8')

        request = self.client.post(
            reverse('assertion_consumer_service',
                    kwargs={'idp_name': self.config.slug}),
            {'SAMLResponse': base_64_utf8_response_metadata})
Exemple #21
0
    def get(self, request, *args, **kwargs):
        binding = request.session.get('Binding', BINDING_HTTP_POST)

        # Parse incoming request
        try:
            req_info = self.IDP.parse_authn_request(
                request.session['SAMLRequest'], binding)
        except Exception as excp:
            return self.handle_error(request, exception=excp)
        # Signed request for HTTP-REDIRECT
        if "SigAlg" in request.session and "Signature" in request.session:
            _certs = self.IDP.metadata.certs(req_info.message.issuer.text,
                                             "any", "signing")
            verified_ok = False
            for cert in _certs:
                # TODO implement
                # if verify_redirect_signature(_info, self.IDP.sec.sec_backend, cert):
                #    verified_ok = True
                #    break
                pass
            if not verified_ok:
                return self.handle_error(
                    request,
                    extra_message="Message signature verification failure",
                    status=400)

        # Gather response arguments
        try:
            resp_args = self.IDP.response_args(req_info.message)
        except (UnknownPrincipal, UnsupportedBinding) as excp:
            return self.handle_error(request, exception=excp, status=400)

        try:
            sp_config = settings.SAML_IDP_SPCONFIG[resp_args['sp_entity_id']]
        except Exception:
            return self.handle_error(
                request,
                exception=ImproperlyConfigured(
                    "No config for SP %s defined in SAML_IDP_SPCONFIG" %
                    resp_args['sp_entity_id']),
                status=400)

        processor = self.get_processor(resp_args['sp_entity_id'], sp_config)

        # Check if user has access to the service of this SP
        if not processor.has_access(request):
            return self.handle_error(
                request,
                exception=PermissionDenied(
                    "You do not have access to this resource"),
                status=403)

        identity = self.get_identity(processor, request.user, sp_config)

        req_authn_context = req_info.message.requested_authn_context or PASSWORD
        AUTHN_BROKER = AuthnBroker()
        AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

        user_id = processor.get_user_id(request.user)

        # Construct SamlResponse message
        try:
            authn_resp = self.IDP.create_authn_response(
                identity=identity,
                userid=user_id,
                name_id=NameID(format=resp_args['name_id_policy'].format,
                               sp_name_qualifier=resp_args['sp_entity_id'],
                               text=user_id),
                authn=AUTHN_BROKER.get_authn_by_accr(req_authn_context),
                sign_response=self.IDP.config.getattr("sign_response", "idp")
                or False,
                sign_assertion=self.IDP.config.getattr("sign_assertion", "idp")
                or False,
                **resp_args)
        except Exception as excp:
            return self.handle_error(request, exception=excp, status=500)

        http_args = self.IDP.apply_binding(
            binding=resp_args['binding'],
            msg_str="%s" % authn_resp,
            destination=resp_args['destination'],
            relay_state=request.session['RelayState'],
            response=True)

        logger.debug('http args are: %s' % http_args)

        return self.render_response(request, processor, http_args)
Exemple #22
0
def login_process(request):
    """ View which processes the actual SAML request and returns a self-submitting form with the SAML response.
        The login_required decorator ensures the user authenticates first on the IdP using 'normal' ways.
    """
    # Construct server with config from settings dict
    conf = IdPConfig()
    conf.load(copy.deepcopy(settings.SAML_IDP_CONFIG))
    IDP = Server(config=conf)
    # Parse incoming request
    try:
        req_info = IDP.parse_authn_request(request.session['SAMLRequest'],
                                           BINDING_HTTP_POST)
    except Exception as excp:
        return HttpResponseBadRequest(excp)
    # TODO this is taken from example, but no idea how this works or whats it does. Check SAML2 specification?
    # Signed request for HTTP-REDIRECT
    if "SigAlg" in request.session and "Signature" in request.session:
        _certs = IDP.metadata.certs(req_info.message.issuer.text, "any",
                                    "signing")
        verified_ok = False
        for cert in _certs:
            # TODO implement
            #if verify_redirect_signature(_info, IDP.sec.sec_backend, cert):
            #    verified_ok = True
            #    break
            pass
        if not verified_ok:
            return HttpResponseBadRequest(
                "Message signature verification failure")

    binding_out, destination = IDP.pick_binding(
        service="assertion_consumer_service",
        entity_id=req_info.message.issuer.text)

    # Gather response arguments
    try:
        resp_args = IDP.response_args(req_info.message)
    except (UnknownPrincipal, UnsupportedBinding) as excp:
        return HttpResponseServerError(excp)

    try:
        sp_config = settings.SAML_IDP_SPCONFIG[resp_args['sp_entity_id']]
    except Exception:
        raise ImproperlyConfigured(
            "No config for SP %s defined in SAML_IDP_SPCONFIG" %
            resp_args['sp_entity_id'])

    # Create user-specified processor or fallback to all-access base processor
    processor_string = sp_config.get('processor', None)
    if processor_string is None:
        processor = BaseProcessor
    else:
        processor_class = import_string(processor_string)
        processor = processor_class()

    # Check if user has access to the service of this SP
    if not processor.has_access(request.user):
        raise PermissionDenied("You do not have access to this resource")

    # Create Identity dict (SP-specific)
    sp_mapping = sp_config.get('attribute_mapping', {'username': '******'})
    identity = processor.create_identity(request.user, sp_mapping)

    # TODO investigate how this works, because I don't get it. Specification?
    req_authn_context = req_info.message.requested_authn_context or PASSWORD
    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

    # Construct SamlResponse message
    try:
        authn_resp = IDP.create_authn_response(
            identity=identity,
            userid=request.user.username,
            name_id=NameID(format=resp_args['name_id_policy'].format,
                           sp_name_qualifier=destination,
                           text=request.user.username),
            authn=AUTHN_BROKER.get_authn_by_accr(req_authn_context),
            sign_response=IDP.config.getattr("sign_response", "idp") or False,
            sign_assertion=IDP.config.getattr("sign_assertion", "idp")
            or False,
            **resp_args)
    except Exception as excp:
        return HttpResponseServerError(excp)

    # Return as html with self-submitting form.
    http_args = IDP.apply_binding(binding=binding_out,
                                  msg_str="%s" % authn_resp,
                                  destination=destination,
                                  relay_state=request.session['RelayState'],
                                  response=True)

    logger.debug('http args are: %s' % http_args)

    if processor.enable_multifactor(request.user):
        # Store http_args in session for after multi factor is complete
        request.session['saml_data'] = http_args['data']
        logger.debug("Redirecting to process_multi_factor")
        return HttpResponseRedirect(reverse('saml_multi_factor'))
    else:
        logger.debug("Performing SAML redirect")
        return HttpResponse(http_args['data'])
Exemple #23
0
from saml2.authn_context import PASSWORDPROTECTEDTRANSPORT
from saml2.authn_context import UNSPECIFIED
from saml2.authn_context import authn_context_class_ref
from saml2.authn_context import requested_authn_context

import eduid_idp.error

SWAMID_AL1 = 'http://www.swamid.se/policy/assurance/al1'
SWAMID_AL2 = 'http://www.swamid.se/policy/assurance/al2'
SWAMID_AL3 = 'http://www.swamid.se/policy/assurance/al3'

EDUID_INTERNAL_1_NAME = 'eduid.se:level:1'
EDUID_INTERNAL_2_NAME = 'eduid.se:level:2'
EDUID_INTERNAL_3_NAME = 'eduid.se:level:3'

EDUID_INTERNAL_1 = authn_context_class_ref(EDUID_INTERNAL_1_NAME)
EDUID_INTERNAL_2 = authn_context_class_ref(EDUID_INTERNAL_2_NAME)
EDUID_INTERNAL_3 = authn_context_class_ref(EDUID_INTERNAL_3_NAME)
EDUID_INTERNAL_UNSPECIFIED = authn_context_class_ref(UNSPECIFIED)

# Default set of canonicalizations for authentication contexts
_context_to_internal = {
    'undefined':
    EDUID_INTERNAL_1,  # the default entry, used on unknown RequestedAuthnContext
    # Level 1
    SWAMID_AL1: EDUID_INTERNAL_1,
    PASSWORD: EDUID_INTERNAL_1,
    PASSWORDPROTECTEDTRANSPORT: EDUID_INTERNAL_1,
    UNSPECIFIED: EDUID_INTERNAL_1,
    # Level 2
    SWAMID_AL2: EDUID_INTERNAL_2,
Exemple #24
0
                        help="How long, in days, the metadata is valid from "
                             "the time of creation")
    parser.add_argument('-c', dest='cert', help='certificate')
    parser.add_argument('-i', dest='id',
                        help="The ID of the entities descriptor")
    parser.add_argument('-k', dest='keyfile',
                        help="A file with a key to sign the metadata with")
    parser.add_argument('-n', dest='name')
    parser.add_argument('-s', dest='sign', action='store_true',
                        help="sign the metadata")
    parser.add_argument('-m', dest='mako_root', default="./")
    parser.add_argument(dest="config")
    args = parser.parse_args()

    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                     username_password_authn, 10,
                     "http://%s" % socket.gethostname())
    AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED),
                     "", 0, "http://%s" % socket.gethostname())
    CONFIG = importlib.import_module(args.config)
    IDP = server.Server(args.config, cache=Cache())
    IDP.ticket = {}

    _rot = args.mako_root
    LOOKUP = TemplateLookup(directories=[_rot + 'templates', _rot + 'htdocs'],
                            module_directory=_rot + 'modules',
                            input_encoding='utf-8', output_encoding='utf-8')

    HOST = CONFIG.HOST
    PORT = CONFIG.PORT
Exemple #25
0
# allow uwsgi or gunicorn mount
# by moving some initialization out of __name__ == '__main__' section.
# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp

args = type('Config', (object, ), {})
args.config = 'idp_conf'
args.mako_root = './'
args.path = None

import socket
from idp_user import USERS
from idp_user import EXTRA
from mako.lookup import TemplateLookup

AUTHN_BROKER = AuthnBroker()
AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), username_password_authn,
                 10, "http://%s" % socket.gethostname())
AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), "", 0,
                 "http://%s" % socket.gethostname())
CONFIG = importlib.import_module(args.config)
IDP = server.Server(args.config, cache=Cache())
IDP.ticket = {}

# ----------------------------------------------------------------------------

if __name__ == '__main__':
    from wsgiref.simple_server import make_server

    parser = argparse.ArgumentParser()
    parser.add_argument('-p', dest='path', help='Path to configuration file.')
    parser.add_argument('-v',
Exemple #26
0
 def get(self, request, *args, **kwargs):  # pylint: disable=missing-function-docstring, unused-argument, too-many-locals
     resp_args = {
         'in_response_to': self.IN_RESPONSE_TO,
         'sp_entity_id': self.SP_ENTITY_ID,
         'name_id_policy': saml.NAMEID_FORMAT_PERSISTENT,
         'binding': BINDING_HTTP_POST,
         'destination': self.DESTINATION,
     }
     sp_config = {
         'processor': 'djangosaml2idp.processors.BaseProcessor',
         'attribute_mapping': {
             'username':
             '******',
             'token':
             'token',
             'aliyun_sso_roles':
             self.CUSTOM_CONFIG['role'],
             'uid':
             self.CUSTOM_CONFIG['role_session_name'],
             'aliyun_sso_session_duration':
             self.CUSTOM_CONFIG['session_duration'],
         },
     }
     processor = self.get_processor(resp_args['sp_entity_id'], sp_config)
     # Check if user has access to the service of this SP
     if not processor.has_access(request):
         return self.handle_error(
             request,
             exception=PermissionDenied(
                 "You do not have access to this resource"),
             status=403)
     cookie_user = self.cookie_user(request)
     if not cookie_user.aliyun_sso_role.is_active:
         # 用户的角色SSO被禁用
         return self.handle_error(
             request,
             exception=PermissionDenied("Your role SSO has been disabled"),
             status=403)
     identity = self.get_identity(processor, cookie_user, sp_config)
     # print('identity is', identity)
     AUTHN_BROKER = AuthnBroker()  # pylint: disable=invalid-name
     AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), "")
     user_id = processor.get_user_id(cookie_user)
     # Construct SamlResponse message
     try:
         app = SAMLAPP.valid_objects.get(
             entity_id=resp_args['sp_entity_id'])
         _spsso_descriptor = entity_descriptor_from_string(
             app.xmldata).spsso_descriptor.pop()  # pylint: disable=no-member
         authn_resp = self.IDP.create_authn_response(
             identity=identity,
             userid=user_id,
             name_id=NameID(format=resp_args['name_id_policy'],
                            sp_name_qualifier=resp_args['sp_entity_id'],
                            text=user_id),
             authn=AUTHN_BROKER.get_authn_by_accr(PASSWORD),
             sign_response=getattr(_spsso_descriptor,
                                   'want_response_signed', '') == 'true',
             sign_assertion=getattr(_spsso_descriptor,
                                    'want_assertions_signed', '') == 'true',
             **resp_args)
     except Exception as excp:  # pylint: disable=broad-except
         return self.handle_error(request, exception=excp, status=500)
     # print('authn_resp is', authn_resp)
     http_args = self.IDP.apply_binding(
         binding=resp_args['binding'],
         msg_str="%s" % authn_resp,
         destination=resp_args['destination'],
         response=True)
     return HttpResponse(http_args['data'])
Exemple #27
0
def main():
    global IDP
    global AUTHN_BROKER
    global LOOKUP
    global args
    global CONFIG
    global USERS
    global PASSWD
    global EXTRA
    sys.path.insert(0, os.getcwd())
    from wsgiref.simple_server import make_server

    parser = argparse.ArgumentParser()
    parser.add_argument('-p', dest='path', help='Path to configuration file.')
    parser.add_argument('-v', dest='valid',
                        help="How long, in days, the metadata is valid from the time of creation")
    parser.add_argument('-c', dest='cert', help='certificate')
    parser.add_argument('-i', dest='id',
                        help="The ID of the entities descriptor")
    parser.add_argument('-k', dest='keyfile',
                        help="A file with a key to sign the metadata with")
    parser.add_argument('-n', dest='name')
    parser.add_argument('-s', dest='sign', action='store_true',
                        help="sign the metadata")
    parser.add_argument('-m', dest='mako_root', default="./")
    parser.add_argument(dest="config")
    args = parser.parse_args()

    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                     username_password_authn, 10,
                     "http://%s" % socket.gethostname())
    AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED),
                     "", 0, "http://%s" % socket.gethostname())
    CONFIG = importlib.import_module(args.config)

    USERS = CONFIG.USERS
    PASSWD = CONFIG.PASSWD
    EXTRA = CONFIG.EXTRA

    IDP = server.Server(args.config, cache=Cache())
    IDP.ticket = {}

    _rot = args.mako_root
    LOOKUP = TemplateLookup(directories=[_rot + 'htdocs', _rot + 'htdocs'],
                            module_directory=_rot + 'modules',
                            input_encoding='utf-8', output_encoding='utf-8')

    HOST = CONFIG.HOST
    PORT = CONFIG.PORT

    #SRV = make_server(HOST, PORT, application)

    SRV = wsgiserver.CherryPyWSGIServer(('0.0.0.0', PORT), application)
    make_server

    if CONFIG.HTTPS:
        SRV.ssl_adapter = ssl_pyopenssl.pyOpenSSLAdapter(CONFIG.SERVER_CERT, CONFIG.SERVER_KEY,
                                                         CONFIG.CERT_CHAIN)

    print "IdP listening on %s:%s" % (HOST, PORT)
    try:
        SRV.start()
    except KeyboardInterrupt:
        SRV.stop()
    def get(self, request, *args, **kwargs):  # pylint: disable=missing-function-docstring, too-many-locals, unused-argument
        passed_data = request.POST if request.method == 'POST' else request.GET

        # get sp information from the parameters
        try:
            sp_entity_id = passed_data['sp']
        except KeyError as excp:
            return self.handle_error(request, exception=excp, status=400)

        try:
            # sp_config = SAML_IDP_SPCONFIG[sp_entity_id]
            sp_config = {
                'processor': 'djangosaml2idp.processors.BaseProcessor',
                'attribute_mapping': {
                    # DJANGO: SAML
                    'username': '******',
                    'email': 'email',
                    'name': 'first_name',
                    'is_boss': 'is_admin',
                    'token': 'token',
                }
            }
        except Exception:  # pylint: disable=broad-except
            return self.handle_error(
                request,
                exception=ImproperlyConfigured(
                    "No config for SP %s defined in SAML_IDP_SPCONFIG" %
                    sp_entity_id),
                status=400)

        binding_out, destination = self.IDP.pick_binding(
            service="assertion_consumer_service", entity_id=sp_entity_id)

        processor = self.get_processor(sp_entity_id, sp_config)

        # Check if user has access to the service of this SP
        if not processor.has_access(request):
            return self.handle_error(
                request,
                exception=PermissionDenied(
                    "You do not have access to this resource"),
                status=403)

        identity = self.get_identity(processor, request.user, sp_config)

        req_authn_context = PASSWORD
        AUTHN_BROKER = AuthnBroker()  # pylint: disable=invalid-name
        AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

        user_id = processor.get_user_id(request.user)

        # Construct SamlResponse messages
        try:
            name_id_formats = self.IDP.config.getattr(
                "name_id_format", "idp") or [NAMEID_FORMAT_UNSPECIFIED]
            name_id = NameID(format=name_id_formats[0], text=user_id)
            authn = AUTHN_BROKER.get_authn_by_accr(req_authn_context)
            sign_response = self.IDP.config.getattr("sign_response",
                                                    "idp") or False
            sign_assertion = self.IDP.config.getattr("sign_assertion",
                                                     "idp") or False
            authn_resp = self.IDP.create_authn_response(
                identity=identity,
                in_response_to=None,
                destination=destination,
                sp_entity_id=sp_entity_id,
                userid=user_id,
                name_id=name_id,
                authn=authn,
                sign_response=sign_response,
                sign_assertion=sign_assertion,
                **passed_data)
        except Exception as excp:  # pylint: disable=broad-except
            return self.handle_error(request, exception=excp, status=500)

        # Return as html with self-submitting form.
        http_args = self.IDP.apply_binding(
            binding=binding_out,
            msg_str="%s" % authn_resp,
            destination=destination,
            relay_state=passed_data['RelayState'],
            response=True)
        return HttpResponse(http_args['data'])
    def get(self, request, *args, **kwargs):  # pylint: disable=missing-function-docstring, unused-argument, too-many-locals
        binding = request.session.get('Binding', BINDING_HTTP_POST)

        # Parse incoming request
        try:
            req_info = self.IDP.parse_authn_request(
                request.session['SAMLRequest'], binding)
        except Exception as excp:  # pylint: disable=broad-except
            return self.handle_error(request, exception=excp)
        # Signed request for HTTP-REDIRECT
        if "SigAlg" in request.session and "Signature" in request.session:
            _certs = self.IDP.metadata.certs(req_info.message.issuer.text,
                                             "any", "signing")
            verified_ok = False
            for cert in _certs:  # pylint: disable=unused-variable
                # TODO implement
                # if verify_redirect_signature(_info, self.IDP.sec.sec_backend, cert):
                #    verified_ok = True
                #    break
                pass
            if not verified_ok:
                return self.handle_error(
                    request,
                    extra_message="Message signature verification failure",
                    status=400)

        # Gather response arguments
        try:
            resp_args = self.IDP.response_args(req_info.message)
        except (UnknownPrincipal, UnsupportedBinding) as excp:
            return self.handle_error(request, exception=excp, status=400)

        try:
            # sp_config = SAML_IDP_SPCONFIG[resp_args['sp_entity_id']]
            sp_config = {
                'processor': 'djangosaml2idp.processors.BaseProcessor',
                'attribute_mapping': {
                    # DJANGO: SAML
                    'email': 'email',
                    'private_email': 'private_email',
                    'username': '******',
                    'is_staff': 'is_staff',
                    'is_superuser': '******',
                    'token': 'token',
                },
            }
        except Exception:  # pylint: disable=broad-except
            return self.handle_error(
                request,
                exception=ImproperlyConfigured(
                    "No config for SP %s defined in SAML_IDP_SPCONFIG" %
                    resp_args['sp_entity_id']),
                status=400)

        processor = self.get_processor(resp_args['sp_entity_id'], sp_config)

        # Check if user has access to the service of this SP
        if not processor.has_access(request):
            return self.handle_error(
                request,
                exception=PermissionDenied(
                    "You do not have access to this resource"),
                status=403)
        cookie_user = self.cookie_user(request)
        identity = self.get_identity(processor, cookie_user, sp_config)

        req_authn_context = req_info.message.requested_authn_context or PASSWORD
        AUTHN_BROKER = AuthnBroker()  # pylint: disable=invalid-name
        AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

        user_id = processor.get_user_id(cookie_user)

        # Construct SamlResponse message
        try:
            authn_resp = self.IDP.create_authn_response(
                identity=identity,
                userid=user_id,
                name_id=NameID(format=resp_args['name_id_policy'].format,
                               sp_name_qualifier=resp_args['sp_entity_id'],
                               text=user_id),
                authn=AUTHN_BROKER.get_authn_by_accr(req_authn_context),
                sign_response=self.IDP.config.getattr("sign_response", "idp")
                or False,
                sign_assertion=self.IDP.config.getattr("sign_assertion", "idp")
                or False,
                **resp_args)
        except Exception as excp:  # pylint: disable=broad-except
            return self.handle_error(request, exception=excp, status=500)

        http_args = self.IDP.apply_binding(
            binding=resp_args['binding'],
            msg_str="%s" % authn_resp,
            destination=resp_args['destination'],
            relay_state=request.session['RelayState'],
            response=True)

        logger.debug('http args are: %s' % http_args)  # pylint: disable=logging-not-lazy

        return self.render_response(request, processor, http_args)
Exemple #30
0
    parser.add_argument('-k',
                        dest='keyfile',
                        help="A file with a key to sign the metadata with")
    parser.add_argument('-n', dest='name')
    parser.add_argument('-s',
                        dest='sign',
                        action='store_true',
                        help="sign the metadata")
    parser.add_argument('-m', dest='mako_root', default="./")
    parser.add_argument(dest="config")
    args = parser.parse_args()

    CONFIG = importlib.import_module(args.config)

    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                     username_password_authn, 10, CONFIG.BASE)
    AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), "", 0, CONFIG.BASE)

    IDP = server.Server(args.config, cache=Cache())
    IDP.ticket = {}

    _rot = args.mako_root
    LOOKUP = TemplateLookup(directories=[_rot + 'templates', _rot + 'htdocs'],
                            module_directory=_rot + 'modules',
                            input_encoding='utf-8',
                            output_encoding='utf-8')

    HOST = CONFIG.HOST
    PORT = CONFIG.PORT
Exemple #31
0
    from wsgiref.simple_server import make_server

    parser = argparse.ArgumentParser()
    parser.add_argument("-p", dest="path", help="Path to configuration file.")
    parser.add_argument("-v", dest="valid", help="How long, in days, the metadata is valid from the time of creation")
    parser.add_argument("-c", dest="cert", help="certificate")
    parser.add_argument("-i", dest="id", help="The ID of the entities descriptor")
    parser.add_argument("-k", dest="keyfile", help="A file with a key to sign the metadata with")
    parser.add_argument("-n", dest="name")
    parser.add_argument("-s", dest="sign", action="store_true", help="sign the metadata")
    parser.add_argument("-m", dest="mako_root", default="./")
    parser.add_argument(dest="config")
    args = parser.parse_args()

    AUTHN_BROKER = AuthnBroker()
    AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), username_password_authn, 10, "http://%s" % socket.gethostname())
    AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), "", 0, "http://%s" % socket.gethostname())
    CONFIG = importlib.import_module(args.config)
    IDP = server.Server(args.config, cache=Cache())
    IDP.ticket = {}

    _rot = args.mako_root
    LOOKUP = TemplateLookup(
        directories=[_rot + "templates", _rot + "htdocs"],
        module_directory=_rot + "modules",
        input_encoding="utf-8",
        output_encoding="utf-8",
    )

    HOST = CONFIG.HOST
    PORT = CONFIG.PORT
Exemple #32
0
# allow uwsgi or gunicorn mount
# by moving some initialization out of __name__ == '__main__' section.
# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp

args = type('Config', (object,), { })
args.config = 'idp_conf'
args.mako_root = './'
args.path = None

import socket
from idp_user import USERS
from idp_user import EXTRA
from mako.lookup import TemplateLookup

AUTHN_BROKER = AuthnBroker()
AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
                 username_password_authn, 10,
                 "http://%s" % socket.gethostname())
AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED),
                 "", 0, "http://%s" % socket.gethostname())

IDP = server.Server(args.config, cache=Cache())
IDP.ticket = {}

# ----------------------------------------------------------------------------

if __name__ == '__main__':
    from wsgiref.simple_server import make_server

    parser = argparse.ArgumentParser()
    parser.add_argument('-p', dest='path', help='Path to configuration file.')
Exemple #33
0
    def get(self, request, *args, **kwargs):
        # Parse incoming request
        try:
            req_info = self.IDP.parse_authn_request(request.session['SAMLRequest'], BINDING_HTTP_POST)
        except Exception as excp:
            return HttpResponseBadRequest(excp)
        # TODO this is taken from example, but no idea how this works or whats it does. Check SAML2 specification?
        # Signed request for HTTP-REDIRECT
        if "SigAlg" in request.session and "Signature" in request.session:
            _certs = self.IDP.metadata.certs(req_info.message.issuer.text, "any", "signing")
            verified_ok = False
            for cert in _certs:
                # TODO implement
                #if verify_redirect_signature(_info, self.IDP.sec.sec_backend, cert):
                #    verified_ok = True
                #    break
                pass
            if not verified_ok:
                return HttpResponseBadRequest("Message signature verification failure")

        binding_out, destination = self.IDP.pick_binding(service="assertion_consumer_service", entity_id=req_info.message.issuer.text)

        # Gather response arguments
        try:
            resp_args = self.IDP.response_args(req_info.message)
        except (UnknownPrincipal, UnsupportedBinding) as excp:
            return HttpResponseServerError(excp)

        try:
            sp_config = settings.SAML_IDP_SPCONFIG[resp_args['sp_entity_id']]
        except Exception:
            raise ImproperlyConfigured("No config for SP %s defined in SAML_IDP_SPCONFIG" % resp_args['sp_entity_id'])

        processor = self.get_processor(sp_config)

        # Check if user has access to the service of this SP
        if not processor.has_access(request.user):
            raise PermissionDenied("You do not have access to this resource")

        identity = self.get_identity(processor, request.user, sp_config)

        # TODO investigate how this works, because I don't get it. Specification?
        req_authn_context = req_info.message.requested_authn_context or PASSWORD
        AUTHN_BROKER = AuthnBroker()
        AUTHN_BROKER.add(authn_context_class_ref(req_authn_context), "")

        # Construct SamlResponse message
        try:
            authn_resp = self.IDP.create_authn_response(
                identity=identity, userid=request.user.username,
                name_id=NameID(format=resp_args['name_id_policy'].format, sp_name_qualifier=destination, text=request.user.username),
                authn=AUTHN_BROKER.get_authn_by_accr(req_authn_context),
                sign_response=self.IDP.config.getattr("sign_response", "idp") or False,
                sign_assertion=self.IDP.config.getattr("sign_assertion", "idp") or False,
                **resp_args)
        except Exception as excp:
            return HttpResponseServerError(excp)

        http_args = self.IDP.apply_binding(
            binding=binding_out,
            msg_str="%s" % authn_resp,
            destination=destination,
            relay_state=request.session['RelayState'],
            response=True)

        logger.debug('http args are: %s' % http_args)

        return self.render_response(request, processor, http_args)