def setUp(self): self.plugin = VEPAuthPlugin(audiences=["localhost"], verifier=vep.DummyVerifier(), token_manager=StubTokenManager()) application = PluggableAuthenticationMiddleware(stub_application, [["vep", self.plugin]], [["vep", self.plugin]], [["vep", self.plugin]], [], stub_request_classifier, stub_challenge_decider) self.app = TestApp(application)
def setUp(self): self.plugin = VEPAuthPlugin(audiences=["localhost"], verifier=vep.DummyVerifier()) application = PluggableAuthenticationMiddleware( stub_application, [["vep", self.plugin]], [["vep", self.plugin]], [["vep", self.plugin]], [], stub_request_classifier, stub_challenge_decider, ) self.app = TestApp(application)
class TestVEPAuthPlugin(unittest2.TestCase): """Testcases for the main VEPAuthPlugin class.""" def setUp(self): self.plugin = VEPAuthPlugin( audiences=["localhost"], verifier=vep.DummyVerifier(), token_manager=StubTokenManager() ) application = PluggableAuthenticationMiddleware( stub_application, [["vep", self.plugin]], [["vep", self.plugin]], [["vep", self.plugin]], [], stub_request_classifier, stub_challenge_decider, ) self.app = TestApp(application) def _make_assertion(self, address, audience="http://localhost", **kwds): return vep.DummyVerifier.make_assertion(address, audience, **kwds) def _start_session(self, email="*****@*****.**", *args, **kwds): assertion = self._make_assertion(email, *args, **kwds) headers = {"Authorization": "Browser-ID " + assertion} session = self.app.get(self.plugin.token_url, headers=headers).json return {"token": session["id"], "secret": session["key"]} def test_implements(self): verifyClass(IIdentifier, VEPAuthPlugin) verifyClass(IAuthenticator, VEPAuthPlugin) verifyClass(IChallenger, VEPAuthPlugin) def test_make_plugin_can_explicitly_set_all_properties(self): plugin = make_plugin( audiences="example.com", token_url="/test_token_url", verifier="vep:DummyVerifier", token_manager="vep:LocalVerifier", nonce_timeout=42, ) self.assertEquals(plugin.audiences, ["example.com"]) self.assertEquals(plugin.token_url, "/test_token_url") self.assertTrue(isinstance(plugin.verifier, vep.DummyVerifier)) self.assertTrue(isinstance(plugin.token_manager, vep.LocalVerifier)) self.assertEquals(plugin.nonce_timeout, 42) def test_make_plugin_produces_sensible_defaults(self): # The "audiences" parameter must be set explicitly self.assertRaises(ValueError, make_plugin) plugin = make_plugin("one two") self.assertEquals(plugin.audiences, ["one", "two"]) self.assertEquals(plugin.token_url, "/request_token") self.assertTrue(isinstance(plugin.verifier, vep.RemoteVerifier)) self.assertTrue(isinstance(plugin.token_manager, SignedTokenManager)) self.assertEquals(plugin.nonce_timeout, 60) def test_make_plugin_loads_urlopen_from_dotted_name(self): plugin = make_plugin("one two", verifier="vep:LocalVerifier", verifier_urlopen="urllib2:urlopen") self.assertEquals(plugin.audiences, ["one", "two"]) self.assertTrue(isinstance(plugin.verifier, vep.LocalVerifier)) self.assertEquals(plugin.verifier.urlopen, urllib2.urlopen) def test_make_plugin_treats_empty_audiences_string_as_none(self): plugin = make_plugin("") self.assertEquals(plugin.audiences, None) plugin = make_plugin(" ") self.assertEquals(plugin.audiences, []) def test_make_plugin_errors_out_on_unexpected_keyword_args(self): self.assertRaises(TypeError, make_plugin, "", unexpected="spanish-inquisition") def test_make_plugin_errors_out_on_args_to_a_non_callable(self): self.assertRaises(ValueError, make_plugin, "", verifier="vep:__doc__", verifier_urlopen="urllib2:urlopen") def test_checking_for_silly_argument_errors(self): self.assertRaises(ValueError, VEPAuthPlugin, audiences="notalist") def test_remember_does_nothing(self): self.assertEquals(self.plugin.remember(make_environ(), {}), []) def test_forget_gives_a_challenge_header(self): headers = self.plugin.forget(make_environ(), {}) self.assertEquals(len(headers), 1) self.assertEquals(headers[0][0], "WWW-Authenticate") self.assertTrue(headers[0][1].startswith("MAC+BrowserID ")) self.assertTrue(self.plugin.token_url in headers[0][1]) def test_unauthenticated_requests_get_a_challenge(self): # Requests to most URLs generate a 401, which is passed through # with the appropriate challenge. r = self.app.get("/", status=401) challenge = r.headers["WWW-Authenticate"] self.assertTrue(challenge.startswith("MAC+BrowserID")) self.assertTrue(self.plugin.token_url in challenge) # Requests to URLs with "forbidden" generate a 403 in the downstream # app, which should be converted into a 401 by the plugin. r = self.app.get("/forbidden", status=401) challenge = r.headers["WWW-Authenticate"] self.assertTrue(challenge.startswith("MAC+BrowserID")) self.assertTrue(self.plugin.token_url in challenge) def test_sending_an_assertion_creates_a_token(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} # This fails since we're not at the token-provisioning URL. r = self.app.get("/", headers=headers, status=401) self.assertTrue("id" not in r.body) # This works since we're at the postback url. r = self.app.get(self.plugin.token_url, headers=headers) self.assertTrue("id" in r.body) def test_that_an_empty_token_url_disables_provisioning(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} self.plugin.token_url = "" r = self.app.get("/", headers=headers, status=401) self.assertTrue("id" not in r.body) r = self.app.get("/request_token", headers=headers, status=401) self.assertTrue("id" not in r.body) def test_non_get_requests_give_405(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} self.app.post(self.plugin.token_url, headers=headers, status=405) def test_provisioning_with_malformed_assertion(self): authz = "Browser-ID I AINT NO ASSERTION, FOOL!" headers = {"Authorization": authz} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("assertion" in r.body) def test_provisioning_with_no_credentials_gives_401(self): headers = {} self.app.get(self.plugin.token_url, headers=headers, status=401) def test_provisioning_with_basic_credentials_gives_400(self): headers = {"Authorization": "Basic dTpw"} self.app.get(self.plugin.token_url, headers=headers, status=400) def test_provisioning_with_untrusted_assertion(self): assertion = self._make_assertion("test@moz", assertion_sig="X") headers = {"Authorization": "Browser-ID " + assertion} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("assertion" in r.body) def test_provisioning_with_invalid_audience(self): assertion = self._make_assertion("*****@*****.**", "http://evil.com") headers = {"Authorization": "Browser-ID " + assertion} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("audience" in r.body) # Setting audiences to None will allow it to pass # if it matches the HTTP_HOST header. self.plugin.audiences = None r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("audience" in r.body) r = self.app.get(self.plugin.token_url, headers=headers, extra_environ={"HTTP_HOST": "evil.com"}) self.assertTrue("id" in r.body) def test_provisioning_with_unaccepted_email_address(self): assertion = self._make_assertion("*****@*****.**") headers = {"Authorization": "Browser-ID " + assertion} self.app.get(self.plugin.token_url, headers=headers, status=401) def test_authenticated_request_works(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) r = self.app.request(req) self.assertEquals(r.body, "*****@*****.**") def test_authentication_with_non_mac_scheme_fails(self): req = Request.blank("/") req.authorization = "OpenID hello=world" self.app.request(req, status=401) def test_authentication_without_consumer_key_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("id", "idd") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_without_timestamp_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("ts", "typostamp") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_without_nonce_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("nonce", "typonce") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_with_expired_timestamp_fails(self): session = self._start_session() req = Request.blank("/") # Do an initial request so that the server can # calculate and cache our clock skew. ts = str(int(time.time())) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=200) # Now do one with a really old timestamp. ts = str(int(time.time() - 1000)) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_far_future_timestamp_fails(self): session = self._start_session() req = Request.blank("/") # Do an initial request so that the server can # calculate and cache our clock skew. ts = str(int(time.time())) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=200) # Now do one with a far future timestamp. ts = str(int(time.time() + 1000)) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_reused_nonce_fails(self): session = self._start_session() # First request with that nonce should succeed. req = Request.blank("/") req.authorization = ("MAC", {"nonce": "PEPPER"}) sign_request(req, **session) r = self.app.request(req) self.assertEquals(r.body, "*****@*****.**") # Second request with that nonce should fail. req = Request.blank("/") req.authorization = ("MAC", {"nonce": "PEPPER"}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_busted_token_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) token = parse_authz_header(req)["id"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(token, "XXX" + token) req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_with_busted_signature_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) signature = parse_authz_header(req)["mac"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(signature, "XXX" + signature) req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_access_to_public_urls(self): # Request with no credentials is allowed access. req = Request.blank("/public") resp = self.app.request(req) self.assertEquals(resp.body, "public") # Request with valid credentials is allowed access. session = self._start_session() req = Request.blank("/public") sign_request(req, **session) resp = self.app.request(req) self.assertEquals(resp.body, "public") # Request with invalid credentials gets a 401. req = Request.blank("/public") sign_request(req, **session) signature = parse_authz_header(req)["mac"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(signature, "XXX" + signature) req.environ["HTTP_AUTHORIZATION"] = authz resp = self.app.request(req, status=401) def test_authenticate_only_accepts_mac_credentials(self): # Yes, this is a rather pointless test that boosts line coverage... self.assertEquals(self.plugin.authenticate(make_environ(), {}), None) def test_token_url_can_contain_placeholders(self): self.plugin.token_url = "/{application}/{version}/{test}/foo" authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} # this doesn't match the pattern and should return a 401 r = self.app.get("/foo/bar/bar", headers=headers, status=401) self.assertTrue("id" not in r.body) # valid pattern should return a consumer key r = self.app.get("/foo/1.0/bar/foo", headers=headers) self.assertTrue("id" in r.body) self.plugin.token_manager.applications = {"foo": ["1.0"], "bar": ["2.1"], "baz": ["1.2"]} # defining manually a set of applications an making a request for one # of them should work r = self.app.get("/foo/1.0/bar/foo", headers=headers) self.assertTrue("id" in r.body) # this doesn't match any of the defined applications and should return # a 404 self.assertRaises(HTTPNotFound, self.app.get, "/not_an_app/1.0/bar/foo", headers=headers) # bad version self.assertRaises(HTTPNotFound, self.app.get, "/foo/1.4/bar/foo", headers=headers) def test_extra_data_gets_added(self): self.plugin.token_manager = ExtraTokenManager() authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} resp = self.app.get(self.plugin.token_url, headers=headers, status=200) self.assertTrue("foo" in resp.json) self.assertEqual(resp.json["foo"], "bar")
class TestVEPAuthPlugin(unittest2.TestCase): """Testcases for the main VEPAuthPlugin class.""" def setUp(self): self.plugin = VEPAuthPlugin(audiences=["localhost"], verifier=vep.DummyVerifier(), token_manager=StubTokenManager()) application = PluggableAuthenticationMiddleware(stub_application, [["vep", self.plugin]], [["vep", self.plugin]], [["vep", self.plugin]], [], stub_request_classifier, stub_challenge_decider) self.app = TestApp(application) def _make_assertion(self, address, audience="http://localhost", **kwds): return vep.DummyVerifier.make_assertion(address, audience, **kwds) def _start_session(self, email="*****@*****.**", *args, **kwds): assertion = self._make_assertion(email, *args, **kwds) headers = {"Authorization": "Browser-ID " + assertion} session = self.app.get(self.plugin.token_url, headers=headers).json return { "token": session["id"], "secret": session["key"], } def test_implements(self): verifyClass(IIdentifier, VEPAuthPlugin) verifyClass(IAuthenticator, VEPAuthPlugin) verifyClass(IChallenger, VEPAuthPlugin) def test_make_plugin_can_explicitly_set_all_properties(self): plugin = make_plugin( audiences="example.com", token_url="/test_token_url", verifier="vep:DummyVerifier", token_manager="vep:LocalVerifier", nonce_timeout=42) self.assertEquals(plugin.audiences, ["example.com"]) self.assertEquals(plugin.token_url, "/test_token_url") self.assertTrue(isinstance(plugin.verifier, vep.DummyVerifier)) self.assertTrue(isinstance(plugin.token_manager, vep.LocalVerifier)) self.assertEquals(plugin.nonce_timeout, 42) def test_make_plugin_produces_sensible_defaults(self): # The "audiences" parameter must be set explicitly self.assertRaises(ValueError, make_plugin) plugin = make_plugin("one two") self.assertEquals(plugin.audiences, ["one", "two"]) self.assertEquals(plugin.token_url, "/request_token") self.assertTrue(isinstance(plugin.verifier, vep.RemoteVerifier)) self.assertTrue(isinstance(plugin.token_manager, SignedTokenManager)) self.assertEquals(plugin.nonce_timeout, 60) def test_make_plugin_loads_urlopen_from_dotted_name(self): plugin = make_plugin("one two", verifier="vep:LocalVerifier", verifier_urlopen="urllib2:urlopen") self.assertEquals(plugin.audiences, ["one", "two"]) self.assertTrue(isinstance(plugin.verifier, vep.LocalVerifier)) self.assertEquals(plugin.verifier.urlopen, urllib2.urlopen) def test_make_plugin_treats_empty_audiences_string_as_none(self): plugin = make_plugin("") self.assertEquals(plugin.audiences, None) plugin = make_plugin(" ") self.assertEquals(plugin.audiences, []) def test_make_plugin_errors_out_on_unexpected_keyword_args(self): self.assertRaises(TypeError, make_plugin, "", unexpected="spanish-inquisition") def test_make_plugin_errors_out_on_args_to_a_non_callable(self): self.assertRaises(ValueError, make_plugin, "", verifier="vep:__doc__", verifier_urlopen="urllib2:urlopen") def test_checking_for_silly_argument_errors(self): self.assertRaises(ValueError, VEPAuthPlugin, audiences="notalist") def test_remember_does_nothing(self): self.assertEquals(self.plugin.remember(make_environ(), {}), []) def test_forget_gives_a_challenge_header(self): headers = self.plugin.forget(make_environ(), {}) self.assertEquals(len(headers), 1) self.assertEquals(headers[0][0], "WWW-Authenticate") self.assertTrue(headers[0][1].startswith("MAC+BrowserID ")) self.assertTrue(self.plugin.token_url in headers[0][1]) def test_unauthenticated_requests_get_a_challenge(self): # Requests to most URLs generate a 401, which is passed through # with the appropriate challenge. r = self.app.get("/", status=401) challenge = r.headers["WWW-Authenticate"] self.assertTrue(challenge.startswith("MAC+BrowserID")) self.assertTrue(self.plugin.token_url in challenge) # Requests to URLs with "forbidden" generate a 403 in the downstream # app, which should be converted into a 401 by the plugin. r = self.app.get("/forbidden", status=401) challenge = r.headers["WWW-Authenticate"] self.assertTrue(challenge.startswith("MAC+BrowserID")) self.assertTrue(self.plugin.token_url in challenge) def test_sending_an_assertion_creates_a_token(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} # This fails since we're not at the token-provisioning URL. r = self.app.get("/", headers=headers, status=401) self.assertTrue("id" not in r.body) # This works since we're at the postback url. r = self.app.get(self.plugin.token_url, headers=headers) self.assertTrue("id" in r.body) def test_that_an_empty_token_url_disables_provisioning(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} self.plugin.token_url = "" r = self.app.get("/", headers=headers, status=401) self.assertTrue("id" not in r.body) r = self.app.get("/request_token", headers=headers, status=401) self.assertTrue("id" not in r.body) def test_non_get_requests_give_405(self): authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} self.app.post(self.plugin.token_url, headers=headers, status=405) def test_provisioning_with_malformed_assertion(self): authz = "Browser-ID I AINT NO ASSERTION, FOOL!" headers = {"Authorization": authz} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("assertion" in r.body) def test_provisioning_with_no_credentials_gives_401(self): headers = {} self.app.get(self.plugin.token_url, headers=headers, status=401) def test_provisioning_with_basic_credentials_gives_400(self): headers = {"Authorization": "Basic dTpw"} self.app.get(self.plugin.token_url, headers=headers, status=400) def test_provisioning_with_untrusted_assertion(self): assertion = self._make_assertion("test@moz", assertion_sig="X") headers = {"Authorization": "Browser-ID " + assertion} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("assertion" in r.body) def test_provisioning_with_invalid_audience(self): assertion = self._make_assertion("*****@*****.**", "http://evil.com") headers = {"Authorization": "Browser-ID " + assertion} r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("audience" in r.body) # Setting audiences to None will allow it to pass # if it matches the HTTP_HOST header. self.plugin.audiences = None r = self.app.get(self.plugin.token_url, headers=headers, status=400) self.assertTrue("audience" in r.body) r = self.app.get(self.plugin.token_url, headers=headers, extra_environ={"HTTP_HOST": "evil.com"}) self.assertTrue("id" in r.body) def test_provisioning_with_unaccepted_email_address(self): assertion = self._make_assertion("*****@*****.**") headers = {"Authorization": "Browser-ID " + assertion} self.app.get(self.plugin.token_url, headers=headers, status=401) def test_authenticated_request_works(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) r = self.app.request(req) self.assertEquals(r.body, "*****@*****.**") def test_authentication_with_non_mac_scheme_fails(self): req = Request.blank("/") req.authorization = "OpenID hello=world" self.app.request(req, status=401) def test_authentication_without_consumer_key_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("id", "idd") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_without_timestamp_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("ts", "typostamp") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_without_nonce_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace("nonce", "typonce") req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_with_expired_timestamp_fails(self): session = self._start_session() req = Request.blank("/") # Do an initial request so that the server can # calculate and cache our clock skew. ts = str(int(time.time())) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=200) # Now do one with a really old timestamp. ts = str(int(time.time() - 1000)) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_far_future_timestamp_fails(self): session = self._start_session() req = Request.blank("/") # Do an initial request so that the server can # calculate and cache our clock skew. ts = str(int(time.time())) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=200) # Now do one with a far future timestamp. ts = str(int(time.time() + 1000)) req.authorization = ("MAC", {"ts": ts}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_reused_nonce_fails(self): session = self._start_session() # First request with that nonce should succeed. req = Request.blank("/") req.authorization = ("MAC", {"nonce": "PEPPER"}) sign_request(req, **session) r = self.app.request(req) self.assertEquals(r.body, "*****@*****.**") # Second request with that nonce should fail. req = Request.blank("/") req.authorization = ("MAC", {"nonce": "PEPPER"}) sign_request(req, **session) self.app.request(req, status=401) def test_authentication_with_busted_token_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) token = parse_authz_header(req)["id"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(token, "XXX" + token) req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_authentication_with_busted_signature_fails(self): session = self._start_session() req = Request.blank("/") sign_request(req, **session) signature = parse_authz_header(req)["mac"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(signature, "XXX" + signature) req.environ["HTTP_AUTHORIZATION"] = authz self.app.request(req, status=401) def test_access_to_public_urls(self): # Request with no credentials is allowed access. req = Request.blank("/public") resp = self.app.request(req) self.assertEquals(resp.body, "public") # Request with valid credentials is allowed access. session = self._start_session() req = Request.blank("/public") sign_request(req, **session) resp = self.app.request(req) self.assertEquals(resp.body, "public") # Request with invalid credentials gets a 401. req = Request.blank("/public") sign_request(req, **session) signature = parse_authz_header(req)["mac"] authz = req.environ["HTTP_AUTHORIZATION"] authz = authz.replace(signature, "XXX" + signature) req.environ["HTTP_AUTHORIZATION"] = authz resp = self.app.request(req, status=401) def test_authenticate_only_accepts_mac_credentials(self): # Yes, this is a rather pointless test that boosts line coverage... self.assertEquals(self.plugin.authenticate(make_environ(), {}), None) def test_token_url_can_contain_placeholders(self): self.plugin.token_url = "/{application}/{version}/{test}/foo" authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} # this doesn't match the pattern and should return a 401 r = self.app.get("/foo/bar/bar", headers=headers, status=401) self.assertTrue("id" not in r.body) # valid pattern should return a consumer key r = self.app.get("/foo/1.0/bar/foo", headers=headers) self.assertTrue("id" in r.body) self.plugin.token_manager.applications = {"foo": ["1.0"], "bar": ["2.1"], "baz": ["1.2"]} # defining manually a set of applications an making a request for one # of them should work r = self.app.get("/foo/1.0/bar/foo", headers=headers) self.assertTrue("id" in r.body) # this doesn't match any of the defined applications and should return # a 404 self.assertRaises(HTTPNotFound, self.app.get, "/not_an_app/1.0/bar/foo", headers=headers) # bad version self.assertRaises(HTTPNotFound, self.app.get, "/foo/1.4/bar/foo", headers=headers) def test_extra_data_gets_added(self): self.plugin.token_manager = ExtraTokenManager() authz = "Browser-ID " + self._make_assertion("*****@*****.**") headers = {"Authorization": authz} resp = self.app.get(self.plugin.token_url, headers=headers, status=200) self.assertTrue('foo' in resp.json) self.assertEqual(resp.json['foo'], 'bar')