From 6a3a60751aae59c84dc8a5b09395fb684f1ebaa8 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Tue, 19 May 2020 20:43:45 +0900 Subject: [PATCH] Fix #690 by adding basic auth handling in the new sync client --- integration_tests/samples/issues/issue_690.py | 44 +++++++++++++++++++ slack/web/base_client.py | 13 ++++++ tests/web/mock_web_api_server.py | 10 +++++ tests/web/test_web_client.py | 30 +++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 integration_tests/samples/issues/issue_690.py diff --git a/integration_tests/samples/issues/issue_690.py b/integration_tests/samples/issues/issue_690.py new file mode 100644 index 000000000..fff4ca5a2 --- /dev/null +++ b/integration_tests/samples/issues/issue_690.py @@ -0,0 +1,44 @@ +# ------------------ +# Only for running this script here +import logging +import sys +from os.path import dirname + +sys.path.insert(1, f"{dirname(__file__)}/../../..") +logging.basicConfig(level=logging.DEBUG) +# ------------------ + +# --------------------- +# Flask App +# --------------------- + +import os + +# pip install flask +from flask import Flask, make_response, request + +app = Flask(__name__) +logger = logging.getLogger(__name__) + + +@app.route("/slack/oauth/callback", methods=["GET"]) +def endpoint(): + code = request.args.get("code") + try: + from slack import WebClient + from slack.errors import SlackApiError + client = WebClient(token="") + client_id = os.environ["SLACK_CLIENT_ID"] + client_secret = os.environ["SLACK_CLIENT_SECRET"] + response = client.oauth_v2_access(client_id=client_id, client_secret=client_secret, code=code) + result = response.get("error", "success!") + return str(result) + except SlackApiError as e: + return make_response(str(e), 400) + + +if __name__ == "__main__": + # export SLACK_CLIENT_ID=111.222 + # export SLACK_CLIENT_SECRET= + # FLASK_ENV=development python integration_tests/samples/issues/issue_690.py + app.run(debug=True, host="localhost", port=3000) diff --git a/slack/web/base_client.py b/slack/web/base_client.py index f3991d8b8..f9b90b303 100644 --- a/slack/web/base_client.py +++ b/slack/web/base_client.py @@ -304,6 +304,19 @@ def _sync_send(self, api_url, req_args): _json = req_args["json"] if "json" in req_args else None headers = req_args["headers"] if "headers" in req_args else None token = params.get("token") if params and "token" in params else None + auth = ( + req_args["auth"] if "auth" in req_args else None + ) # Basic Auth for oauth.v2.access / oauth.access + if auth is not None: + if isinstance(auth, BasicAuth): + headers["Authorization"] = auth.encode() + elif isinstance(auth, str): + headers["Authorization"] = auth + else: + self._logger.warning( + f"As the auth: {auth}: {type(auth)} is unsupported, skipped" + ) + body_params = {} if params: body_params.update(params) diff --git a/tests/web/mock_web_api_server.py b/tests/web/mock_web_api_server.py index 6199b8a25..eda4058e9 100644 --- a/tests/web/mock_web_api_server.py +++ b/tests/web/mock_web_api_server.py @@ -45,6 +45,16 @@ def set_common_headers(self): def _handle(self): try: + if self.path in {"/oauth.access", "/oauth.v2.access"}: + self.send_response(200) + self.set_common_headers() + if self.headers["authorization"] == "Basic MTExLjIyMjpzZWNyZXQ=": + self.wfile.write("""{"ok":true}""".encode("utf-8")) + return + else: + self.wfile.write("""{"ok":false, "error":"invalid"}""".encode("utf-8")) + return + if self.is_valid_token() and self.is_valid_user_agent(): parsed_path = urlparse(self.path) diff --git a/tests/web/test_web_client.py b/tests/web/test_web_client.py index d2e372be0..f813732eb 100644 --- a/tests/web/test_web_client.py +++ b/tests/web/test_web_client.py @@ -147,3 +147,33 @@ async def test_issue_560_bool_in_params_async(self): await self.async_client.conversations_list(exclude_archived=1) # ok await self.async_client.conversations_list(exclude_archived="true") # ok await self.async_client.conversations_list(exclude_archived=True) # TypeError + + def test_issue_690_oauth_v2_access(self): + self.client.token = "" + resp = self.client.oauth_v2_access(client_id="111.222", client_secret="secret", code="codeeeeeeeeee") + self.assertIsNone(resp["error"]) + with self.assertRaises(err.SlackApiError): + self.client.oauth_v2_access(client_id="999.999", client_secret="secret", code="codeeeeeeeeee") + + @async_test + async def test_issue_690_oauth_v2_access_async(self): + self.async_client.token = "" + resp = await self.async_client.oauth_v2_access(client_id="111.222", client_secret="secret", code="codeeeeeeeeee") + self.assertIsNone(resp["error"]) + with self.assertRaises(err.SlackApiError): + await self.async_client.oauth_v2_access(client_id="999.999", client_secret="secret", code="codeeeeeeeeee") + + def test_issue_690_oauth_access(self): + self.client.token = "" + resp = self.client.oauth_access(client_id="111.222", client_secret="secret", code="codeeeeeeeeee") + self.assertIsNone(resp["error"]) + with self.assertRaises(err.SlackApiError): + self.client.oauth_access(client_id="999.999", client_secret="secret", code="codeeeeeeeeee") + + @async_test + async def test_issue_690_oauth_access_async(self): + self.async_client.token = "" + resp = await self.async_client.oauth_access(client_id="111.222", client_secret="secret", code="codeeeeeeeeee") + self.assertIsNone(resp["error"]) + with self.assertRaises(err.SlackApiError): + await self.async_client.oauth_access(client_id="999.999", client_secret="secret", code="codeeeeeeeeee")