Exemplo n.º 1
0
 async def mock_req(method: str, uri: str, data=None, headers=None):
     (expected_uri, resp_obj) = expected_requests.pop(0)
     assert uri == expected_uri
     resp = FakeResponse(
         code=200,
         phrase=b"OK",
         body=json.dumps(resp_obj).encode("utf-8"),
     )
     return resp
Exemplo n.º 2
0
 async def mock_req(
     method: str,
     uri: str,
     data: Optional[dict] = None,
     headers: Optional[Iterable[Tuple[AnyStr, AnyStr]]] = None,
 ):
     (expected_uri, resp_obj) = expected_requests.pop(0)
     assert uri == expected_uri
     resp = FakeResponse(
         code=HTTPStatus.OK,
         phrase=b"OK",
         body=json.dumps(resp_obj).encode("utf-8"),
     )
     return resp
Exemplo n.º 3
0
    def test_exchange_code_jwt_key(self):
        """Test that code exchange works with a JWK client secret."""
        from authlib.jose import jwt

        token = {"type": "bearer"}
        self.http_client.request = simple_async_mock(
            return_value=FakeResponse(
                code=200, phrase=b"OK", body=json.dumps(token).encode("utf-8")
            )
        )
        code = "code"

        # advance the clock a bit before we start, so we aren't working with zero
        # timestamps.
        self.reactor.advance(1000)
        start_time = self.reactor.seconds()
        ret = self.get_success(self.provider._exchange_code(code))

        self.assertEqual(ret, token)

        # the request should have hit the token endpoint
        kwargs = self.http_client.request.call_args[1]
        self.assertEqual(kwargs["method"], "POST")
        self.assertEqual(kwargs["uri"], TOKEN_ENDPOINT)

        # the client secret provided to the should be a jwt which can be checked with
        # the public key
        args = parse_qs(kwargs["data"].decode("utf-8"))
        secret = args["client_secret"][0]
        with open(_public_key_file_path()) as f:
            key = f.read()
        claims = jwt.decode(secret, key)
        self.assertEqual(claims.header["kid"], "ABC789")
        self.assertEqual(claims["aud"], ISSUER)
        self.assertEqual(claims["iss"], "DEFGHI")
        self.assertEqual(claims["sub"], CLIENT_ID)
        self.assertEqual(claims["iat"], start_time)
        self.assertGreater(claims["exp"], start_time)

        # check the rest of the POSTed data
        self.assertEqual(args["grant_type"], ["authorization_code"])
        self.assertEqual(args["code"], [code])
        self.assertEqual(args["client_id"], [CLIENT_ID])
        self.assertEqual(args["redirect_uri"], [CALLBACK_URL])
Exemplo n.º 4
0
    def test_exchange_code_no_auth(self):
        """Test that code exchange works with no client secret."""
        token = {"type": "bearer"}
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=200, phrase=b"OK", body=json.dumps(token).encode("utf-8")))
        code = "code"
        ret = self.get_success(self.provider._exchange_code(code))

        self.assertEqual(ret, token)

        # the request should have hit the token endpoint
        kwargs = self.http_client.request.call_args[1]
        self.assertEqual(kwargs["method"], "POST")
        self.assertEqual(kwargs["uri"], TOKEN_ENDPOINT)

        # check the POSTed data
        args = parse_qs(kwargs["data"].decode("utf-8"))
        self.assertEqual(args["grant_type"], ["authorization_code"])
        self.assertEqual(args["code"], [code])
        self.assertEqual(args["client_id"], [CLIENT_ID])
        self.assertEqual(args["redirect_uri"], [CALLBACK_URL])
Exemplo n.º 5
0
    def test_exchange_code(self):
        """Code exchange behaves correctly and handles various error scenarios."""
        token = {"type": "bearer"}
        token_json = json.dumps(token).encode("utf-8")
        self.http_client.request = simple_async_mock(
            return_value=FakeResponse(code=200, phrase=b"OK", body=token_json))
        code = "code"
        ret = self.get_success(self.provider._exchange_code(code))
        kwargs = self.http_client.request.call_args[1]

        self.assertEqual(ret, token)
        self.assertEqual(kwargs["method"], "POST")
        self.assertEqual(kwargs["uri"], TOKEN_ENDPOINT)

        args = parse_qs(kwargs["data"].decode("utf-8"))
        self.assertEqual(args["grant_type"], ["authorization_code"])
        self.assertEqual(args["code"], [code])
        self.assertEqual(args["client_id"], [CLIENT_ID])
        self.assertEqual(args["client_secret"], [CLIENT_SECRET])
        self.assertEqual(args["redirect_uri"], [CALLBACK_URL])

        # Test error handling
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=400,
            phrase=b"Bad Request",
            body=b'{"error": "foo", "error_description": "bar"}',
        ))
        from synapse.handlers.oidc import OidcError

        exc = self.get_failure(self.provider._exchange_code(code), OidcError)
        self.assertEqual(exc.value.error, "foo")
        self.assertEqual(exc.value.error_description, "bar")

        # Internal server error with no JSON body
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=500,
            phrase=b"Internal Server Error",
            body=b"Not JSON",
        ))
        exc = self.get_failure(self.provider._exchange_code(code), OidcError)
        self.assertEqual(exc.value.error, "server_error")

        # Internal server error with JSON body
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=500,
            phrase=b"Internal Server Error",
            body=b'{"error": "internal_server_error"}',
        ))

        exc = self.get_failure(self.provider._exchange_code(code), OidcError)
        self.assertEqual(exc.value.error, "internal_server_error")

        # 4xx error without "error" field
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=400,
            phrase=b"Bad request",
            body=b"{}",
        ))
        exc = self.get_failure(self.provider._exchange_code(code), OidcError)
        self.assertEqual(exc.value.error, "server_error")

        # 2xx error with "error" field
        self.http_client.request = simple_async_mock(return_value=FakeResponse(
            code=200,
            phrase=b"OK",
            body=b'{"error": "some_error"}',
        ))
        exc = self.get_failure(self.provider._exchange_code(code), OidcError)
        self.assertEqual(exc.value.error, "some_error")