def test_account_login_browserid(self): from floof.views.account import account_login_browserid 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['next_url'] == next_url audience = 'https://mysite.example.org' self.config.add_settings({'auth.browserid.audience': audience}) request = self._make_request() request.method = 'POST' request.user = sim.sim_user(credentials=[('browserid', OLD_ASSERTION_ADDR)]) for a in (None, '', self._randstr(), OLD_ASSERTION): request.POST = MultiDict({'assertion': a}) verify(request, next_url=request.route_url('account.login'), flash_msg='signature was invalid') request.session.clear() email = self._randstr() + '@example.com' verifier = DummyVerifier() a = verifier.make_assertion(email, audience) request.POST = MultiDict({'assertion': a}) request.user = sim.sim_user(credentials=[('browserid', email)]) request.environ['paste.testing'] = True request.environ['tests.auth.browserid.verifier'] = verifier request.environ['tests.auth.browserid.audience'] = audience verify(request, next_url=request.route_url('root'), flash_msg='Re-authentication successful')
class TestDummyVerifier(unittest.TestCase, VerifierTestCases): def setUp(self): with warnings.catch_warnings(record=True): warnings.simplefilter("default") self.verifier = DummyVerifier() def test_verification_of_valid_dummy_assertion(self): audience = "http://example.com" assertion = self.verifier.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_untrusted_issuer(self): audience = "http://example.com" issuer = "moz.com" # Assertions for @moz.com addresses can come from moz.com assertion = self.verifier.make_assertion("*****@*****.**", audience, issuer=issuer) self.assertTrue(self.verifier.verify(assertion, audience)) # But assertions for other addresses cannot. assertion = self.verifier.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 = self.verifier.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 = self.verifier.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 = self.verifier.make_assertion("*****@*****.**", audience, certificate_sig="CORRUPTUS") self.assertRaises(InvalidSignatureError, self.verifier.verify, assertion)
def test_cache_eviction_based_on_time(self): cache = FIFOCache(cache_timeout=0.1) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying an assertion. assertion = self.verifier.make_assertion("*****@*****.**", "") self.assertTrue(verifier.verify(assertion)) # Make it error out if re-fetching the keys def fetch_public_key(hostname): raise 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)
def test_cache_eviction_during_write(self): cache = FIFOCache(cache_timeout=0.1) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying an assertion. assertion1 = self.verifier.make_assertion("*****@*****.**", "", "1.com") self.assertTrue(verifier.verify(assertion1)) self.assertEquals(len(cache), 1) # Let that cached key expire time.sleep(0.1) # Now grab a different key; caching it should purge the expired key. assertion2 = self.verifier.make_assertion("*****@*****.**", "", "2.com") self.assertTrue(verifier.verify(assertion2)) self.assertEquals(len(cache), 1) # Check that only the second entry is in cache. def fetch_public_key(hostname): raise RuntimeError("key fetch disabled") verifier.fetch_public_key = fetch_public_key self.assertTrue(verifier.verify(assertion2)) self.assertRaises(RuntimeError, verifier.verify, assertion1)
def test_malformed_assertions(self): # This one doesn't actually contain an assertion assertion = encode_json_bytes({}) self.assertRaises(ValueError, self.verifier.verify, assertion) # This one has no certificates pub, priv = DummyVerifier._get_keypair("TEST") assertion = encode_json_bytes({ "assertion": JWT.generate({"aud": "TEST"}, priv), "certificates": [] }) self.assertRaises(ValueError, self.verifier.verify, assertion)
def test_well_known_doc_with_public_key(self): # The browserid.org server doesn't currently have /.well-known/vep. # This simulates it with a dummy key. def urlopen(url, data): # NOQA class response(object): @staticmethod def read(): key = DummyVerifier.fetch_public_key("browserid.org") return json.dumps({"public-key": key}) return response self.verifier.urlopen = urlopen assertion = DummyVerifier.make_assertion("*****@*****.**", "http://e.com") self.assertTrue(self.verifier.verify(assertion))
def setUp(self): self.root = self.conf_get('main', 'url') self.vusers = int(self.conf_get('main', 'vusers')) self.verifier = DummyVerifier key = DummyVerifier.fetch_public_key("browserid.org") key = json.dumps({"public-key": key}) def urlopen(url, data): # NOQA class response(object): @staticmethod def read(): return key return response self.verifier.urlopen = urlopen
def test_cache_eviction_based_on_size(self): cache = FIFOCache(max_size=2) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying some assertions. assertion1 = self.verifier.make_assertion("*****@*****.**", "", "1.com") self.assertTrue(verifier.verify(assertion1)) assertion2 = self.verifier.make_assertion("*****@*****.**", "", "2.com") self.assertTrue(verifier.verify(assertion2)) self.assertEquals(len(cache), 2) # Hitting a third host should evict the first public key. assertion3 = self.verifier.make_assertion("*****@*****.**", "", "3.com") self.assertTrue(verifier.verify(assertion3)) self.assertEquals(len(cache), 2) # Make it error out if re-fetching any keys def fetch_public_key(hostname): raise RuntimeError("key fetch disabled") verifier.fetch_public_key = fetch_public_key # It should have to re-fetch for 1, but not 2. self.assertTrue(verifier.verify(assertion2)) self.assertRaises(RuntimeError, verifier.verify, assertion1)
def test_error_jwt_with_mismatched_algorithm(self): pub, priv = DummyVerifier._get_keypair("TEST") jwt = JWT.generate({}, priv) jwt = JWT.parse(jwt) pub["algorithm"] = "RS" self.assertFalse(jwt.check_signature(pub))
def setUp(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.verifier = DummyVerifier() # There should be no warnings from the dummy verifier. self.assertEquals(len(w), 0)
class TestDummyVerifier(unittest.TestCase, VerifierTestCases): def setUp(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.verifier = DummyVerifier() # There should be no warnings from the dummy verifier. self.assertEquals(len(w), 0) def test_verification_of_valid_dummy_assertion(self): audience = "http://example.com" assertion = self.verifier.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 = self.verifier.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 = self.verifier.make_assertion("*****@*****.**", audience, issuer=issuer) self.assertTrue(self.verifier.verify(assertion, audience)) # But assertions for other addresses cannot. assertion = self.verifier.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 = self.verifier.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 = self.verifier.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 = self.verifier.make_assertion("*****@*****.**", audience, certificate_sig="CORRUPTUS") self.assertRaises(InvalidSignatureError, self.verifier.verify, assertion) def test_cache_eviction_based_on_time(self): cache = FIFOCache(cache_timeout=0.1) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying an assertion. assertion = self.verifier.make_assertion("*****@*****.**", "") self.assertTrue(verifier.verify(assertion)) # Make it error out if re-fetching the keys def fetch_public_key(hostname): raise 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) def test_cache_eviction_based_on_size(self): cache = FIFOCache(max_size=2) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying some assertions. assertion1 = self.verifier.make_assertion("*****@*****.**", "", "1.com") self.assertTrue(verifier.verify(assertion1)) assertion2 = self.verifier.make_assertion("*****@*****.**", "", "2.com") self.assertTrue(verifier.verify(assertion2)) self.assertEquals(len(cache), 2) # Hitting a third host should evict the first public key. assertion3 = self.verifier.make_assertion("*****@*****.**", "", "3.com") self.assertTrue(verifier.verify(assertion3)) self.assertEquals(len(cache), 2) # Make it error out if re-fetching any keys def fetch_public_key(hostname): raise RuntimeError("key fetch disabled") verifier.fetch_public_key = fetch_public_key # 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): cache = FIFOCache(cache_timeout=0.1) verifier = DummyVerifier(cache=cache) # Prime the cache by verifying an assertion. assertion1 = self.verifier.make_assertion("*****@*****.**", "", "1.com") self.assertTrue(verifier.verify(assertion1)) self.assertEquals(len(cache), 1) # Let that cached key expire time.sleep(0.1) # Now grab a different key; caching it should purge the expired key. assertion2 = self.verifier.make_assertion("*****@*****.**", "", "2.com") self.assertTrue(verifier.verify(assertion2)) self.assertEquals(len(cache), 1) # Check that only the second entry is in cache. def fetch_public_key(hostname): raise RuntimeError("key fetch disabled") verifier.fetch_public_key = fetch_public_key self.assertTrue(verifier.verify(assertion2)) self.assertRaises(RuntimeError, verifier.verify, assertion1)
def read(): key = DummyVerifier.fetch_public_key("browserid.org") return json.dumps({"public-key": key})
def setUp(self): with warnings.catch_warnings(record=True): warnings.simplefilter("default") self.verifier = DummyVerifier()