Exemple #1
0
def test_multiple_fo_one_working():
    cms_org = ClientMetadataStatement(signing_keys=KEYS['org']['jwks'],
                                      contacts=['*****@*****.**'])

    #  signed by FO
    ms_org1 = FOP.pack_metadata_statement(cms_org,
                                          alg='RS256',
                                          scope=['openid'])

    #  signed by FO1
    ms_org2 = FO1P.pack_metadata_statement(cms_org,
                                           alg='RS256',
                                           scope=['openid', 'address'])

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb'])

    ms_rp = ORGOP.pack_metadata_statement(
        cms_rp,
        alg='RS256',
        metadata_statements=Message(**{
            FOP.iss: ms_org1,
            FO1P.iss: ms_org2
        }))

    # only knows about one FO
    receiver = fo_member(FOP)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    assert len(ri.result['metadata_statements']) == 1
    _key = list(ri.result['metadata_statements'].keys())[0]
    _ms = ri.result['metadata_statements'][_key]
    assert _ms['iss'] == ISSUER['fo']
Exemple #2
0
    def federated_client_registration_request(self, **kwargs):
        """
        Constructs a client registration request to be used by a client in a 
        federation.
        
        :param kwargs: A set of claims that should be part of the registration.
        :return: A :py:class:`ClientMetadataStatement` 
        """
        req = ClientMetadataStatement()

        try:
            req['redirect_uris'] = kwargs['redirect_uris']
        except KeyError:
            try:
                req["redirect_uris"] = self.redirect_uris
            except AttributeError:
                raise MissingRequiredAttribute("redirect_uris", kwargs)
        else:
            del kwargs['redirect_uris']

        req.update(kwargs)

        if self.federation:
            return self.federation_entity.update_request(
                req, federation=self.federation)
        elif self.provider_federations:
            return self.federation_entity.update_request(
                req, loes=self.provider_federations)
Exemple #3
0
def test_multiple_fo_all_working():
    cms_org = ClientMetadataStatement(signing_keys=KEYS['org']['jwks'],
                                      contacts=['*****@*****.**'])

    #  signed by FO
    ms_org1 = FOP.pack_metadata_statement(cms_org,
                                          alg='RS256',
                                          scope=['openid'])

    #  signed by FO1
    ms_org2 = FO1P.pack_metadata_statement(cms_org,
                                           alg='RS256',
                                           scope=['openid', 'address'])

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb'])

    ms_rp = ORGOP.pack_metadata_statement(
        cms_rp,
        alg='RS256',
        metadata_statements=Message(**{
            FOP.iss: ms_org1,
            FO1P.iss: ms_org2
        }))

    # knows all FO's
    receiver = fo_member(FOP, FO1P)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    assert len(ri.result['metadata_statements']) == 2
    _iss = [iss for iss, val in ri.result['metadata_statements'].items()]
    assert set(_iss) == {ISSUER['fo'], ISSUER['fo1']}
Exemple #4
0
def test_evaluate_metadata_statement_1():
    cms_org = ClientMetadataStatement(
        signing_keys=ORGOP.keyjar.export_jwks(), contacts=['*****@*****.**'])

    #  signed by FO
    ms_org = FOP.pack_metadata_statement(cms_org, alg='RS256', scope=['openid'])

    cms_inter = ClientMetadataStatement(
        signing_keys=KEYS['inter']['jwks'],
        tos_uri=['https://inter.example.com/tos.html']
    )

    #  signed by org
    ms_inter = ORGOP.pack_metadata_statement(
        cms_inter, alg='RS256',
        metadata_statements=Message(**{FOP.iss: ms_org}))

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb']
    )

    #  signed by intermediate
    ms_rp = INTEROP.pack_metadata_statement(
        cms_rp, alg='RS256',
        metadata_statements=Message(**{FOP.iss: ms_inter}))

    receiver = fo_member(FOP)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    res = receiver.evaluate_metadata_statement(ri.result)
    assert len(res) == 1
    assert res[0].iss == ISSUER['org']
    assert sorted(list(res[0].keys())) == sorted(
        ['contacts', 'tos_uri', 'redirect_uris', 'scope'])
Exemple #5
0
def test_pack_and_unpack_ms_lev2():
    cms_org = ClientMetadataStatement(signing_keys=KEYS['org']['jwks'],
                                      contacts=['*****@*****.**'])

    #  signed by FO
    ms_org = FOP.pack_metadata_statement(cms_org,
                                         alg='RS256',
                                         scope=['openid'])

    cms_inter = ClientMetadataStatement(
        signing_keys=KEYS['inter']['jwks'],
        tos_uri=['https://inter.example.com/tos.html'])

    #  signed by org
    ms_inter = ORGOP.pack_metadata_statement(
        cms_inter,
        alg='RS256',
        metadata_statements=Message(**{FOP.iss: ms_org}))

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb'])

    #  signed by intermediate
    ms_rp = INTEROP.pack_metadata_statement(
        cms_rp,
        alg='RS256',
        metadata_statements=Message(**{FOP.iss: ms_inter}))

    receiver = fo_member(FOP)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    assert ri.result
Exemple #6
0
def test_evaluate_metadata_statement_3():
    cms_org = ClientMetadataStatement(
        signing_keys=KEYS['org']['jwks'],
        contacts=['*****@*****.**']
    )

    #  signed by FO
    ms_org1 = FOP.pack_metadata_statement(cms_org, alg='RS256',
                                          claims=['email', 'email_verified',
                                                  'phone', 'phone_verified'],
                                          scope=['openid', 'email', 'phone'])

    #  signed by FO1
    ms_org2 = FO1P.pack_metadata_statement(cms_org, alg='RS256',
                                           scope=['openid', 'email', 'address'])

    cms_inter = ClientMetadataStatement(
        signing_keys=KEYS['inter']['jwks'],
        tos_uri=['https://inter.example.com/tos.html']
    )

    ms_inter = {}
    for k, v in {FOP.iss: ms_org1, FO1P.iss: ms_org2}.items():
        #  signed by org
        ms_inter[k] = ORGOP.pack_metadata_statement(
            cms_inter, alg='RS256',
            metadata_statements=Message(**{k: v}))

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb'],
        scope=['openid', 'email']
    )

    #  signed by intermediate
    ms_rp = INTEROP.pack_metadata_statement(
        cms_rp, alg='RS256', metadata_statements=Message(**ms_inter))

    # knows all FO's
    receiver = fo_member(FOP, FO1P)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    res = receiver.evaluate_metadata_statement(ri.result)
    assert len(res) == 2
    assert set([r.fo for r in res]) == {ISSUER['fo'], ISSUER['fo1']}
    for r in res:
        if r.fo == ISSUER['fo']:
            assert sorted(list(r.keys())) == sorted(
                ['claims', 'contacts', 'tos_uri', 'redirect_uris', 'scope'])
            assert r['scope'] == ['openid', 'email', 'phone']
        else:
            assert sorted(list(r.keys())) == sorted(
                ['contacts', 'tos_uri', 'redirect_uris', 'scope'])
            assert r['scope'] == ['openid', 'email', 'address']
Exemple #7
0
    def test_registration_endpoint_fed(self):
        request = ClientMetadataStatement(
            redirect_uris=['https://example.com/rp'])
        rp = Operator(keyjar=keybundle[FO['swamid']], iss=FO['swamid'])
        sms = rp.pack_metadata_statement(request, alg='RS256')
        request = rp.extend_with_ms(request, {FO['swamid']: sms})

        resp = self.op.registration_endpoint(request.to_dict())
        assert isinstance(resp, Created)
        assert resp.status == "201 Created"

        clresp = json.loads(resp.message)
        assert list(clresp['metadata_statements'].keys()) == [FO['swamid']]
Exemple #8
0
def test_evaluate_metadata_statement_4():
    """
    One 4-level (FO, Org, Inter, admin) and one 2-level (FO1, Inter, admin)
    """
    cms_org = ClientMetadataStatement(signing_keys=KEYS['org']['jwks'],
                                      contacts=['*****@*****.**'])

    #  signed by FO
    ms_org = FOP.pack_metadata_statement(
        cms_org,
        alg='RS256',
        claims=['email', 'email_verified', 'phone', 'phone_verified'],
        scope=['openid', 'email', 'phone'])

    cms_inter = ClientMetadataStatement(
        signing_keys=KEYS['inter']['jwks'],
        tos_uri=['https://inter.example.com/tos.html'])

    #  signed by org
    ms_inter0 = ORGOP.pack_metadata_statement(
        cms_inter,
        alg='RS256',
        metadata_statements=Message(**{FOP.iss: ms_org}))

    ms_inter1 = LIGOOP.pack_metadata_statement(cms_inter, alg='ES256')

    cms_rp = ClientMetadataStatement(
        signing_keys=KEYS['admin']['jwks'],
        redirect_uris=['https://rp.example.com/auth_cb'],
        scope=['openid', 'email'])

    #  signed by intermediate
    ms_rp = INTEROP.pack_metadata_statement(
        cms_rp,
        alg='RS256',
        metadata_statements=Message(**{
            FOP.iss: ms_inter0,
            LIGOOP.iss: ms_inter1
        }))

    # knows both FO's
    receiver = fo_member(FOP, LIGOOP)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)

    _re = receiver.evaluate_metadata_statement(ri.result)
    res = le_dict(_re)
    assert set(res.keys()) == {ISSUER['fo'], ISSUER['ligo']}
    assert sorted(list(res[ISSUER['fo']].keys())) == sorted(
        ['claims', 'contacts', 'redirect_uris', 'scope', 'tos_uri'])

    assert res[ISSUER['fo']]['scope'] == ['openid', 'email', 'phone']
Exemple #9
0
    def registration_endpoint(self, request, authn=None, **kwargs):
        """

        :param request:
        :param authn:
        :param kwargs:
        :return:
        """
        logger.debug("@registration_endpoint: <<{}>>".format(sanitize(request)))

        if isinstance(request, dict):
            request = ClientMetadataStatement(**request)
        else:
            try:
                request = ClientMetadataStatement().deserialize(request, "json")
            except ValueError:
                request = ClientMetadataStatement().deserialize(request)

        try:
            request.verify()
        except Exception as err:
            return error('Invalid request')

        logger.info(
            "registration_request:{}".format(sanitize(request.to_dict())))

        ms_list = self.federation_entity.get_metadata_statement(request,
                                                                'registration')

        if ms_list:
            ms = self.federation_entity.pick_by_priority(ms_list)
            self.federation = ms.fo
        else:  # Nothing I can use
            return error(error='invalid_request',
                         descr='No signed metadata statement I could use')

        request = RegistrationRequest(**ms.le)
        result = self.client_registration_setup(request)

        if isinstance(result, Response):
            return result

        # TODO This is where the OP should sign the response
        if ms.fo:
            _fo = ms.fo
            sms = self.signer.create_signed_metadata_statement(
                result, 'response', [_fo], single=True)
            self.federation_entity.extend_with_ms(result, {_fo: sms})

        return Created(result.to_json(), content="application/json",
                       headers=[("Cache-Control", "no-store")])
Exemple #10
0
def test_create_client_metadata_statement():
    ms = MetadataStatement(signing_keys=KEYS['org']['jwks'])
    ms_jwt = ms.to_jwt(KEYS['fo']['keyjar'].get_signing_key('rsa'))

    cms = ClientMetadataStatement(
        metadata_statements=Message(**{ISSUER['org']: ms_jwt}),
        contacts=['*****@*****.**'])

    assert cms
Exemple #11
0
def test_pack_ms_wrong_fo():
    cms = ClientMetadataStatement(signing_keys=KEYS['org']['jwks'],
                                  contacts=['*****@*****.**'])

    _jwt = FOP.pack_metadata_statement(cms, alg='RS256', scope=['openid'])

    member = fo_member(FO1P)
    pr = member.unpack_metadata_statement(jwt_ms=_jwt)
    assert pr.result is None
    assert isinstance(pr.error[_jwt], (MissingSigningKey, KeyError))
Exemple #12
0
 def chose_registration_federation(self):
     """
     Chose one among many possible federations. Once the federation has been
     choosen store the registration info.
     
     :return: The :py:class:`LessOrEqual` instance matching the choosen 
         federation.
     """
     _leo = self.chose_federation(self.registration_federations)
     self.federation = _leo.fo
     self.store_registration_info(_leo.protected_claims)
     return ClientMetadataStatement(**_leo.protected_claims())
Exemple #13
0
def test_pack_and_unpack_ms_lev1():
    # metadata statement created by the organization
    cms_org = ClientMetadataStatement(signing_keys=ORGOP.keyjar.export_jwks(),
                                      contacts=['*****@*****.**'])

    #  signed by FO
    ms_org = FOP.pack_metadata_statement(cms_org,
                                         alg='RS256',
                                         scope=['openid'])

    # metadata statement created by the admin
    cms_rp = ClientMetadataStatement(
        signing_keys=ADMINOP.keyjar.export_jwks(),
        redirect_uris=['https://rp.example.com/auth_cb'])

    # signed by the org
    ms_rp = ORGOP.pack_metadata_statement(
        cms_rp, alg='RS256', metadata_statements=Message(**{FOP.iss: ms_org}))

    receiver = fo_member(FOP)
    ri = receiver.unpack_metadata_statement(jwt_ms=ms_rp)
    assert ri.result
Exemple #14
0
def test_pack_and_unpack_ms_lev0():
    cms = ClientMetadataStatement(signing_keys=FOP.keyjar.export_jwks(),
                                  contacts=['*****@*****.**'])

    _jwt = FOP.pack_metadata_statement(cms, alg='RS256', scope=['openid'])

    assert _jwt
    json_ms = unfurl(_jwt)
    #  print(json_ms.keys())
    assert set(json_ms.keys()) == {'signing_keys', 'iss', 'iat', 'exp',
                                   'kid', 'scope', 'contacts', 'jti'}

    # Unpack what you have packed
    pr = FOP.unpack_metadata_statement(jwt_ms=_jwt)

    assert pr.result
Exemple #15
0
    def registration_endpoint(self, request, authn=None, **kwargs):
        """
        Registration endpoint. This is where a registration request should
        be handled.

        :param request: The request, either as a dictionary or as a JSON
            document
        :param authn: Authentication information
        :param kwargs: Extra key work arguments.
        :return: A request response or an error response.
        """
        logger.debug("@registration_endpoint: <<{}>>".format(
            sanitize(request)))

        if isinstance(request, dict):
            request = ClientMetadataStatement(**request)
        else:
            try:
                request = ClientMetadataStatement().deserialize(
                    request, "json")
            except ValueError:
                request = ClientMetadataStatement().deserialize(request)

        if not self.is_federation_request(request):
            return provider.Provider.registration_endpoint(self,
                                                           request.to_json(),
                                                           authn=None,
                                                           **kwargs)

        try:
            request.verify()
        except Exception as err:
            return error('Invalid request')

        logger.info("registration_request:{}".format(
            sanitize(request.to_dict())))

        les = self.federation_entity.get_metadata_statement(
            request, 'registration')

        if les:
            ms = self.federation_entity.pick_by_priority(les)
            self.federation = ms.fo
        else:  # Nothing I can use
            return error(error='invalid_request',
                         descr='No signed metadata statement I could use')

        _pc = ms.protected_claims()
        if _pc:
            request = RegistrationRequest(**_pc)
        else:
            request = RegistrationRequest(
                **ms.unprotected_and_protected_claims())
        result = self.client_registration_setup(request)
        if 'signed_jwks_uri' in _pc:
            _kb = KeyBundle(source=_pc['signed_jwks_uri'],
                            verify_keys=ms.signing_keys,
                            verify_ssl=False)
            _kb.do_remote()
            replace_jwks_key_bundle(self.keyjar, result['client_id'], _kb)
            result['signed_jwks_uri'] = _pc['signed_jwks_uri']

        if isinstance(result, Response):
            return result

        # TODO This is where the OP should sign the response
        if ms.fo:
            _fo = ms.fo
            _sig = self._signer()

            if _sig:
                sms = _sig.create_signed_metadata_statement(result,
                                                            'response', [_fo],
                                                            single=True)
            else:
                raise SigningServiceError('No Signer')

            self.federation_entity.extend_with_ms(result, {_fo: sms})

        return Created(result.to_json(),
                       content="application/json",
                       headers=[("Cache-Control", "no-store")])