コード例 #1
0
 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_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)
コード例 #3
0
 def test_authentication_with_busted_token_fails(self):
     session = self._start_session()
     req = Request.blank("/")
     sign_request(req, **session)
     token = parse_authz_header(req)["oauth_consumer_key"]
     authz = req.environ["HTTP_AUTHORIZATION"]
     authz = authz.replace(token, "XXX" + token)
     req.environ["HTTP_AUTHORIZATION"] = authz
     self.app.request(req, status=401)
コード例 #4
0
 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_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)
コード例 #6
0
    def _identify_oauth(self, request):
        """Parse, validate and return the request's OAuth parameters.

        This method grabs the OAuth credentials from the Authorization header
        and performs some sanity-checks.  If the credentials are missing or
        malformed then it returns None; if they're ok then they are returned
        in a dict.

        Note that this method does *not* validate the OAuth signature.
        """
        params = parse_authz_header(request, None)
        if params is None:
            return None
        if params.get("scheme") != "OAuth":
            return None
        # Check that various parameters are as expected.
        if params.get("oauth_signature_method") != "HMAC-SHA1":
            msg = "unsupported OAuth signature method"
            return self._respond_unauthorized(request, msg)
        if "oauth_consumer_key" not in params:
            msg = "missing oauth_consumer_key"
            return self._respond_unauthorized(request, msg)
        # Check the timestamp, reject if too far from current time.
        try:
            timestamp = int(params["oauth_timestamp"])
        except (KeyError, ValueError):
            msg = "missing or malformed oauth_timestamp"
            return self._respond_unauthorized(request, msg)
        if abs(timestamp - time.time()) >= self.nonce_timeout:
            msg = "oauth_timestamp is not within accepted range"
            return self._respond_unauthorized(request, msg)
        # Check that the nonce is not being re-used.
        nonce = params.get("oauth_nonce")
        if nonce is None:
            msg = "missing oauth_nonce"
            return self._respond_unauthorized(request, msg)
        if nonce in self.nonce_cache:
            msg = "oauth_nonce has already been used"
            return self._respond_unauthorized(request, msg)
        # OK, they seem like sensible OAuth paramters.
        return params
コード例 #7
0
    def _identify_mac(self, request):
        """Parse, validate and return the request's MAC parameters.

        This method grabs the MAC credentials from the Authorization header
        and performs some sanity-checks.  If the credentials are missing or
        malformed then it returns None; if they're ok then they are returned
        in a dict.

        Note that this method does *not* validate the MAC signature.
        """
        params = parse_authz_header(request, None)
        if params is None:
            return None
        if params.get("scheme") != "MAC":
            return None
        # Check that various parameters are as expected.
        token = params.get("id")
        if token is None:
            msg = "missing MAC id"
            return self._respond_unauthorized(request, msg)
        # Check the timestamp and nonce for freshness or reuse.
        # TODO: the spec requires us to adjust for per-client clock skew.
        try:
            timestamp = int(params["ts"])
        except (KeyError, ValueError):
            msg = "missing or malformed MAC timestamp"
            return self._respond_unauthorized(request, msg)
        nonce = params.get("nonce")
        if nonce is None:
            msg = "missing MAC nonce"
            return self._respond_unauthorized(request, msg)
        if not self.nonce_manager.is_fresh(token, timestamp, nonce):
            msg = "MAC has stale token or nonce"
            return self._respond_unauthorized(request, msg)
        # OK, they seem like sensible MAC paramters.
        return params
コード例 #8
0
    def _identify_mac(self, request):
        """Parse, validate and return the request's MAC parameters.

        This method grabs the MAC credentials from the Authorization header
        and performs some sanity-checks.  If the credentials are missing or
        malformed then it returns None; if they're ok then they are returned
        in a dict.

        Note that this method does *not* validate the MAC signature.
        """
        params = parse_authz_header(request, None)
        if params is None:
            return None
        if params.get("scheme") != "MAC":
            return None
        # Check that various parameters are as expected.
        token = params.get("id")
        if token is None:
            msg = "missing MAC id"
            return self._respond_unauthorized(request, msg)
        # Check the timestamp and nonce for freshness or reuse.
        # TODO: the spec requires us to adjust for per-client clock skew.
        try:
            timestamp = int(params["ts"])
        except (KeyError, ValueError):
            msg = "missing or malformed MAC timestamp"
            return self._respond_unauthorized(request, msg)
        nonce = params.get("nonce")
        if nonce is None:
            msg = "missing MAC nonce"
            return self._respond_unauthorized(request, msg)
        if not self.nonce_manager.is_fresh(token, timestamp, nonce):
            msg = "MAC has stale token or nonce"
            return self._respond_unauthorized(request, msg)
        # OK, they seem like sensible MAC paramters.
        return params
    def test_parse_authz_header(self):
        def req(authz):
            """Make a fake request with the given authz header."""
            class request:
                environ = {"HTTP_AUTHORIZATION": authz}

            return request

        # Test parsing of a single unquoted parameter.
        params = parse_authz_header(req('Digest realm=hello'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['realm'], 'hello')

        # Test parsing of multiple parameters with mixed quotes.
        params = parse_authz_header(req('Digest test=one, again="two"'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['test'], 'one')
        self.assertEquals(params['again'], 'two')

        # Test parsing of an escaped quote and empty string.
        params = parse_authz_header(req('Digest test="\\"",again=""'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['test'], '"')
        self.assertEquals(params['again'], '')

        # Test parsing of embedded commas, escaped and non-escaped.
        params = parse_authz_header(req('Digest one="1\\,2", two="3,4"'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['one'], '1,2')
        self.assertEquals(params['two'], '3,4')

        # Test parsing on various malformed inputs
        self.assertRaises(ValueError, parse_authz_header, req(None))
        self.assertRaises(ValueError, parse_authz_header, req(""))
        self.assertRaises(ValueError, parse_authz_header, req(" "))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken raw-token'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="unclosed-quote'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm=unopened-quote"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="unescaped"quote"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="escaped-end-quote\\"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="duplicated",,what=comma'))

        # Test all those again, but returning a default value
        self.assertEquals(None, parse_authz_header(req(None), None))
        self.assertEquals(None, parse_authz_header(req(""), None))
        self.assertEquals(None, parse_authz_header(req(" "), None))
        self.assertEquals(None,
                          parse_authz_header(req('Broken raw-token'), None))
        self.assertEquals(
            None, parse_authz_header(req('Broken realm="unclosed-quote'),
                                     None))
        self.assertEquals(
            None, parse_authz_header(req('Broken realm=unopened-quote"'),
                                     None))
        self.assertEquals(
            None,
            parse_authz_header(req('Broken realm="unescaped"quote"'), None))
        self.assertEquals(
            None,
            parse_authz_header(req('Broken realm="escaped-end-quote\\"'),
                               None))
        self.assertEquals(
            None,
            parse_authz_header(req('Broken realm="duplicated",,what=comma'),
                               None))
コード例 #10
0
    def test_parse_authz_header(self):
        def req(authz):
            """Make a fake request with the given authz header."""
            class request:
                environ = {"HTTP_AUTHORIZATION": authz}
            return request

        # Test parsing of a single unquoted parameter.
        params = parse_authz_header(req('Digest realm=hello'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['realm'], 'hello')

        # Test parsing of multiple parameters with mixed quotes.
        params = parse_authz_header(req('Digest test=one, again="two"'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['test'], 'one')
        self.assertEquals(params['again'], 'two')

        # Test parsing of an escaped quote and empty string.
        params = parse_authz_header(req('Digest test="\\"",again=""'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['test'], '"')
        self.assertEquals(params['again'], '')

        # Test parsing of embedded commas, escaped and non-escaped.
        params = parse_authz_header(req('Digest one="1\\,2", two="3,4"'))
        self.assertEquals(params['scheme'], 'Digest')
        self.assertEquals(params['one'], '1,2')
        self.assertEquals(params['two'], '3,4')

        # Test parsing on various malformed inputs
        self.assertRaises(ValueError, parse_authz_header, req(None))
        self.assertRaises(ValueError, parse_authz_header, req(""))
        self.assertRaises(ValueError, parse_authz_header, req(" "))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken raw-token'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="unclosed-quote'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm=unopened-quote"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="unescaped"quote"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="escaped-end-quote\\"'))
        self.assertRaises(ValueError, parse_authz_header,
                          req('Broken realm="duplicated",,what=comma'))

        # Test all those again, but returning a default value
        self.assertEquals(None, parse_authz_header(req(None), None))
        self.assertEquals(None, parse_authz_header(req(""), None))
        self.assertEquals(None, parse_authz_header(req(" "), None))
        self.assertEquals(None,
                          parse_authz_header(req('Broken raw-token'), None))
        self.assertEquals(None, parse_authz_header(
                          req('Broken realm="unclosed-quote'), None))
        self.assertEquals(None, parse_authz_header(
                          req('Broken realm=unopened-quote"'), None))
        self.assertEquals(None, parse_authz_header(
                          req('Broken realm="unescaped"quote"'), None))
        self.assertEquals(None, parse_authz_header(
                          req('Broken realm="escaped-end-quote\\"'), None))
        self.assertEquals(None, parse_authz_header(
                          req('Broken realm="duplicated",,what=comma'), None))