diff --git a/flytekit/clients/auth/token_client.py b/flytekit/clients/auth/token_client.py index e7e55f74a9..7cbb42a13e 100644 --- a/flytekit/clients/auth/token_client.py +++ b/flytekit/clients/auth/token_client.py @@ -3,6 +3,7 @@ import logging import time import typing +import urllib.parse from dataclasses import dataclass from datetime import datetime, timedelta @@ -57,14 +58,16 @@ def from_json_response(cls, j: typing.Dict) -> "DeviceCodeResponse": def get_basic_authorization_header(client_id: str, client_secret: str) -> str: """ This function transforms the client id and the client secret into a header that conforms with http basic auth. - It joins the id and the secret with a : then base64 encodes it, then adds the appropriate text + It joins the id and the secret with a : then base64 encodes it, then adds the appropriate text. Secrets are + first URL encoded to escape illegal characters. :param client_id: str :param client_secret: str :rtype: str """ - concated = "{}:{}".format(client_id, client_secret) - return "Basic {}".format(base64.b64encode(concated.encode(utf_8)).decode(utf_8)) + encoded = urllib.parse.quote_plus(client_secret) + concatenated = "{}:{}".format(client_id, encoded) + return "Basic {}".format(base64.b64encode(concatenated.encode(utf_8)).decode(utf_8)) def get_token( diff --git a/tests/flytekit/unit/clients/auth/test_token_client.py b/tests/flytekit/unit/clients/auth/test_token_client.py index 6e56c351bc..c22284cd38 100644 --- a/tests/flytekit/unit/clients/auth/test_token_client.py +++ b/tests/flytekit/unit/clients/auth/test_token_client.py @@ -18,6 +18,9 @@ def test_get_basic_authorization_header(): header = get_basic_authorization_header("client_id", "abc") assert header == "Basic Y2xpZW50X2lkOmFiYw==" + header = get_basic_authorization_header("client_id", "abc%%$?\\/\\/") + assert header == "Basic Y2xpZW50X2lkOmFiYyUyNSUyNSUyNCUzRiU1QyUyRiU1QyUyRg==" + @patch("flytekit.clients.auth.token_client.requests") def test_get_token(mock_requests):