Example #1
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)
Example #2
0
    def test_cache_eviction_based_on_time(self):
        certs = CertificatesManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            verifier.fetch_public_key = fetch_public_key
            # It should be in the cache, so this works fine.
            verifier.verify(assertion)
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)
Example #3
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)
Example #4
0
def verifyBackedAssertion(audience, assertion):
    if True:
        from browserid import LocalVerifier
        v = LocalVerifier(["*"], warning=False)
        print "local verification", v.verify(assertion)
        return
    else:
        url = "https://verifier.accounts.firefox.com/v2"
        headers = {"content-type": "application/json"}
        r = requests.post(url,
                          headers=headers,
                          data=json.dumps({"audience": audience,
                                           "assertion": assertion}))
        if r.status_code != 200:
            raise WebError(r)
        return r.json()
Example #5
0
    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")
    def test_cache_eviction_during_write(self):
        certs = CertificatesManager(cache_timeout=0.1)
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(certs.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(certs.cache), 1)
        # Check that only the second entry is in cache.

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
Example #7
0
def verifyBackedAssertion(audience, assertion):
    if True:
        from browserid import LocalVerifier
        v = LocalVerifier(["*"], warning=False)
        print "local verification", v.verify(assertion)
        return
    else:
        url = "https://verifier.accounts.firefox.com/v2"
        headers = {"content-type": "application/json"}
        r = requests.post(url,
                          headers=headers,
                          data=json.dumps({
                              "audience": audience,
                              "assertion": assertion
                          }))
        if r.status_code != 200:
            raise WebError(r)
        return r.json()
Example #8
0
    def test_cache_eviction_during_write(self):
        certs = CertificatesManager(cache_timeout=0.1)
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion1 = make_assertion("*****@*****.**", "", "1.com")
        self.assertTrue(verifier.verify(assertion1))
        self.assertEquals(len(certs.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(certs.cache), 1)
        # Check that only the second entry is in cache.

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
Example #9
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)
Example #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)
Example #11
0
    def test_cache_eviction_based_on_size(self):
        certs = CertificatesManager(max_size=2)
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # 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(certs.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(certs.cache), 2)
        # Make it error out if re-fetching any keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
Example #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)
def verify_assertion(audience, assertion, local=True):

	if local:

		v = LocalVerifier(["*"], warning=False)
		result = v.verify(assertion)

	else:
		url		= "https://verifier.accounts.firefox.com/v2"
		payload = json.dumps({"audience": audience, "assertion": assertion})

		req = urllib2.Request(url, data=payload)
		req.add_header("Content-Type", "application/json")
		req.get_method = lambda: 'POST'

		try:
			f = opener.open(req)
			result = json.loads(f.read())
			f.close()

		except urllib2.URLError, e:
			raise WeaveException("FxA sync auth token request failed: " + str(e) + " " + e.read())
Example #14
0
    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')
Example #15
0
 def test_audience_pattern_checking(self):
     verifier = LocalVerifier(["*.moz.com", "www.test.com"], warning=False)
     # Domains like *.moz.com should be valid audiences.
     # They will work with both the implicit patterns and explicit audience.
     assertion = make_assertion("*****@*****.**", "www.moz.com")
     self.assertTrue(verifier.verify(assertion))
     self.assertTrue(verifier.verify(assertion, "www.moz.com"))
     self.assertRaises(AudienceMismatchError,
                       verifier.verify, assertion, "www.test.com")
     # The specific domain www.test.com should be a valid audience.
     # It will work with both the implicit patterns and explicit audience.
     assertion = make_assertion("*****@*****.**", "www.test.com")
     self.assertTrue(verifier.verify(assertion))
     self.assertTrue(verifier.verify(assertion, "www.test.com"))
     self.assertTrue(verifier.verify(assertion, "*.test.com"))
     self.assertRaises(AudienceMismatchError,
                       verifier.verify, assertion, "www.moz.com")
     # Domains not matching any patterns should not be valid audiences.
     # They will fail unless given as an explicit argument.
     assertion = make_assertion("*****@*****.**", "www.evil.com")
     self.assertRaises(AudienceMismatchError, verifier.verify, assertion)
     self.assertTrue(verifier.verify(assertion, "www.evil.com"))
     self.assertTrue(verifier.verify(assertion, "*.evil.com"))
Example #16
0
 def test_audience_pattern_checking(self):
     verifier = LocalVerifier(["*.moz.com", "www.test.com"], warning=False)
     # Domains like *.moz.com should be valid audiences.
     # They will work with both the implicit patterns and explicit audience.
     assertion = make_assertion("*****@*****.**", "www.moz.com")
     self.assertTrue(verifier.verify(assertion))
     self.assertTrue(verifier.verify(assertion, "www.moz.com"))
     self.assertRaises(AudienceMismatchError, verifier.verify, assertion, "www.test.com")
     # The specific domain www.test.com should be a valid audience.
     # It will work with both the implicit patterns and explicit audience.
     assertion = make_assertion("*****@*****.**", "www.test.com")
     self.assertTrue(verifier.verify(assertion))
     self.assertTrue(verifier.verify(assertion, "www.test.com"))
     self.assertTrue(verifier.verify(assertion, "*.test.com"))
     self.assertRaises(AudienceMismatchError, verifier.verify, assertion, "www.moz.com")
     # Domains not matching any patterns should not be valid audiences.
     # They will fail unless given as an explicit argument.
     assertion = make_assertion("*****@*****.**", "www.evil.com")
     self.assertRaises(AudienceMismatchError, verifier.verify, assertion)
     self.assertTrue(verifier.verify(assertion, "www.evil.com"))
     self.assertTrue(verifier.verify(assertion, "*.evil.com"))
    def test_cache_eviction_based_on_time(self):
        certs = CertificatesManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # Prime the cache by verifying an assertion.
        assertion = make_assertion("*****@*****.**", "")
        self.assertTrue(verifier.verify(assertion))
        # Make it error out if re-fetching the keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            verifier.fetch_public_key = fetch_public_key
            # It should be in the cache, so this works fine.
            verifier.verify(assertion)
            # But after sleeping it gets evicted and the error is triggered.
            time.sleep(0.1)
            self.assertRaises(RuntimeError, verifier.verify, assertion)
Example #18
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)

    @patch('browserid.certificates.fetch_public_key', fetch_public_key)
    def test_well_known_doc_with_public_key(self):
        assertion = make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))
Example #19
0
    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)
    def test_cache_eviction_based_on_size(self):
        certs = CertificatesManager(max_size=2)
        verifier = LocalVerifier(["*"], certs=certs, warning=False)
        # 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(certs.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(certs.cache), 2)
        # Make it error out if re-fetching any keys

        with patched_key_fetching(exc=RuntimeError("key fetch disabled")):
            # It should have to re-fetch for 1, but not 2.
            self.assertTrue(verifier.verify(assertion2))
            self.assertRaises(RuntimeError, verifier.verify, assertion1)
Example #21
0
    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")
Example #22
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)
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_while_fetching_public_key(self):
        with patched_urlopen(exc=RuntimeError("TESTING")):
            self.assertRaises(ConnectionError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    def test_missing_well_known_document(self):
        with patched_urlopen(exc=RuntimeError("404 Not Found")):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    def test_malformed_well_known_document(self):
        # patch urlopen
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "I AINT NO JSON, FOOL!"

            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    def test_malformed_pub_key_document(self):
        called = []

        def urlopen(url, data):
            # First call must raise 404 so it will look for /pk.
            # Second call must return invalid JSON.
            class response(object):
                @staticmethod
                def read():
                    if not called:
                        called.append(True)
                        raise ValueError("404 Not Found")
                    return "I AINT NO JSON, FOOL!"

            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    def test_well_known_doc_with_no_public_key(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "{}"

            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    def test_well_known_doc_with_public_key(self):
        #  The browserid.org server doesn't currently have /.well-known/browserid.
        #  This simulates it with a dummy key.
        def urlopen(url, data):  # NOQA
            class response(object):
                @staticmethod
                def read():
                    key = fetch_public_key("browserid.org")
                    return json.dumps({"public-key": key})

            return response

        with patched_urlopen(urlopen):
            assertion = make_assertion("*****@*****.**", "http://e.com")
            self.assertTrue(self.verifier.verify(assertion))

    def test_handling_of_invalid_content_length_header_from_server(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def info():
                    return {"Content-Length": "forty-two"}

                @staticmethod  # NOQA
                def read(size):
                    raise RuntimeError  # pragma: nocover

            return response

        with patched_urlopen(urlopen):
            self.assertRaises(ConnectionError,
                              self.verifier.verify,
                              EXPIRED_ASSERTION,
                              now=0)

    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)
Example #24
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_while_fetching_public_key(self):
        with patched_urlopen(exc=RuntimeError("TESTING")):
            self.assertRaises(ConnectionError,
                              self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_missing_well_known_document(self):
        with patched_urlopen(exc=RuntimeError("404 Not Found")):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_malformed_well_known_document(self):
        # patch urlopen
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "I AINT NO JSON, FOOL!"
            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_malformed_pub_key_document(self):
        called = []

        def urlopen(url, data):
            # First call must raise 404 so it will look for /pk.
            # Second call must return invalid JSON.
            class response(object):
                @staticmethod
                def read():
                    if not called:
                        called.append(True)
                        raise ValueError("404 Not Found")
                    return "I AINT NO JSON, FOOL!"
            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_well_known_doc_with_no_public_key(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def read():
                    return "{}"
            return response

        with patched_urlopen(urlopen):
            self.assertRaises(InvalidIssuerError,
                              self.verifier.verify, EXPIRED_ASSERTION, now=0)

    def test_well_known_doc_with_public_key(self):
        #  The browserid.org server doesn't currently have /.well-known/browserid.
        #  This simulates it with a dummy key.
        def urlopen(url, data):  # NOQA
            class response(object):
                @staticmethod
                def read():
                    key = fetch_public_key("browserid.org")
                    return json.dumps({"public-key": key})
            return response

        with patched_urlopen(urlopen):
            assertion = make_assertion("*****@*****.**", "http://e.com")
            self.assertTrue(self.verifier.verify(assertion))

    def test_handling_of_invalid_content_length_header_from_server(self):
        def urlopen(url, data):
            class response(object):
                @staticmethod
                def info():
                    return {"Content-Length": "forty-two"}
                @staticmethod  # NOQA
                def read(size):
                    raise RuntimeError  # pragma: nocover
            return response

        with patched_urlopen(urlopen):
            self.assertRaises(ConnectionError, self.verifier.verify,
                              EXPIRED_ASSERTION, now=0)

    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)
Example #25
0
 def setUp(self):
     self.patched = patched_supportdoc_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(["*"])
Example #26
0
class TestDummyVerifier(unittest.TestCase, VerifierTestCases):

    def setUp(self):
        self.patched = patched_supportdoc_fetching()
        self.patched.__enter__()
        self.verifier = LocalVerifier(["*"])

    def tearDown(self):
        self.patched.__exit__(None, None, None)

    def test_verification_of_valid_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError,
                          self.verifier.verify, assertion, "http://moz.com")

    def test_verification_of_oldstyle_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   new_style=False)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError, self.verifier.verify,
                          assertion, "http://moz.com")

    def test_verification_of_untrusted_issuer(self):
        audience = "http://example.com"
        issuer = "moz.com"
        # Assertions for @moz.com addresses can come from moz.com
        assertion = make_assertion("*****@*****.**", audience, issuer=issuer)
        self.assertTrue(self.verifier.verify(assertion, audience))
        # But assertions for other addresses cannot (unless they delegated).
        assertion = make_assertion("*****@*****.**", audience,
                                   issuer=issuer)
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion, audience)

    def test_verification_of_expired_dummy_assertion(self):
        audience = "http://example.com"
        now = (time.time() * 1000)
        assertion = make_assertion("*****@*****.**", audience, exp=now - 1)
        self.assertTrue(self.verifier.verify(assertion, now=now - 2))
        self.assertRaises(ExpiredSignatureError, self.verifier.verify,
                          assertion)

    def test_verification_of_dummy_assertion_with_bad_assertion_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   assertion_sig="BADTOTHEBONE")
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion)

    def test_verification_of_dummy_assertion_with_bad_certificate_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   certificate_sig="CORRUPTUS")
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion)

    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_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)

    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)

    def test_audience_pattern_checking(self):
        verifier = LocalVerifier(["*.moz.com", "www.test.com"])
        # Domains like *.moz.com should be valid audiences.
        # They will work with both the implicit patterns and explicit audience.
        assertion = make_assertion("*****@*****.**", "www.moz.com")
        self.assertTrue(verifier.verify(assertion))
        self.assertTrue(verifier.verify(assertion, "www.moz.com"))
        self.assertRaises(AudienceMismatchError,
                          verifier.verify, assertion, "www.test.com")
        # The specific domain www.test.com should be a valid audience.
        # It will work with both the implicit patterns and explicit audience.
        assertion = make_assertion("*****@*****.**", "www.test.com")
        self.assertTrue(verifier.verify(assertion))
        self.assertTrue(verifier.verify(assertion, "www.test.com"))
        self.assertTrue(verifier.verify(assertion, "*.test.com"))
        self.assertRaises(AudienceMismatchError,
                          verifier.verify, assertion, "www.moz.com")
        # Domains not matching any patterns should not be valid audiences.
        # They will fail unless given as an explicit argument.
        assertion = make_assertion("*****@*****.**", "www.evil.com")
        self.assertRaises(AudienceMismatchError, verifier.verify, assertion)
        self.assertTrue(verifier.verify(assertion, "www.evil.com"))
        self.assertTrue(verifier.verify(assertion, "*.evil.com"))
Example #27
0
class TestDummyVerifier(unittest.TestCase, VerifierTestCases):

    def setUp(self):
        self.patched = patched_supportdoc_fetching()
        self.patched.__enter__()
        self.verifier = LocalVerifier(["*"], warning=False)

    def tearDown(self):
        self.patched.__exit__(None, None, None)

    def test_verification_of_valid_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError,
                          self.verifier.verify, assertion, "http://moz.com")

    def test_verification_of_oldstyle_dummy_assertion(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   new_style=False)
        self.assertTrue(self.verifier.verify(assertion))
        self.assertTrue(self.verifier.verify(assertion, audience))
        self.assertRaises(AudienceMismatchError, self.verifier.verify,
                          assertion, "http://moz.com")

    def test_verification_of_untrusted_issuer(self):
        audience = "http://example.com"
        issuer = "moz.com"
        # Assertions for @moz.com addresses can come from moz.com
        assertion = make_assertion("*****@*****.**", audience, issuer=issuer)
        self.assertTrue(self.verifier.verify(assertion, audience))
        # But assertions for other addresses cannot (unless they delegated).
        assertion = make_assertion("*****@*****.**", audience,
                                   issuer=issuer)
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion, audience)

    def test_verification_of_expired_dummy_assertion(self):
        audience = "http://example.com"
        now = (time.time() * 1000)
        assertion = make_assertion("*****@*****.**", audience, exp=now - 1)
        self.assertTrue(self.verifier.verify(assertion, now=now - 2))
        self.assertRaises(ExpiredSignatureError, self.verifier.verify,
                          assertion)

    def test_verification_of_dummy_assertion_with_bad_assertion_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   assertion_sig="BADTOTHEBONE")
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion)

    def test_verification_of_dummy_assertion_with_bad_certificate_sig(self):
        audience = "http://example.com"
        assertion = make_assertion("*****@*****.**", audience,
                                   certificate_sig="CORRUPTUS")
        self.assertRaises(InvalidSignatureError, self.verifier.verify,
                          assertion)

    def test_cache_eviction_based_on_time(self):
        supportdocs = SupportDocumentManager(FIFOCache(cache_timeout=0.1))
        verifier = LocalVerifier(["*"], supportdocs=supportdocs,
                warning=False)
        # 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_cache_eviction_based_on_size(self):
        supportdocs = SupportDocumentManager(max_size=2)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs,
                warning=False)
        # 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)

    def test_cache_eviction_during_write(self):
        supportdocs = SupportDocumentManager(cache_timeout=0.1)
        verifier = LocalVerifier(["*"], supportdocs=supportdocs,
                warning=False)
        # 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)

    def test_audience_pattern_checking(self):
        verifier = LocalVerifier(["*.moz.com", "www.test.com"], warning=False)
        # Domains like *.moz.com should be valid audiences.
        # They will work with both the implicit patterns and explicit audience.
        assertion = make_assertion("*****@*****.**", "www.moz.com")
        self.assertTrue(verifier.verify(assertion))
        self.assertTrue(verifier.verify(assertion, "www.moz.com"))
        self.assertRaises(AudienceMismatchError,
                          verifier.verify, assertion, "www.test.com")
        # The specific domain www.test.com should be a valid audience.
        # It will work with both the implicit patterns and explicit audience.
        assertion = make_assertion("*****@*****.**", "www.test.com")
        self.assertTrue(verifier.verify(assertion))
        self.assertTrue(verifier.verify(assertion, "www.test.com"))
        self.assertTrue(verifier.verify(assertion, "*.test.com"))
        self.assertRaises(AudienceMismatchError,
                          verifier.verify, assertion, "www.moz.com")
        # Domains not matching any patterns should not be valid audiences.
        # They will fail unless given as an explicit argument.
        assertion = make_assertion("*****@*****.**", "www.evil.com")
        self.assertRaises(AudienceMismatchError, verifier.verify, assertion)
        self.assertTrue(verifier.verify(assertion, "www.evil.com"))
        self.assertTrue(verifier.verify(assertion, "*.evil.com"))
Example #28
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")
Example #29
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")
Example #30
0
 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)
Example #31
0
 def setUp(self):
     self.patched = patched_key_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(["*"], warning=False)
Example #32
0
 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)
Example #33
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")
Example #34
0
 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)
Example #35
0
 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)
Example #36
0
 def setUp(self):
     self.patched = patched_supportdoc_fetching()
     self.patched.__enter__()
     self.verifier = LocalVerifier(["*"], warning=False)
Example #37
0
 def setUp(self):
     super(TestWorkerPoolVerifier, self).setUp()
     self.verifier = WorkerPoolVerifier(verifier=LocalVerifier(["*"]))
Example #38
0
 def setUp(self):
     super(TestWorkerPoolVerifier, self).setUp()
     self.verifier = WorkerPoolVerifier(
             verifier=LocalVerifier(["*"], warning=False)
     )
Example #39
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)

    @patch('browserid.certificates.fetch_public_key', fetch_public_key)
    def test_well_known_doc_with_public_key(self):
        assertion = make_assertion("*****@*****.**", "http://e.com")
        self.assertTrue(self.verifier.verify(assertion))

    @patch('browserid.certificates.fetch_public_key', fetch_public_key)
    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 difference 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")