def _test_bad_assertion(self, idx=None, in_one_day=None): if idx is None: idx = random.choice(range(self.vusers)) if in_one_day is None: in_one_day = int(time.time() + 60 * 60 * 24) * 1000 email = "{uid}@{host}".format(uid=idx, host="mockmyid.com") # expired assertion expired = make_assertion( email=email, issuer=self.valid_domain, exp=int(time.time() - 60) * 1000, audience=self.audience, issuer_keypair=(None, MOCKMYID_PRIVATE_KEY)) self._do_token_exchange(expired, 401) # wrong issuer wrong_issuer = make_assertion(email, exp=in_one_day, audience=self.audience) self._do_token_exchange(wrong_issuer, 401) # wrong email host email = "{uid}@{host}".format(uid=idx, host=self.invalid_domain) wrong_email_host = make_assertion( email, issuer=self.valid_domain, exp=in_one_day, audience=self.audience, issuer_keypair=(None, MOCKMYID_PRIVATE_KEY)) self._do_token_exchange(wrong_email_host, 401)
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 _generate_token(self): """Pick an identity, log in and generate the auth token.""" uid = random.randint(1, 1000000) # existing user # Use the tokenserver if configured, otherwise fake it ourselves. if self.token_server_url is None: self.logi("synthesizing token for uid %s" % (uid,)) endpoint_node = random.choice(self.endpoint_nodes) req = Request.blank(endpoint_node) token, secret = self.auth_plugin.encode_mac_id(req, uid) endpoint_url = endpoint_node + "/%s/%s" % (VERSION, uid) else: email = "*****@*****.**" % (uid,) self.logi("requesting token for %s" % (email,)) assertion = make_assertion(email, audience="persona.org", issuer="loadtest.local") token_url = self.token_server_url + "/1.0/aitc/1.0" self.addHeader("Authorization", "Browser-ID " + assertion) response = self.get(token_url) credentials = json.loads(response.body) token = credentials["id"].encode("ascii") secret = credentials["key"].encode("ascii") endpoint_url = credentials["api_endpoint"] self.logi("assigned endpoint_url %s" % (endpoint_url)) return token, secret, endpoint_url
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_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 get_assertion(email, audience='*', hostname='browserid.org', bad_issuer_cert=False, bad_email_cert=False): """Creates a browserid assertion for the given email, audience and hostname. This function can also be used to create invalid assertions. This will be the case if you set the bad_issuer_cert or the bad_email cert arguments to True. """ key = load_key(hostname) pub = key.rsa.pub()[1].decode('latin-1') kwargs = { 'issuer_keypair': (pub, key), 'email_keypair': (pub, key) } # We remove the issuer_keypair and email_keypair arguments, which will let # the underlying make_assertion function from browserid use its internal # test certificates, which are not the same as the one we use for the # tokenserver. if bad_issuer_cert: del kwargs['issuer_keypair'] if bad_email_cert: del kwargs['email_keypair'] return make_assertion(email, audience, **kwargs)
def test_single_token_exchange_new_user(self): uid = str(uuid.uuid1()) email = "loadtest-{uid}@{host}".format(uid=uid, host=self.valid_domain) self._do_token_exchange(make_assertion( email=email, issuer=self.valid_domain, audience=self.audience, issuer_keypair=(None, MOCKMYID_PRIVATE_KEY)))
def test_single_token_exchange(self): uid = random.randint(1, 1000000) email = "user{uid}@{host}".format(uid=uid, host=self.valid_domain) self._do_token_exchange(make_assertion( email=email, issuer=self.valid_domain, audience=self.audience, issuer_keypair=(None, MOCKMYID_PRIVATE_KEY)))
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"})
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)
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): 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 _make_assertion(self, email, **kwds): if "audience" not in kwds: kwds["audience"] = self.audience if "exp" not in kwds: kwds["exp"] = int((time.time() + ONE_YEAR) * 1000) if "issuer" not in kwds: kwds["issuer"] = MOCKMYID_DOMAIN if "issuer_keypair" not in kwds: kwds["issuer_keypair"] = (None, MOCKMYID_PRIVATE_KEY) return make_assertion(email, **kwds)
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)
def test_verifier_rejects_unallowed_issuers(self): config = self._make_config({ # noqa; indentation below is non-standard "browserid.audiences": "https://testmytoken.com", "browserid.allowed_issuers": "accounts.firefox.com mockmyid.com", }) verifier = config.registry.getUtility(IBrowserIdVerifier) assertion = make_assertion(email="*****@*****.**", audience="https://testmytoken.com") mock_response = { "status": "okay", "principal": { "email": "*****@*****.**", }, "audience": "https://testmytoken.com", "issuer": "login.persona.org", } with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "mockmyid.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): self.assertEquals( verifier.verify(assertion)["principal"]["email"], "*****@*****.**") mock_response["issuer"] = "accounts.firefox.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): self.assertEquals( verifier.verify(assertion)["principal"]["email"], "*****@*****.**") mock_response["issuer"] = "mockmyid.org" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "http://mockmyid.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "mockmyid.co" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = 42 with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = None with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) del mock_response["issuer"] with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): 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_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"})
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 _make_assertion(self, email=None, audience=None, **kwds): if email is None: email = "user%d@%s" % (random.randint(0, 1000000), MOCKMYID_DOMAIN) if audience is None: audience = "https://secret.mozilla.com" if "exp" not in kwds: kwds["exp"] = int((time.time() + ONE_YEAR) * 1000) if "issuer" not in kwds: kwds["issuer"] = MOCKMYID_DOMAIN if "issuer_keypair" not in kwds: kwds["issuer_keypair"] = (None, MOCKMYID_PRIVATE_KEY) return make_assertion(email, audience, **kwds)
def test_token_exchange(self): # a valid browserid assertion should be taken by the server and turned # back into an authentication token which is valid for 30 minutes. # we want to test this for a number of users, with different # assertions. for idx in range(self.vusers): email = "{uid}@{host}".format(uid=idx, host=self.valid_domain) self._do_token_exchange(make_assertion( email=email, issuer=self.valid_domain, audience=self.audience, issuer_keypair=(None, MOCKMYID_PRIVATE_KEY)))
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.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"))
def test_verifier_rejects_unallowed_issuers(self): config = self._make_config({ # noqa; indentation below is non-standard "browserid.audiences": "https://testmytoken.com", "browserid.allowed_issuers": "accounts.firefox.com mockmyid.com", }) verifier = config.registry.getUtility(IBrowserIdVerifier) assertion = make_assertion(email="*****@*****.**", audience="https://testmytoken.com") mock_response = { "status": "okay", "principal": { "email": "*****@*****.**", }, "audience": "https://testmytoken.com", "issuer": "login.persona.org", } with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "mockmyid.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): self.assertEquals(verifier.verify(assertion)["principal"]["email"], "*****@*****.**") mock_response["issuer"] = "accounts.firefox.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): self.assertEquals(verifier.verify(assertion)["principal"]["email"], "*****@*****.**") mock_response["issuer"] = "mockmyid.org" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "http://mockmyid.com" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = "mockmyid.co" with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = 42 with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) mock_response["issuer"] = None with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion) del mock_response["issuer"] with self._mock_verifier(verifier, text=json.dumps(mock_response)): with self.assertRaises(browserid.errors.InvalidIssuerError): verifier.verify(assertion)
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_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)
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 _make_browserid_assertion(self, email, **kwds): if "audience" not in kwds: kwds["audience"] = self.client.base_url if "exp" not in kwds: kwds["exp"] = int((time.time() + ONE_YEAR) * 1000) if "issuer" not in kwds: kwds["issuer"] = MOCKMYID_DOMAIN if "issuer_keypair" not in kwds: kwds["issuer_keypair"] = (None, MOCKMYID_PRIVATE_KEY) kwds["idp_claims"] = { 'fxa-generation': self.generation_counter, 'fxa-keysChangedAt': self.generation_counter, } return make_assertion(email, **kwds)
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_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)
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')
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')
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)
def get_assertion(email, audience="*", issuer='browserid.org', bad_issuer_cert=False, bad_email_cert=False, exp=None): """Creates a browserid assertion for the given email, audience and hostname. This function can also be used to create invalid assertions. This will be the case if you set the bad_issuer_cert or the bad_email cert arguments to True. """ kwargs = {'exp': exp} if bad_issuer_cert: kwargs['issuer_keypair'] =\ get_keypair(hostname="not-the-right-host.com") if bad_email_cert: kwargs['email_keypair'] =\ get_keypair(hostname="not-the-right-host.com") return make_assertion(email, audience, issuer=issuer, **kwargs)
def test_verifier_failure_cases(self): config = self._make_config({ # noqa; indentation below is non-standard "browserid.audiences": "https://testmytoken.com", }) verifier = config.registry.getUtility(IBrowserIdVerifier) assertion = make_assertion(email="*****@*****.**", audience="https://testmytoken.com") with self._mock_verifier(verifier, status_code=500): with self.assertRaises(browserid.errors.ConnectionError): verifier.verify(assertion) with self._mock_verifier(verifier, text="<h1>Server Error</h1>"): with self.assertRaises(browserid.errors.ConnectionError): verifier.verify(assertion) with self._mock_verifier(verifier, text='{"status": "error"}'): with self.assertRaises(browserid.errors.InvalidSignatureError): verifier.verify(assertion) with self._mock_verifier(verifier, text='{"status": "potato"}'): with self.assertRaises(browserid.errors.InvalidSignatureError): verifier.verify(assertion)
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)
def get_assertion(email, audience="*", issuer='browserid.org', bad_issuer_cert=False, bad_email_cert=False, exp=None): """Creates a browserid assertion for the given email, audience and hostname. This function can also be used to create invalid assertions. This will be the case if you set the bad_issuer_cert or the bad_email cert arguments to True. """ kwargs = {'exp': exp} if bad_issuer_cert: kwargs['issuer_keypair'] =\ get_keypair(hostname="not-the-right-host.com") if bad_email_cert: kwargs['email_keypair'] =\ get_keypair(hostname="not-the-right-host.com") assertion = make_assertion(email, audience, issuer=issuer, **kwargs) return assertion.encode('ascii')
def _getassertion(self, **kw): kw.setdefault('email', '*****@*****.**') kw.setdefault('audience', 'http://tokenserver.services.mozilla.com') return make_assertion(**kw).encode('ascii')
def _make_assertion(self, email, **kwds): if "exp" not in kwds: kwds["exp"] = int((time.time() + ONE_YEAR) * 1000) return make_assertion(email, **kwds)
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_double_delegated_primary(self): assertion = make_assertion("*****@*****.**", "http://persona.org", issuer="delegated.org") self.assertTrue(self.verifier.verify(assertion))
def test_well_known_doc_with_public_key(self): assertion = make_assertion("*****@*****.**", "http://e.com") self.assertTrue(self.verifier.verify(assertion))
def _getassertion(self, **kw): kw.setdefault("email", "*****@*****.**") kw.setdefault("audience", "http://tokenserver.services.mozilla.com") return make_assertion(**kw).encode("ascii")
def test_browserid_is_supported(self): assertion = make_assertion('x', 'y').encode('ascii') res = self.app.get('/1.0/sync/1.1', headers={'Authorization': 'BrowserID ' + assertion}, status=401) self.assertEqual(res.json['status'], 'invalid-credentials')