예제 #1
0
 def test_without_memory_nor_memcache(self):
     # this should make a request each time
     with patched_supportdoc_fetching():
         cm = SupportDocumentManagerWithCache(memory=False, memcache=False)
         self.assertFalse(cm.memory)
         self.assertFalse(cm.memcache)
         cm.get_support_document('browserid.org')
 def test_without_memory_nor_memcache(self):
     # this should make a request each time
     with patched_supportdoc_fetching():
         cm = SupportDocumentManagerWithCache(memory=False, memcache=False)
         self.assertFalse(cm.memory)
         self.assertFalse(cm.memcache)
         cm.get_support_document('browserid.org')
 def test_verifier_rejects_unallowed_issuers(self):
     config = self._make_config({  # noqa; indentation below is non-standard
         "browserid.audiences":
             "https://testmytoken.com",
         "browserid.trusted_issuers":
             "accounts.firefox.com trustyidp.org",
         "browserid.allowed_issuers":
             "accounts.firefox.com mockmyid.com",
     })
     with patched_supportdoc_fetching():
         verifier = config.registry.getUtility(IBrowserIdVerifier)
         # The issuer is both trusted, and allowed.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="accounts.firefox.com")
         self.assertEquals(verifier.verify(assertion)["email"],
                           "*****@*****.**")
         # The issuer is allowed and is the primary.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="mockmyid.com")
         self.assertEquals(verifier.verify(assertion)["email"],
                           "*****@*****.**")
         # The issuer is allowed, but not trusted as a secondary.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="mockmyid.com")
         with self.assertRaises(browserid.errors.InvalidSignatureError):
             verifier.verify(assertion)
         # The issuer is trsuted, but is not allowed.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="trustyidp.org")
         with self.assertRaises(browserid.errors.InvalidIssuerError):
             verifier.verify(assertion)
         # The issuer is the primary, but is not allowed.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="example.com")
         with self.assertRaises(browserid.errors.InvalidIssuerError):
             verifier.verify(assertion)
         # Various tests for string pattern-matching edgecases.
         # All of these are primaries, but not allowed.
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="mockmyid.org")
         with self.assertRaises(browserid.errors.InvalidIssuerError):
             verifier.verify(assertion)
         assertion = make_assertion(email="*****@*****.**",
                                    audience="https://testmytoken.com",
                                    issuer="mockmyid.co")
         with self.assertRaises(browserid.errors.InvalidIssuerError):
             verifier.verify(assertion)
예제 #4
0
    def test_cache_eviction_based_on_time(self):
        supportdocs = SupportDocumentManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            # It should be in the cache, so this works fine.
            self.assertTrue(verifier.verify(assertion))
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)
예제 #5
0
    def test_cache_eviction_based_on_time(self):
        supportdocs = SupportDocumentManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            # It should be in the cache, so this works fine.
            self.assertTrue(verifier.verify(assertion))
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)
    def test_memory(self):
        with patched_supportdoc_fetching():
            memory = TTLedDict(1)
            cm = SupportDocumentManagerWithCache(memory=memory)
            self.assertFalse(cm.memcache)
            self.assertEquals(len(cm.memory), 0)

            # getting something should populate the memory
            cm.get_support_document('browserid.org')
            self.assertEquals(len(cm.memory), 1)

            # if we sleep for a while, the value should be invalid
            time.sleep(1)
            self.assertFalse('browserid.org' in memory)
            with self.assertRaises(KeyError):
                memory['browserid.org']
예제 #7
0
    def test_memory(self):
        with patched_supportdoc_fetching():
            memory = TTLedDict(1)
            cm = SupportDocumentManagerWithCache(memory=memory)
            self.assertFalse(cm.memcache)
            self.assertEquals(len(cm.memory), 0)

            # getting something should populate the memory
            cm.get_support_document('browserid.org')
            self.assertEquals(len(cm.memory), 1)

            # if we sleep for a while, the value should be invalid
            time.sleep(1)
            self.assertFalse('browserid.org' in memory)
            with self.assertRaises(KeyError):
                memory['browserid.org']
예제 #8
0
파일: test_account.py 프로젝트: eevee/floof
    def test_account_login_persona(self):
        from floof.views.account import account_login_persona as view

        def verify(request, next_url, flash_msg):
            response = view(request.context, request)
            flashes = request.session['_f_']
            assert len(flashes) == 1
            assert flash_msg in flashes[0]
            assert response['redirect-to'] == next_url

        audience = 'https://localhost'
        self.config.add_settings({'auth.persona.audience': audience})
        request = self._make_request()
        request.method = 'POST'
        request.user = sim.sim_user(credentials=[('persona', OLD_ASSERTION_ADDR)])

        # Test failures

        trials = (
            (None, 'unspecified error'),
            ('', 'unspecified error'),
            (self._randstr(), 'unspecified error'),
            (OLD_ASSERTION, 'signature was invalid')
        )

        for a, f in trials:
            request.POST = MultiDict({'assertion': a})
            verify(request,
                   next_url=request.route_url('account.login'),
                   flash_msg=f)
            request.session.clear()

        # Test success

        email = self._randstr() + '@example.com'
        verifier = LocalVerifier([audience], warning=False)
        a = make_assertion(email, audience)

        request.POST = MultiDict({'assertion': a})
        request.user = sim.sim_user(credentials=[('persona', email)])
        request.environ['paste.testing'] = True
        request.environ['tests.auth.persona.verifier'] = verifier
        request.environ['tests.auth.persona.audience'] = audience
        with patched_supportdoc_fetching():
            verify(request,
                   next_url=request.route_url('root'),
                   flash_msg='Re-authentication successful')
예제 #9
0
파일: test_account.py 프로젝트: silky/floof
    def test_account_login_persona(self):
        from floof.views.account import account_login_persona as view

        def verify(request, next_url, flash_msg):
            response = view(request.context, request)
            flashes = request.session['_f_']
            assert len(flashes) == 1
            assert flash_msg in flashes[0]
            assert response['redirect-to'] == next_url

        audience = 'https://localhost'
        self.config.add_settings({'auth.persona.audience': audience})
        request = self._make_request()
        request.method = 'POST'
        request.user = sim.sim_user(credentials=[('persona',
                                                  OLD_ASSERTION_ADDR)])

        # Test failures

        trials = ((None, 'unspecified error'), ('', 'unspecified error'),
                  (self._randstr(), 'unspecified error'),
                  (OLD_ASSERTION, 'signature was invalid'))

        for a, f in trials:
            request.POST = MultiDict({'assertion': a})
            verify(request,
                   next_url=request.route_url('account.login'),
                   flash_msg=f)
            request.session.clear()

        # Test success

        email = self._randstr() + '@example.com'
        verifier = LocalVerifier([audience], warning=False)
        a = make_assertion(email, audience)

        request.POST = MultiDict({'assertion': a})
        request.user = sim.sim_user(credentials=[('persona', email)])
        request.environ['paste.testing'] = True
        request.environ['tests.auth.persona.verifier'] = verifier
        request.environ['tests.auth.persona.audience'] = audience
        with patched_supportdoc_fetching():
            verify(request,
                   next_url=request.route_url('root'),
                   flash_msg='Re-authentication successful')
예제 #10
0
    def test_cache_eviction_during_write(self):
        supportdocs = SupportDocumentManager(cache_timeout=0.1)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(supportdocs.cache), 1)
        # Let that cached key expire
        time.sleep(0.1)
        # Now grab a different key; caching it should purge the expired key.
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(supportdocs.cache), 1)
        # Check that only the second entry is in cache.

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #11
0
    def test_cache_eviction_during_write(self):
        supportdocs = SupportDocumentManager(cache_timeout=0.1)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(supportdocs.cache), 1)
        # Let that cached key expire
        time.sleep(0.1)
        # Now grab a different key; caching it should purge the expired key.
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(supportdocs.cache), 1)
        # Check that only the second entry is in cache.

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #12
0
    def test_cache_eviction_based_on_size(self):
        supportdocs = SupportDocumentManager(max_size=2)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying some assertions.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(supportdocs.cache), 2)
        # Hitting a third host should evict the first public key.
        assertion3 = make_assertion("*****@*****.**", "", "3.com")
        self.assertTrue(verifier.verify(assertion3))
        self.assertEquals(len(supportdocs.cache), 2)
        # Make it error out if re-fetching any keys

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #13
0
    def test_cache_eviction_based_on_size(self):
        supportdocs = SupportDocumentManager(max_size=2)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs)
        # Prime the cache by verifying some assertions.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        assertion2 = make_assertion("*****@*****.**", "", "2.com")
        self.assertTrue(verifier.verify(assertion2))
        self.assertEquals(len(supportdocs.cache), 2)
        # Hitting a third host should evict the first public key.
        assertion3 = make_assertion("*****@*****.**", "", "3.com")
        self.assertTrue(verifier.verify(assertion3))
        self.assertEquals(len(supportdocs.cache), 2)
        # Make it error out if re-fetching any keys

        exc = RuntimeError("key fetch disabled")
        with patched_supportdoc_fetching(exc=exc):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
예제 #14
0
    def setUp(self):
        self.config = testing.setUp()
        settings = {}
        load_into_settings(self.get_ini(), settings)
        self.config.add_settings(settings)
        metlog_wrapper = load_from_settings('metlog',
                self.config.registry.settings)
        for logger in ('tokenserver', 'mozsvc', 'powerhose'):
            hook_logger(logger, metlog_wrapper.client)

        self.config.registry['metlog'] = metlog_wrapper.client
        self.config.include("tokenserver")
        load_and_register("tokenserver", self.config)
        self.backend = self.config.registry.getUtility(INodeAssignment)
        wsgiapp = self.config.make_wsgi_app()
        wsgiapp = CatchErrors(wsgiapp)
        self.app = TestApp(wsgiapp)

        self.patched = patched_supportdoc_fetching()
        self.patched.__enter__()

        # by default the conditions are accepted
        self.backend.set_accepted_conditions_flag('aitc-1.0', True)
예제 #15
0
 def check_signature(self, *args, **kwargs):
     with patched_supportdoc_fetching():
         return super(MockCryptoWorker, self)\
                 .check_signature(*args, **kwargs)
예제 #16
0
 def setUp(self):
     self.patched = patched_supportdoc_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(["*"], warning=False)
예제 #17
0
class TestLocalVerifier(unittest.TestCase, VerifierTestCases):

    def setUp(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            self.verifier = LocalVerifier(["*"])
        # There should be a warning about using this verifier.
        self.assertEquals(w[0].category, FutureWarning)

    def test_error_handling_in_verify_certificate_chain(self):
        self.assertRaises(ValueError,
                          self.verifier.verify_certificate_chain, [])
        certs = decode_json_bytes(EXPIRED_ASSERTION)["certificates"]
        certs = [jwt.parse(cert) for cert in certs]
        self.assertRaises(ExpiredSignatureError,
                          self.verifier.verify_certificate_chain, certs)

    @callwith(patched_supportdoc_fetching())
    def test_well_known_doc_with_public_key(self):
        assertion = make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_delegated_primary(self):
        assertion = make_assertion("*****@*****.**", "http://persona.org",
                issuer="delegated.org")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_double_delegated_primary(self):
        assertion = make_assertion("*****@*****.**",
                "http://persona.org", issuer="delegated.org")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_audience_verification(self):

        # create an assertion with the audience set to http://persona.org for
        # the tests. This assertion is only valid for this audience.
        assertion = make_assertion("*****@*****.**", "http://persona.org")

        # we don't set any audience explicitely here
        verifier = LocalVerifier(warning=False)

        # specifying the audience on verifier.verify uses it.
        self.assertRaises(AudienceMismatchError, verifier.verify, assertion,
                          audience="*.example.com")

        # if we change the audience to the expected one, the assertion is
        # considered valid
        self.assertTrue(verifier.verify(assertion, audience="persona.org"))

        # specifying the audience when creating the verifier AND when calling
        # verifier.verify.
        verifier = LocalVerifier(["*.example.com"], warning=False)
        self.assertRaises(AudienceMismatchError, verifier.verify, assertion,
                          audience="*.example.com")

        # specifying a different audience at instanciation and at verification,
        # only the last one is used.
        self.assertTrue(verifier.verify(assertion, audience="persona.org"))

        # overwritting the audience with an invalid one (we are waiting for
        # persona.org but getting example.com) raises an error
        self.assertRaises(AudienceMismatchError, verifier.verify,
                          audience="persona.org",
                          assertion=make_assertion("*****@*****.**",
                                                   "http://example.com"))

        # the assertion is valid for http://persona.org; the verifier is
        # configured to accept this audience so it should validate
        verifier = LocalVerifier(["persona.org"], warning=False)
        self.assertTrue(verifier.verify(assertion))

        # but if we ask explicitely for a different audience (the assertion is
        # not accepted, even if the instance is configured so)
        self.assertRaises(AudienceMismatchError, verifier.verify,
                          assertion, audience="example.com")
예제 #18
0
 def setUp(self):
     self.patched = patched_supportdoc_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(["*"])
예제 #19
0
class TestLocalVerifier(unittest.TestCase, VerifierTestCases):
    def setUp(self):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            self.verifier = LocalVerifier(["*"])
        # There should be no warning about using this verifier.
        self.assertEquals(len(w), 0)

    @callwith(patched_supportdoc_fetching())
    def test_error_handling_in_verify_certificate_chain(self):
        self.assertRaises(ValueError, self.verifier.verify_certificate_chain,
                          [])
        certs = decode_json_bytes(EXPIRED_ASSERTION)["certificates"]
        certs = [jwt.parse(cert) for cert in certs]
        self.assertRaises(ExpiredSignatureError,
                          self.verifier.verify_certificate_chain, certs)

    @callwith(patched_supportdoc_fetching())
    def test_well_known_doc_with_public_key(self):
        assertion = make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_delegated_primary(self):
        assertion = make_assertion("*****@*****.**",
                                   "http://persona.org",
                                   issuer="delegated.org")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_double_delegated_primary(self):
        assertion = make_assertion("*****@*****.**",
                                   "http://persona.org",
                                   issuer="delegated.org")
        self.assertTrue(self.verifier.verify(assertion))

    @callwith(patched_supportdoc_fetching())
    def test_extraction_of_extra_claims(self):
        assertion = make_assertion(
            "*****@*****.**",
            "http://e.com",
            idp_claims={"extra": "claim"},
            user_claims={"another": "claim"},
        )
        result = self.verifier.verify(assertion)
        self.assertEqual(result["status"], "okay")
        self.assertEqual(result["idpClaims"], {"extra": "claim"})
        self.assertEqual(result["userClaims"], {"another": "claim"})

    @callwith(patched_supportdoc_fetching())
    def test_extraction_of_extra_claims_from_principal(self):
        assertion = make_assertion(
            "*****@*****.**",
            "http://e.com",
            idp_claims={
                "extra": "claim",
                "principal": {
                    "email": "*****@*****.**",
                    "another": "claim",
                    "public-key": "should-be-ignored",
                }
            },
        )
        result = self.verifier.verify(assertion)
        self.assertEqual(result["status"], "okay")
        self.assertEqual(result["idpClaims"], {
            "extra": "claim",
            "another": "claim",
        })
        self.assertTrue("userClaims" not in result)

    @callwith(patched_supportdoc_fetching())
    def test_email_validation(self):
        verifier = LocalVerifier(audiences="http://persona.org")

        # Null bytes in the email hostname.
        assertion = make_assertion("[email protected]\x00.com",
                                   "http://persona.org")
        self.assertRaises(ValueError, verifier.verify, assertion)

        # Newlines in the email hostanem.
        assertion = make_assertion("[email protected]\[email protected]",
                                   "http://persona.org")
        self.assertRaises(ValueError, verifier.verify, assertion)

        # Null bytes in the email username.
        assertion = make_assertion(u"test\[email protected]",
                                   "http://persona.org")
        self.assertRaises(ValueError, verifier.verify, assertion)

        # Null bytes with regex-busting newline.
        assertion = make_assertion(u"[email protected]\u0000\[email protected]",
                                   "http://persona.org")
        self.assertRaises(ValueError, verifier.verify, assertion)

    @callwith(patched_supportdoc_fetching())
    def test_audience_verification(self):

        # create an assertion with the audience set to http://persona.org for
        # the tests. This assertion is only valid for this audience.
        assertion = make_assertion("*****@*****.**", "http://persona.org")

        # we don't set any audience explicitely here
        verifier = LocalVerifier()

        # specifying the audience on verifier.verify uses it.
        self.assertRaises(AudienceMismatchError,
                          verifier.verify,
                          assertion,
                          audience="*.example.com")

        # if we change the audience to the expected one, the assertion is
        # considered valid
        self.assertTrue(verifier.verify(assertion, audience="persona.org"))

        # specifying the audience when creating the verifier AND when calling
        # verifier.verify.
        verifier = LocalVerifier(["*.example.com"])
        self.assertRaises(AudienceMismatchError,
                          verifier.verify,
                          assertion,
                          audience="*.example.com")

        # specifying a different audience at instanciation and at verification,
        # only the last one is used.
        self.assertTrue(verifier.verify(assertion, audience="persona.org"))

        # overwritting the audience with an invalid one (we are waiting for
        # persona.org but getting example.com) raises an error
        self.assertRaises(AudienceMismatchError,
                          verifier.verify,
                          audience="persona.org",
                          assertion=make_assertion("*****@*****.**",
                                                   "http://example.com"))

        # the assertion is valid for http://persona.org; the verifier is
        # configured to accept this audience so it should validate
        verifier = LocalVerifier(["persona.org"])
        self.assertTrue(verifier.verify(assertion))

        # but if we ask explicitely for a different audience (the assertion is
        # not accepted, even if the instance is configured so)
        self.assertRaises(AudienceMismatchError,
                          verifier.verify,
                          assertion,
                          audience="example.com")
예제 #20
0
 def check_signature(self, *args, **kwargs):
     with patched_supportdoc_fetching():
         return super(MockCryptoWorker, self)\
             .check_signature(*args, **kwargs)