diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30de936..06b2d01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adding explicit support for Python `3.12`.
- Publicly expose `requests_auth.SupportMultiAuth`, allowing multiple authentication support for every `requests` authentication class that exists.
- Publicly expose `requests_auth.TokenMemoryCache`, allowing to create custom Oauth2 token cache based on this default implementation.
+- You can now provide your own HTML success (`success_html`) and failure (`failure_html`) display via the new `OAuth2.display` shared setting. Refer to documentation for more details.
- Thanks to the new `redirect_uri_domain` parameter on Authorization code (with and without PKCE) and Implicit flows, you can now provide the [FQDN](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to use in the `redirect_uri` when `localhost` (the default) is not allowed.
- `requests_auth.WakaTimeAuthorizationCode` handling access to the [WakaTime API](https://wakatime.com/developers).
@@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `requests_auth.JsonTokenFileCache` does not expose `tokens_path` or `last_save_time` attributes anymore and is also allowing `pathlib.Path` instances as cache location.
- `requests_auth.TokenMemoryCache` does not expose `forbid_concurrent_cache_access` or `forbid_concurrent_missing_token_function_call` attributes anymore.
- Browser display settings have been moved to a shared setting, see documentation for more information on `requests_auth.OAuth2.display`.
+ The failure page will be displayed for 10 seconds by default instead of 5 seconds previously.
As a result the following classes no longer expose `success_display_time` and `failure_display_time` parameters.
- `requests_auth.OAuth2AuthorizationCode`.
- `requests_auth.OktaAuthorizationCode`.
@@ -30,6 +32,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `requests_auth.AzureActiveDirectoryImplicitIdToken`.
- `requests_auth.OktaImplicit`.
- `requests_auth.OktaImplicitIdToken`.
+- The authentication success and failure displayed in the browser were revamped to be more user-friendly. `requests_auth.testing` was modified to accommodate this change:
+ - `tab.assert_success` `expected_message` parameter was removed.
+ - `tab.assert_failure` `expected_message` parameter should not be prefixed with `Unable to properly perform authentication: ` anymore and `\n` in the message should be replaced with `
`.
### Fixed
- Type information is now provided following [PEP 561](https://www.python.org/dev/peps/pep-0561/).
diff --git a/README.md b/README.md
index a9b1881..af4e947 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
-
+
@@ -703,7 +703,9 @@ The following parameters can be provided to `DisplaySettings`:
| Name | Description | Default value |
|:-----------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------|
| `success_display_time` | In case a code or token is successfully received, this is the maximum amount of milliseconds the success page will be displayed in your browser. | 1 |
-| `failure_display_time` | In case received code or token is not valid, this is the maximum amount of milliseconds the failure page will be displayed in your browser. | 5_000 |
+| `success_html` | In case a code or token is successfully received, this is the success page that will be displayed in your browser. `{display_time}` is expected in this content. | |
+| `failure_display_time` | In case received code or token is not valid, this is the maximum amount of milliseconds the failure page will be displayed in your browser. | 10_000 |
+| `failure_html` | In case received code or token is not valid, this is the failure page that will be displayed in your browser. `{information}` and `{display_time}` are expected in this content. | |
## API key in header
@@ -911,9 +913,7 @@ def test_something(browser_mock: BrowserMock):
# perform code using authentication
- tab.assert_success(
- "You are now authenticated on 1234 You may close this tab."
- )
+ tab.assert_success()
```
## Endorsements
diff --git a/requests_auth/_oauth2/authentication_responses_server.py b/requests_auth/_oauth2/authentication_responses_server.py
index 0240d21..1a49526 100644
--- a/requests_auth/_oauth2/authentication_responses_server.py
+++ b/requests_auth/_oauth2/authentication_responses_server.py
@@ -36,7 +36,10 @@ def do_GET(self):
self.server.request_error = e
logger.exception("Unable to properly perform authentication.")
self.send_html(
- self.error_page(f"Unable to properly perform authentication: {e}")
+ OAuth2.display.failure_html.format(
+ display_time=OAuth2.display.failure_display_time,
+ information=str(e).replace("\n", "
"),
+ )
)
def do_POST(self):
@@ -48,7 +51,10 @@ def do_POST(self):
self.server.request_error = e
logger.exception("Unable to properly perform authentication.")
self.send_html(
- self.error_page(f"Unable to properly perform authentication: {e}")
+ OAuth2.display.failure_html.format(
+ display_time=OAuth2.display.failure_display_time,
+ information=str(e).replace("\n", "
"),
+ )
)
def _parse_grant(self, arguments: dict):
@@ -67,15 +73,15 @@ def _parse_grant(self, arguments: dict):
state = states[0]
self.server.grant = state, grant
self.send_html(
- self.success_page(
- f"You are now authenticated on {state}. You may close this tab."
+ OAuth2.display.success_html.format(
+ display_time=OAuth2.display.success_display_time
)
)
def _get_form(self):
content_length = int(self.headers.get("Content-Length", 0))
body_str = self.rfile.read(content_length).decode("utf-8")
- return parse_qs(body_str, keep_blank_values=1)
+ return parse_qs(body_str, keep_blank_values=True)
def _get_params(self):
return parse_qs(urlparse(self.path).query)
@@ -87,28 +93,6 @@ def send_html(self, html_content: str):
self.wfile.write(str.encode(html_content))
logger.debug("HTML content sent to client.")
- def success_page(self, text: str):
- return f"""
- {text}
- """
-
- def error_page(self, text: str):
- return f"""
- {text}
- """
-
def fragment_redirect_page(self):
"""Return a page with JS that calls back the server on the url
original url: scheme://FQDN/path#fragment
@@ -180,7 +164,7 @@ def request_new_grant(grant_details: GrantDetails) -> (str, str):
:raises InvalidGrantRequest: If the request was invalid.
:raises TimeoutOccurred: If not retrieved within timeout.
:raises GrantNotProvided: If grant is not provided in response (but no error occurred).
- :raises StateNotProvided: If state if not provided in addition to the grant.
+ :raises StateNotProvided: If state is not provided in addition to the grant.
"""
logger.debug(f"Requesting new {grant_details.name}...")
diff --git a/requests_auth/_oauth2/browser.py b/requests_auth/_oauth2/browser.py
index dba045c..2ee4c8d 100644
--- a/requests_auth/_oauth2/browser.py
+++ b/requests_auth/_oauth2/browser.py
@@ -31,22 +31,122 @@ def __init__(self, kwargs):
class DisplaySettings:
+ _default_template = """
+
+
+ {title}
+
+
+
+
+
{title}
+
{information}
+
+
+
+"""
+ _default_success = (
+ _default_template.replace("{title}", "Authentication success")
+ .replace("{color}", "#32cd32")
+ .replace("{background_color}", "#f0fff0")
+ .replace("{information}", "You can close this tab")
+ )
+ _default_failure = (
+ _default_template.replace("{title}", "Authentication failed")
+ .replace("{color}", "#dc143c")
+ .replace("{background_color}", "#fffafa")
+ )
+
def __init__(
self,
*,
success_display_time: int = 1,
- failure_display_time: int = 5_000,
+ success_html: str = None,
+ failure_display_time: int = 10_000,
+ failure_html: str = None,
):
"""
:param success_display_time: In case a code/token is successfully received,
this is the maximum amount of milliseconds the success page will be displayed in your browser.
Display the page for 1 millisecond by default.
+ :param success_html: In case a code or token is successfully received,
+ this is the success page that will be displayed in your browser.
+ `{display_time}` is expected in this content.
:param failure_display_time: In case received code/token is not valid,
this is the maximum amount of milliseconds the failure page will be displayed in your browser.
- Display the page for 5 seconds by default.
+ Display the page for 10 seconds by default.
+ :param failure_html: In case received code or token is not valid,
+ this is the failure page that will be displayed in your browser.
+ `{information}` and `{display_time}` are expected in this content.
"""
# Time is expressed in milliseconds
self.success_display_time = success_display_time
+ self.success_html = success_html or self._default_success
# Time is expressed in milliseconds
self.failure_display_time = failure_display_time
+ self.failure_html = failure_html or self._default_failure
diff --git a/requests_auth/testing.py b/requests_auth/testing.py
index 1e8fe1e..ce70470 100644
--- a/requests_auth/testing.py
+++ b/requests_auth/testing.py
@@ -34,10 +34,177 @@ class Tab(threading.Thread):
* assert the content sent to the browser
"""
- def __init__(self, reply_url: str, data: str):
+ def __init__(
+ self,
+ reply_url: str,
+ data: str,
+ displayed_html: Optional[str] = None,
+ ):
self.reply_url = reply_url
self.data = data.encode() if data is not None else None
self.checked = False
+ self.success_html = (
+ displayed_html
+ or """
+
+
+ Authentication success
+
+
+
+
+
Authentication success
+
You can close this tab
+
+
+
+"""
+ )
+ self.failure_html = (
+ displayed_html
+ or """
+
+
+ Authentication failed
+
+
+
+
+
Authentication failed
+
{information}
+
+
+
+"""
+ )
super().__init__()
def run(self) -> None:
@@ -50,7 +217,7 @@ def run(self) -> None:
# Simulate a browser tab token redirect to the reply URL
self.content = self._simulate_redirect().decode()
- def _request_favicon(self):
+ def _request_favicon(self) -> None:
scheme, netloc, *_ = urlsplit(self.reply_url)
favicon_response = urllib.request.urlopen(f"{scheme}://{netloc}/favicon.ico")
assert favicon_response.read() == b"Favicon is not provided."
@@ -76,19 +243,15 @@ def _simulate_requests_auth_redirect(self) -> bytes:
)
return urllib.request.urlopen(reply_url, data=self.data).read()
- def assert_success(self, expected_message: str, timeout: int = 1):
+ def assert_success(self, timeout: int = 1) -> None:
self.join()
- assert (
- self.content
- == f"\n {expected_message}
\n "
- )
+ assert self.content == self.success_html.format(display_time=timeout)
self.checked = True
- def assert_failure(self, expected_message: str, timeout: int = 5000):
+ def assert_failure(self, expected_message: str, timeout: int = 10_000) -> None:
self.join()
- assert (
- self.content
- == f"\n {expected_message}
\n "
+ assert self.content == self.failure_html.format(
+ display_time=timeout, information=expected_message
)
self.checked = True
@@ -97,7 +260,7 @@ class BrowserMock:
def __init__(self):
self.tabs: Dict[str, Tab] = {}
- def open(self, url: str, new: int):
+ def open(self, url: str, new: int) -> bool:
assert new == 1
assert url in self.tabs, f"Browser call on {url} was not mocked."
# Simulate a browser by sending the response in another thread
@@ -105,18 +268,23 @@ def open(self, url: str, new: int):
return True
def add_response(
- self, opened_url: str, reply_url: Optional[str], data: str = None
+ self,
+ opened_url: str,
+ reply_url: Optional[str],
+ data: Optional[str] = None,
+ displayed_html: Optional[str] = None,
) -> Tab:
"""
:param opened_url: URL opened by requests_auth
:param reply_url: The URL to send a response to, None to simulate the fact that there is no redirect.
:param data: Body of the POST response to be sent. None to send a GET request.
+ :param displayed_html: Expected success/failure page.
"""
- tab = Tab(reply_url, data)
+ tab = Tab(reply_url, data, displayed_html)
self.tabs[opened_url] = tab
return tab
- def assert_checked(self):
+ def assert_checked(self) -> None:
for url, tab in self.tabs.items():
tab.join()
assert tab.checked, f"Response received on {url} was not checked properly."
diff --git a/tests/features/multi_auth/test_add_operator.py b/tests/features/multi_auth/test_add_operator.py
index 9605b8f..8a4f6bc 100644
--- a/tests/features/multi_auth/test_add_operator.py
+++ b/tests/features/multi_auth/test_add_operator.py
@@ -360,9 +360,7 @@ def test_oauth2_authorization_code_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_and_multiple_authentication_can_be_combined(
@@ -406,9 +404,7 @@ def test_oauth2_authorization_code_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_and_api_key_authentication_can_be_combined(
@@ -451,9 +447,7 @@ def test_oauth2_pkce_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_and_multiple_authentication_can_be_combined(
@@ -500,9 +494,7 @@ def test_oauth2_pkce_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_and_api_key_authentication_can_be_combined(
@@ -535,9 +527,7 @@ def test_oauth2_implicit_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_and_multiple_authentication_can_be_combined(
@@ -574,6 +564,4 @@ def test_oauth2_implicit_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
diff --git a/tests/features/multi_auth/test_and_operator.py b/tests/features/multi_auth/test_and_operator.py
index b08a78d..4abe2af 100644
--- a/tests/features/multi_auth/test_and_operator.py
+++ b/tests/features/multi_auth/test_and_operator.py
@@ -360,9 +360,7 @@ def test_oauth2_authorization_code_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_and_multiple_authentication_can_be_combined(
@@ -406,9 +404,7 @@ def test_oauth2_authorization_code_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_and_api_key_authentication_can_be_combined(
@@ -451,9 +447,7 @@ def test_oauth2_pkce_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_and_multiple_authentication_can_be_combined(
@@ -500,9 +494,7 @@ def test_oauth2_pkce_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_and_api_key_authentication_can_be_combined(
@@ -535,9 +527,7 @@ def test_oauth2_implicit_and_api_key_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_and_multiple_authentication_can_be_combined(
@@ -574,6 +564,4 @@ def test_oauth2_implicit_and_multiple_authentication_can_be_combined(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
diff --git a/tests/oauth2/authorization_code/test_oauth2_authorization_code.py b/tests/oauth2/authorization_code/test_oauth2_authorization_code.py
index f54e962..60012d6 100644
--- a/tests/oauth2/authorization_code/test_oauth2_authorization_code.py
+++ b/tests/oauth2/authorization_code/test_oauth2_authorization_code.py
@@ -47,9 +47,7 @@ def test_oauth2_authorization_code_flow_uses_provided_session(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
@@ -91,8 +89,73 @@ def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, browser_mock: BrowserMock
+):
+ auth = requests_auth.OAuth2AuthorizationCode(
+ "http://provide_code",
+ "http://provide_access_token",
+ )
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ tab = browser_mock.add_response(
+ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de",
+ displayed_html="SUCCESS: {display_time}
",
+ )
+ responses.post(
+ "http://provide_access_token",
+ json={
+ "access_token": "2YotnFZFEjr1zCsicMWpAA",
+ "token_type": "example",
+ "expires_in": 3600,
+ "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
+ "example_parameter": "example_value",
+ },
+ match=[
+ urlencoded_params_matcher(
+ {
+ "grant_type": "authorization_code",
+ "redirect_uri": "http://localhost:5000/",
+ "response_type": "code",
+ "code": "SplxlOBeZQQYbYS6WxSbIA",
+ }
+ ),
+ ],
+ )
+ responses.get(
+ "http://authorized_only",
+ match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})],
+ )
+
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_failure(
+ token_cache, browser_mock: BrowserMock
+):
+ auth = requests_auth.OAuth2AuthorizationCode(
+ "http://provide_code",
+ "http://provide_access_token",
+ )
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -133,9 +196,7 @@ def test_oauth2_authorization_code_flow_get_code_is_sent_in_authorization_header
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_token_is_expired_after_30_seconds_by_default(
@@ -182,9 +243,7 @@ def test_oauth2_authorization_code_flow_token_is_expired_after_30_seconds_by_def
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_client_credentials_flow_token_custom_expiry(
@@ -244,9 +303,7 @@ def test_refresh_token(token_cache, responses: RequestsMock, browser_mock: Brows
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
@@ -313,9 +370,7 @@ def test_refresh_token_invalid(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
"http://provide_access_token",
@@ -346,9 +401,7 @@ def test_refresh_token_invalid(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_refresh_token_access_token_not_expired(
@@ -388,9 +441,7 @@ def test_refresh_token_access_token_not_expired(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# expect Bearer token to remain the same
responses.get(
@@ -427,9 +478,7 @@ def test_empty_token_is_invalid(
str(exception_info.value)
== "access_token not provided within {'access_token': '', 'token_type': 'example', 'expires_in': 3600, 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA', 'example_parameter': 'example_value'}."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_no_json(
@@ -446,9 +495,7 @@ def test_with_invalid_grant_request_no_json(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "failure"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error(
@@ -475,9 +522,7 @@ def test_with_invalid_grant_request_invalid_request_error(
"includes multiple credentials, utilizes more than one mechanism for "
"authenticating the client, or is otherwise malformed."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description(
@@ -498,9 +543,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc of the error"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri(
@@ -528,9 +571,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url"
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri_and_other_fields(
@@ -559,9 +600,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== "invalid_request: desc of the error\nMore information can be found on http://test_url\nAdditional information: {'other': 'other info'}"
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_without_error(
@@ -582,9 +621,7 @@ def test_with_invalid_grant_request_without_error(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "{'other': 'other info'}"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_client_error(
@@ -615,9 +652,7 @@ def test_with_invalid_grant_request_invalid_client_error(
'code and include the "WWW-Authenticate" response header field matching the '
"authentication scheme used by the client."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_grant_error(
@@ -644,9 +679,7 @@ def test_with_invalid_grant_request_invalid_grant_error(
"does not match the redirection URI used in the authorization request, or was "
"issued to another client."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unauthorized_client_error(
@@ -671,9 +704,7 @@ def test_with_invalid_grant_request_unauthorized_client_error(
== "unauthorized_client: The authenticated client is not authorized to use this "
"authorization grant type."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unsupported_grant_type_error(
@@ -698,9 +729,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error(
== "unsupported_grant_type: The authorization grant type is not supported by the "
"authorization server."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_scope_error(
@@ -725,9 +754,7 @@ def test_with_invalid_grant_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, malformed, or "
"exceeds the scope granted by the resource owner."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_token_request_invalid_request_error(
@@ -747,7 +774,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -764,9 +791,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc"
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -786,7 +811,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url"
+ "invalid_request: desc
More information can be found on http://test_url"
)
@@ -807,7 +832,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on http://test_url
Additional information: {'other': ['test']}"
)
@@ -828,7 +853,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -849,7 +874,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -870,7 +895,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -891,7 +916,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -912,7 +937,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -933,7 +958,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -974,9 +999,7 @@ def test_nonce_is_sent_if_provided_in_authorization_url(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_response_type_can_be_provided_in_url(
@@ -1017,9 +1040,7 @@ def test_response_type_can_be_provided_in_url(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 49b67a19e70f692c3fc09dd124e5782b41a86f4f4931e1cc938ccbb466eecf1b730edb9eb01e42005de77ce3dd5a016418f8e780f30c4477d71102fe03e39e62. You may close this tab."
- )
+ tab.assert_success()
def test_authorization_url_is_mandatory():
diff --git a/tests/oauth2/authorization_code/test_oauth2_authorization_code_okta.py b/tests/oauth2/authorization_code/test_oauth2_authorization_code_okta.py
index 073b289..2b24009 100644
--- a/tests/oauth2/authorization_code/test_oauth2_authorization_code_okta.py
+++ b/tests/oauth2/authorization_code/test_oauth2_authorization_code_okta.py
@@ -51,9 +51,7 @@ def test_oauth2_authorization_code_flow_uses_provided_session(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
@@ -97,8 +95,75 @@ def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, browser_mock: BrowserMock
+):
+ auth = requests_auth.OktaAuthorizationCode(
+ "testserver.okta-emea.com",
+ "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ )
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ tab = browser_mock.add_response(
+ opened_url="https://testserver.okta-emea.com/oauth2/default/v1/authorize?client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b",
+ displayed_html="SUCCESS: {display_time}
",
+ )
+ responses.post(
+ "https://testserver.okta-emea.com/oauth2/default/v1/token",
+ json={
+ "access_token": "2YotnFZFEjr1zCsicMWpAA",
+ "token_type": "example",
+ "expires_in": 3600,
+ "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
+ "example_parameter": "example_value",
+ },
+ match=[
+ urlencoded_params_matcher(
+ {
+ "grant_type": "authorization_code",
+ "redirect_uri": "http://localhost:5000/",
+ "client_id": "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ "scope": "openid",
+ "response_type": "code",
+ "code": "SplxlOBeZQQYbYS6WxSbIA",
+ }
+ ),
+ ],
+ )
+ responses.get(
+ "http://authorized_only",
+ match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})],
+ )
+
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_failure(
+ token_cache, browser_mock: BrowserMock
+):
+ auth = requests_auth.OktaAuthorizationCode(
+ "testserver.okta-emea.com",
+ "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ )
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="https://testserver.okta-emea.com/oauth2/default/v1/authorize?client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -141,9 +206,7 @@ def test_okta_authorization_code_flow_get_code_is_sent_in_authorization_header_b
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_okta_authorization_code_flow_token_is_expired_after_30_seconds_by_default(
@@ -192,9 +255,7 @@ def test_okta_authorization_code_flow_token_is_expired_after_30_seconds_by_defau
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_okta_authorization_code_flow_token_custom_expiry(
@@ -245,9 +306,7 @@ def test_empty_token_is_invalid(
str(exception_info.value)
== "access_token not provided within {'access_token': '', 'token_type': 'example', 'expires_in': 3600, 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA', 'example_parameter': 'example_value'}."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_no_json(
@@ -268,9 +327,7 @@ def test_with_invalid_grant_request_no_json(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "failure"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error(
@@ -297,9 +354,7 @@ def test_with_invalid_grant_request_invalid_request_error(
"includes multiple credentials, utilizes more than one mechanism for "
"authenticating the client, or is otherwise malformed."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description(
@@ -320,9 +375,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc of the error"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri(
@@ -350,9 +403,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url"
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri_and_other_fields(
@@ -381,9 +432,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== "invalid_request: desc of the error\nMore information can be found on http://test_url\nAdditional information: {'other': 'other info'}"
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_without_error(
@@ -404,9 +453,7 @@ def test_with_invalid_grant_request_without_error(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "{'other': 'other info'}"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_client_error(
@@ -437,9 +484,7 @@ def test_with_invalid_grant_request_invalid_client_error(
'code and include the "WWW-Authenticate" response header field matching the '
"authentication scheme used by the client."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_grant_error(
@@ -466,9 +511,7 @@ def test_with_invalid_grant_request_invalid_grant_error(
"does not match the redirection URI used in the authorization request, or was "
"issued to another client."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unauthorized_client_error(
@@ -493,9 +536,7 @@ def test_with_invalid_grant_request_unauthorized_client_error(
== "unauthorized_client: The authenticated client is not authorized to use this "
"authorization grant type."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unsupported_grant_type_error(
@@ -520,9 +561,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error(
== "unsupported_grant_type: The authorization grant type is not supported by the "
"authorization server."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_scope_error(
@@ -547,9 +586,7 @@ def test_with_invalid_grant_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, malformed, or "
"exceeds the scope granted by the resource owner."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_token_request_invalid_request_error(
@@ -569,7 +606,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -586,9 +623,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc"
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -608,7 +643,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url"
+ "invalid_request: desc
More information can be found on http://test_url"
)
@@ -629,7 +664,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on http://test_url
Additional information: {'other': ['test']}"
)
@@ -650,7 +685,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -671,7 +706,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -692,7 +727,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -713,7 +748,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -734,7 +769,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -755,7 +790,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
diff --git a/tests/oauth2/authorization_code/test_oauth2_authorization_code_wakatime.py b/tests/oauth2/authorization_code/test_oauth2_authorization_code_wakatime.py
index c134764..4f78cbe 100644
--- a/tests/oauth2/authorization_code/test_oauth2_authorization_code_wakatime.py
+++ b/tests/oauth2/authorization_code/test_oauth2_authorization_code_wakatime.py
@@ -49,9 +49,7 @@ def test_oauth2_authorization_code_flow_uses_provided_client(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
@@ -92,8 +90,73 @@ def test_oauth2_authorization_code_flow_uses_redirect_uri_domain(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, browser_mock: BrowserMock
+):
+ auth = requests_auth.WakaTimeAuthorizationCode(
+ "jPJQV0op6Pu3b66MWDi8b1wD",
+ "waka_sec_0c4MBGeR9LN74LzV5uelF9SgeQ32CqfeWpIuieneBbsL57dAAlqqJWDiVDJOlsSx61pVwHMKlsb3uMvU",
+ scope="email",
+ )
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ tab = browser_mock.add_response(
+ opened_url="https://wakatime.com/oauth/authorize?client_id=jPJQV0op6Pu3b66MWDi8b1wD&client_secret=waka_sec_0c4MBGeR9LN74LzV5uelF9SgeQ32CqfeWpIuieneBbsL57dAAlqqJWDiVDJOlsSx61pVwHMKlsb3uMvU&scope=email&response_type=code&state=5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a",
+ displayed_html="SUCCESS: {display_time}
",
+ )
+ responses.post(
+ "https://wakatime.com/oauth/token",
+ body="access_token=waka_tok_12345&token_type=bearer&expires_in=3600&refresh_token=waka_ref_12345&scope=email&example_parameter=example_value",
+ content_type="text/html; charset=utf-8",
+ match=[
+ urlencoded_params_matcher(
+ {
+ "grant_type": "authorization_code",
+ "redirect_uri": "http://localhost:5000/",
+ "client_id": "jPJQV0op6Pu3b66MWDi8b1wD",
+ "client_secret": "waka_sec_0c4MBGeR9LN74LzV5uelF9SgeQ32CqfeWpIuieneBbsL57dAAlqqJWDiVDJOlsSx61pVwHMKlsb3uMvU",
+ "scope": "email",
+ "response_type": "code",
+ "code": "SplxlOBeZQQYbYS6WxSbIA",
+ }
+ )
+ ],
+ )
+ responses.get(
+ "https://authorized_only",
+ match=[header_matcher({"Authorization": "Bearer waka_tok_12345"})],
+ )
+
+ requests.get("https://authorized_only", auth=auth)
+
+ tab.assert_success()
+
+
+def test_oauth2_authorization_code_flow_uses_custom_failure(
+ token_cache, browser_mock: BrowserMock
+):
+ auth = requests_auth.WakaTimeAuthorizationCode(
+ "jPJQV0op6Pu3b66MWDi8b1wD",
+ "waka_sec_0c4MBGeR9LN74LzV5uelF9SgeQ32CqfeWpIuieneBbsL57dAAlqqJWDiVDJOlsSx61pVwHMKlsb3uMvU",
+ scope="email",
+ )
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="https://wakatime.com/oauth/authorize?client_id=jPJQV0op6Pu3b66MWDi8b1wD&client_secret=waka_sec_0c4MBGeR9LN74LzV5uelF9SgeQ32CqfeWpIuieneBbsL57dAAlqqJWDiVDJOlsSx61pVwHMKlsb3uMvU&scope=email&response_type=code&state=5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -134,9 +197,7 @@ def test_multiple_scopes_are_comma_separated(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 34f21f9ea8be7b1dfd3dd1673a9aea7c3a1737228b4f08bc11ebacb88449afaa658811f8022e9962927a0ec42805c0e3cc5e6b0d9185308216b298a686001a1f. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_get_code_is_sent_in_authorization_header_by_default(
@@ -176,9 +237,7 @@ def test_oauth2_authorization_code_flow_get_code_is_sent_in_authorization_header
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_json_response_is_handled_even_if_unused(
@@ -224,9 +283,7 @@ def test_json_response_is_handled_even_if_unused(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_get_code_is_expired_after_30_seconds_by_default(
@@ -273,9 +330,7 @@ def test_oauth2_authorization_code_flow_get_code_is_expired_after_30_seconds_by_
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_get_code_custom_expiry(
@@ -338,9 +393,7 @@ def test_oauth2_authorization_code_flow_refresh_token(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
@@ -405,9 +458,7 @@ def test_oauth2_authorization_code_flow_refresh_token_invalid(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
@@ -442,9 +493,7 @@ def test_oauth2_authorization_code_flow_refresh_token_invalid(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_authorization_code_flow_refresh_token_access_token_not_expired(
@@ -484,9 +533,7 @@ def test_oauth2_authorization_code_flow_refresh_token_access_token_not_expired(
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
# expect Bearer token to remain the same
requests.get("https://authorized_only", auth=auth)
@@ -530,9 +577,7 @@ def test_empty_token_is_invalid(
str(exception_info.value)
== "access_token not provided within {'access_token': '', 'token_type': 'bearer', 'expires_in': '3600', 'refresh_token': 'waka_ref_12345', 'scope': 'email', 'example_parameter': 'example_value'}."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_no_json(
@@ -557,9 +602,7 @@ def test_with_invalid_grant_request_no_json(
with pytest.raises(requests_auth.InvalidGrantRequest, match="failure"):
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error(
@@ -590,9 +633,7 @@ def test_with_invalid_grant_request_invalid_request_error(
"includes multiple credentials, utilizes more than one mechanism for "
"authenticating the client, or is otherwise malformed."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description(
@@ -617,9 +658,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description(
requests.get("https://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc of the error"
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri(
@@ -651,9 +690,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on https://test_url"
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri_and_other_fields(
@@ -686,9 +723,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== "invalid_request: desc of the error\nMore information can be found on https://test_url\nAdditional information: {'other': 'other info'}"
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_without_error(
@@ -714,9 +749,7 @@ def test_with_invalid_grant_request_without_error(
):
requests.get("https://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_client_error(
@@ -751,9 +784,7 @@ def test_with_invalid_grant_request_invalid_client_error(
'code and include the "WWW-Authenticate" response header field matching the '
"authentication scheme used by the client."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_grant_error(
@@ -784,9 +815,7 @@ def test_with_invalid_grant_request_invalid_grant_error(
"does not match the redirection URI used in the authorization request, or was "
"issued to another client."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unauthorized_client_error(
@@ -815,9 +844,7 @@ def test_with_invalid_grant_request_unauthorized_client_error(
== "unauthorized_client: The authenticated client is not authorized to use this "
"authorization grant type."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unsupported_grant_type_error(
@@ -846,9 +873,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error(
== "unsupported_grant_type: The authorization grant type is not supported by the "
"authorization server."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_scope_error(
@@ -877,9 +902,7 @@ def test_with_invalid_grant_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, malformed, or "
"exceeds the scope granted by the resource owner."
)
- tab.assert_success(
- "You are now authenticated on 5d0adb208bdbecaf5cfb6de0bf4ba0aea52986f3fc5ea7bc30c4b2db449c17e5c9d15f9a3926476cdaf1c72e9f73c7cfdc624dde0187c38d8c6b04532770df2a. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_token_request_invalid_request_error(
@@ -903,7 +926,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -925,9 +948,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
):
requests.get("https://authorized_only", auth=auth)
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -951,7 +972,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on https://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on https://test_url"
+ "invalid_request: desc
More information can be found on https://test_url"
)
@@ -976,7 +997,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on https://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on https://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on https://test_url
Additional information: {'other': ['test']}"
)
@@ -1001,7 +1022,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -1026,7 +1047,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -1051,7 +1072,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -1076,7 +1097,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -1101,7 +1122,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -1126,7 +1147,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
diff --git a/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce.py b/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce.py
index cf5a23b..7bfb9f2 100644
--- a/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce.py
+++ b/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce.py
@@ -52,9 +52,7 @@ def test_oauth2_pkce_flow_uses_provided_session(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_flow_uses_redirect_uri_domain(
@@ -100,8 +98,80 @@ def test_oauth2_pkce_flow_uses_redirect_uri_domain(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_pkce_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock
+):
+ monkeypatch.setattr(
+ requests_auth._oauth2.authorization_code_pkce.os, "urandom", lambda x: b"1" * 63
+ )
+ auth = requests_auth.OAuth2AuthorizationCodePKCE(
+ "http://provide_code",
+ "http://provide_access_token",
+ )
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ tab = browser_mock.add_response(
+ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256",
+ reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de",
+ displayed_html="SUCCESS: {display_time}
",
+ )
+ responses.post(
+ "http://provide_access_token",
+ json={
+ "access_token": "2YotnFZFEjr1zCsicMWpAA",
+ "token_type": "example",
+ "expires_in": 3600,
+ "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
+ "example_parameter": "example_value",
+ },
+ match=[
+ urlencoded_params_matcher(
+ {
+ "code_verifier": "MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx",
+ "grant_type": "authorization_code",
+ "redirect_uri": "http://localhost:5000/",
+ "response_type": "code",
+ "code": "SplxlOBeZQQYbYS6WxSbIA",
+ }
+ ),
+ ],
+ )
+ responses.get(
+ "http://authorized_only",
+ match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})],
+ )
+
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_success()
+
+
+def test_oauth2_pkce_flow_uses_custom_failure(
+ token_cache, monkeypatch, browser_mock: BrowserMock
+):
+ monkeypatch.setattr(
+ requests_auth._oauth2.authorization_code_pkce.os, "urandom", lambda x: b"1" * 63
+ )
+ auth = requests_auth.OAuth2AuthorizationCodePKCE(
+ "http://provide_code",
+ "http://provide_access_token",
+ )
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -146,9 +216,7 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_flow_token_is_expired_after_30_seconds_by_default(
@@ -199,9 +267,7 @@ def test_oauth2_pkce_flow_token_is_expired_after_30_seconds_by_default(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_client_credentials_flow_token_custom_expiry(
@@ -270,9 +336,7 @@ def test_expires_in_sent_as_str(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_refresh_token(
@@ -316,9 +380,7 @@ def test_refresh_token(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
"http://provide_access_token",
@@ -388,9 +450,7 @@ def test_refresh_token_invalid(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# response for refresh token grant
responses.post(
"http://provide_access_token",
@@ -421,9 +481,7 @@ def test_refresh_token_invalid(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_refresh_token_access_token_not_expired(
@@ -467,9 +525,7 @@ def test_refresh_token_access_token_not_expired(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
# expect Bearer token to remain the same
response = requests.get("http://authorized_only", auth=auth)
@@ -519,9 +575,7 @@ def test_nonce_is_sent_if_provided_in_authorization_url(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_no_json(
@@ -541,9 +595,7 @@ def test_with_invalid_grant_request_no_json(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "failure"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error(
@@ -573,9 +625,7 @@ def test_with_invalid_grant_request_invalid_request_error(
"includes multiple credentials, utilizes more than one mechanism for "
"authenticating the client, or is otherwise malformed."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description(
@@ -599,9 +649,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc of the error"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri(
@@ -632,9 +680,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url"
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri_and_other_fields(
@@ -666,9 +712,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url\nAdditional information: {{'other': 'other info'}}"
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_without_error(
@@ -692,9 +736,7 @@ def test_with_invalid_grant_request_without_error(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "{'other': 'other info'}"
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_client_error(
@@ -728,9 +770,7 @@ def test_with_invalid_grant_request_invalid_client_error(
'code and include the "WWW-Authenticate" response header field matching the '
"authentication scheme used by the client."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_grant_error(
@@ -760,9 +800,7 @@ def test_with_invalid_grant_request_invalid_grant_error(
"does not match the redirection URI used in the authorization request, or was "
"issued to another client."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unauthorized_client_error(
@@ -790,9 +828,7 @@ def test_with_invalid_grant_request_unauthorized_client_error(
== "unauthorized_client: The authenticated client is not authorized to use this "
"authorization grant type."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unsupported_grant_type_error(
@@ -820,9 +856,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error(
== "unsupported_grant_type: The authorization grant type is not supported by the "
"authorization server."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_scope_error(
@@ -850,9 +884,7 @@ def test_with_invalid_grant_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, malformed, or "
"exceeds the scope granted by the resource owner."
)
- tab.assert_success(
- "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_token_request_invalid_request_error(
@@ -875,7 +907,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -895,9 +927,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc"
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -920,7 +950,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url"
+ "invalid_request: desc
More information can be found on http://test_url"
)
@@ -944,7 +974,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on http://test_url
Additional information: {'other': ['test']}"
)
@@ -968,7 +998,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -992,7 +1022,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -1016,7 +1046,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -1040,7 +1070,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -1064,7 +1094,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -1088,7 +1118,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -1135,9 +1165,7 @@ def test_response_type_can_be_provided_in_url(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on b32e05720bd3722e0ac87bf72897a78b669a0810adf8da46b675793dcfe0f41a40f7d7fdda952bd73ea533a2462907d805adf8c1a162d51b99b2ddec0d411feb. You may close this tab."
- )
+ tab.assert_success()
def test_authorization_url_is_mandatory():
diff --git a/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce_okta.py b/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce_okta.py
index 1eb8eb3..e3e8634 100644
--- a/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce_okta.py
+++ b/tests/oauth2/authorization_code_pkce/test_oauth2_authorization_code_pkce_okta.py
@@ -56,9 +56,7 @@ def test_oauth2_pkce_flow_uses_provided_session(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_pkce_flow_uses_redirect_uri_domain(
@@ -106,8 +104,82 @@ def test_oauth2_pkce_flow_uses_redirect_uri_domain(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_pkce_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock
+):
+ monkeypatch.setattr(
+ requests_auth._oauth2.authorization_code_pkce.os, "urandom", lambda x: b"1" * 63
+ )
+ auth = requests_auth.OktaAuthorizationCodePKCE(
+ "testserver.okta-emea.com",
+ "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ )
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ tab = browser_mock.add_response(
+ opened_url="https://testserver.okta-emea.com/oauth2/default/v1/authorize?client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256",
+ reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b",
+ displayed_html="SUCCESS: {display_time}
",
+ )
+ responses.post(
+ "https://testserver.okta-emea.com/oauth2/default/v1/token",
+ json={
+ "access_token": "2YotnFZFEjr1zCsicMWpAA",
+ "token_type": "example",
+ "expires_in": 3600,
+ "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
+ "example_parameter": "example_value",
+ },
+ match=[
+ urlencoded_params_matcher(
+ {
+ "code_verifier": "MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx",
+ "grant_type": "authorization_code",
+ "redirect_uri": "http://localhost:5000/",
+ "client_id": "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ "scope": "openid",
+ "response_type": "code",
+ "code": "SplxlOBeZQQYbYS6WxSbIA",
+ }
+ ),
+ ],
+ )
+ responses.get(
+ "http://authorized_only",
+ match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})],
+ )
+
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_success()
+
+
+def test_oauth2_pkce_flow_uses_custom_failure(
+ token_cache, monkeypatch, browser_mock: BrowserMock
+):
+ monkeypatch.setattr(
+ requests_auth._oauth2.authorization_code_pkce.os, "urandom", lambda x: b"1" * 63
+ )
+ auth = requests_auth.OktaAuthorizationCodePKCE(
+ "testserver.okta-emea.com",
+ "54239d18-c68c-4c47-8bdd-ce71ea1d50cd",
+ )
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="https://testserver.okta-emea.com/oauth2/default/v1/authorize?client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -154,9 +226,7 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_okta_pkce_flow_token_is_expired_after_30_seconds_by_default(
@@ -209,9 +279,7 @@ def test_okta_pkce_flow_token_is_expired_after_30_seconds_by_default(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_okta_pkce_flow_token_custom_expiry(
@@ -282,9 +350,7 @@ def test_expires_in_sent_as_str(
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_no_json(
@@ -308,9 +374,7 @@ def test_with_invalid_grant_request_no_json(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "failure"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error(
@@ -340,9 +404,7 @@ def test_with_invalid_grant_request_invalid_request_error(
"includes multiple credentials, utilizes more than one mechanism for "
"authenticating the client, or is otherwise malformed."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description(
@@ -366,9 +428,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc of the error"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri(
@@ -399,9 +459,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url"
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_request_error_and_error_description_and_uri_and_other_fields(
@@ -433,9 +491,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_
str(exception_info.value)
== f"invalid_request: desc of the error\nMore information can be found on http://test_url\nAdditional information: {{'other': 'other info'}}"
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_without_error(
@@ -459,9 +515,7 @@ def test_with_invalid_grant_request_without_error(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "{'other': 'other info'}"
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_client_error(
@@ -495,9 +549,7 @@ def test_with_invalid_grant_request_invalid_client_error(
'code and include the "WWW-Authenticate" response header field matching the '
"authentication scheme used by the client."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_grant_error(
@@ -527,9 +579,7 @@ def test_with_invalid_grant_request_invalid_grant_error(
"does not match the redirection URI used in the authorization request, or was "
"issued to another client."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unauthorized_client_error(
@@ -557,9 +607,7 @@ def test_with_invalid_grant_request_unauthorized_client_error(
== "unauthorized_client: The authenticated client is not authorized to use this "
"authorization grant type."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_unsupported_grant_type_error(
@@ -587,9 +635,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error(
== "unsupported_grant_type: The authorization grant type is not supported by the "
"authorization server."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_grant_request_invalid_scope_error(
@@ -617,9 +663,7 @@ def test_with_invalid_grant_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, malformed, or "
"exceeds the scope granted by the resource owner."
)
- tab.assert_success(
- "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab."
- )
+ tab.assert_success()
def test_with_invalid_token_request_invalid_request_error(
@@ -642,7 +686,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -662,9 +706,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info:
requests.get("http://authorized_only", auth=auth)
assert str(exception_info.value) == "invalid_request: desc"
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -687,7 +729,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url"
+ "invalid_request: desc
More information can be found on http://test_url"
)
@@ -711,7 +753,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on http://test_url
Additional information: {'other': ['test']}"
)
@@ -735,7 +777,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -759,7 +801,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -783,7 +825,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -807,7 +849,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -831,7 +873,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -855,7 +897,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
diff --git a/tests/oauth2/implicit/test_oauth2_implicit.py b/tests/oauth2/implicit/test_oauth2_implicit.py
index a19e619..abc23b3 100644
--- a/tests/oauth2/implicit/test_oauth2_implicit.py
+++ b/tests/oauth2/implicit/test_oauth2_implicit.py
@@ -72,12 +72,8 @@ def test_oauth2_implicit_flow_token_is_not_reused_if_a_url_parameter_is_changing
requests.get("http://authorized_only", auth=auth2)
- tab1.assert_success(
- "You are now authenticated on 5652a8138e3a99dab7b94532c73ed5b10f19405316035d1efdc8bf7e0713690485254c2eaff912040eac44031889ef0a5ed5730c8a111541120d64a898c31afe. You may close this tab."
- )
- tab2.assert_success(
- "You are now authenticated on 5c3940ccf78ac6e7d6d8d06782d9fd95a533aa5425b616eaa38dc3ec9508fbd55152c58a0d8dd8a087e76b77902559285819a41cb78ce8713e5a3b974bf07ce9. You may close this tab."
- )
+ tab1.assert_success()
+ tab2.assert_success()
def test_oauth2_implicit_flow_token_is_reused_if_only_nonce_differs(
@@ -113,9 +109,7 @@ def test_oauth2_implicit_flow_token_is_reused_if_only_nonce_differs(
)
requests.get("http://authorized_only", auth=auth2)
- tab.assert_success(
- "You are now authenticated on 67b95d2c7555751d1d72c97c7cd9ad6630c8395e0eaa51ee86ac7e451211ded9cd98a7190848789fe93632d8960425710e93f1f5549c6c6bc328bf3865a85ff2. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_token_can_be_requested_on_a_custom_server_port(
@@ -141,9 +135,7 @@ def test_oauth2_implicit_flow_token_can_be_requested_on_a_custom_server_port(
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_uses_redirect_uri_domain(
@@ -167,8 +159,51 @@ def test_oauth2_implicit_flow_uses_redirect_uri_domain(
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
+ tab.assert_success()
+
+
+def test_oauth2_implicit_flow_uses_custom_success(
+ token_cache, responses: RequestsMock, browser_mock: BrowserMock
+):
+ auth = requests_auth.OAuth2Implicit("http://provide_token")
+ requests_auth.OAuth2.display.success_html = (
+ "SUCCESS: {display_time}
"
+ )
+ expiry_in_1_hour = datetime.datetime.now(
+ datetime.timezone.utc
+ ) + datetime.timedelta(hours=1)
+ token = create_token(expiry_in_1_hour)
+ tab = browser_mock.add_response(
+ opened_url="http://provide_token?response_type=token&state=42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000",
+ displayed_html="SUCCESS: {display_time}
",
+ data=f"access_token={token}&state=42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521",
+ )
+ responses.get(
+ "http://authorized_only",
+ match=[header_matcher({"Authorization": f"Bearer {token}"})],
+ )
+
+ requests.get("http://authorized_only", auth=auth)
+ tab.assert_success()
+
+
+def test_oauth2_implicit_flow_uses_custom_failure(
+ token_cache, browser_mock: BrowserMock
+):
+ auth = requests_auth.OAuth2Implicit("http://provide_token")
+ requests_auth.OAuth2.display.failure_html = "FAILURE: {display_time}\n{information}"
+ tab = browser_mock.add_response(
+ opened_url="http://provide_token?response_type=token&state=42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F",
+ reply_url="http://localhost:5000#error=invalid_request",
+ displayed_html="FAILURE: {display_time}\n{information}",
+ )
+
+ with pytest.raises(requests_auth.InvalidGrantRequest):
+ requests.get("http://authorized_only", auth=auth)
+
+ tab.assert_failure(
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -191,9 +226,7 @@ def test_oauth2_implicit_flow_post_token_is_sent_in_authorization_header_by_defa
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_token_is_expired_after_30_seconds_by_default(
@@ -225,9 +258,7 @@ def test_oauth2_implicit_flow_token_is_expired_after_30_seconds_by_default(
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_token_custom_expiry(
@@ -325,7 +356,7 @@ def test_state_change(token_cache, responses: RequestsMock, browser_mock: Browse
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success("You are now authenticated on 123456. You may close this tab.")
+ tab.assert_success()
def test_empty_token_is_invalid(token_cache, browser_mock: BrowserMock):
@@ -340,9 +371,7 @@ def test_empty_token_is_invalid(token_cache, browser_mock: BrowserMock):
auth=requests_auth.OAuth2Implicit("http://provide_token"),
)
assert str(exception_info.value) == " is invalid."
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_token_without_expiry_is_invalid(token_cache, browser_mock: BrowserMock):
@@ -357,9 +386,7 @@ def test_token_without_expiry_is_invalid(token_cache, browser_mock: BrowserMock)
auth=requests_auth.OAuth2Implicit("http://provide_token"),
)
assert str(exception_info.value) == "Expiry (exp) is not provided in None."
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_get_token_is_sent_in_authorization_header_by_default(
@@ -380,9 +407,7 @@ def test_oauth2_implicit_flow_get_token_is_sent_in_authorization_header_by_defau
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_token_is_sent_in_requested_field(
@@ -406,9 +431,7 @@ def test_oauth2_implicit_flow_token_is_sent_in_requested_field(
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_can_send_a_custom_response_type_and_expects_token_to_be_received_with_this_name(
@@ -434,9 +457,7 @@ def test_oauth2_implicit_flow_can_send_a_custom_response_type_and_expects_token_
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 67b95d2c7555751d1d72c97c7cd9ad6630c8395e0eaa51ee86ac7e451211ded9cd98a7190848789fe93632d8960425710e93f1f5549c6c6bc328bf3865a85ff2. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_expects_token_in_id_token_if_response_type_is_id_token(
@@ -460,9 +481,7 @@ def test_oauth2_implicit_flow_expects_token_in_id_token_if_response_type_is_id_t
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 87c4108ec0eb03599335333a40434a36674269690b6957fef684bfb6c5a849ce660ef7031aa874c44d67cd3eada8febdfce41efb1ed3bc53a0a7e716cbba025a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_expects_token_in_id_token_if_response_type_in_url_is_id_token(
@@ -484,9 +503,7 @@ def test_oauth2_implicit_flow_expects_token_in_id_token_if_response_type_in_url_
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 87c4108ec0eb03599335333a40434a36674269690b6957fef684bfb6c5a849ce660ef7031aa874c44d67cd3eada8febdfce41efb1ed3bc53a0a7e716cbba025a. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_expects_token_to_be_stored_in_access_token_by_default(
@@ -508,9 +525,7 @@ def test_oauth2_implicit_flow_expects_token_to_be_stored_in_access_token_by_defa
)
requests.get("http://authorized_only", auth=auth)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_token_is_reused_if_not_expired(
@@ -540,9 +555,7 @@ def test_oauth2_implicit_flow_token_is_reused_if_not_expired(
)
requests.get("http://authorized_only", auth=oauth2)
- tab.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab.assert_success()
def test_oauth2_implicit_flow_post_failure_if_token_is_not_provided(
@@ -559,9 +572,7 @@ def test_oauth2_implicit_flow_post_failure_if_token_is_not_provided(
auth=requests_auth.OAuth2Implicit("http://provide_token"),
)
assert str(exception_info.value) == "access_token not provided within {}."
- tab.assert_failure(
- "Unable to properly perform authentication: access_token not provided within {}."
- )
+ tab.assert_failure("access_token not provided within {}.")
def test_oauth2_implicit_flow_get_failure_if_token_is_not_provided(
@@ -577,9 +588,7 @@ def test_oauth2_implicit_flow_get_failure_if_token_is_not_provided(
auth=requests_auth.OAuth2Implicit("http://provide_token"),
)
assert str(exception_info.value) == "access_token not provided within {}."
- tab.assert_failure(
- "Unable to properly perform authentication: access_token not provided within {}."
- )
+ tab.assert_failure("access_token not provided within {}.")
def test_oauth2_implicit_flow_post_failure_if_state_is_not_provided(
@@ -603,9 +612,7 @@ def test_oauth2_implicit_flow_post_failure_if_state_is_not_provided(
str(exception_info.value)
== f"state not provided within {{'access_token': ['{token}']}}."
)
- tab.assert_failure(
- f"Unable to properly perform authentication: state not provided within {{'access_token': ['{token}']}}."
- )
+ tab.assert_failure(f"state not provided within {{'access_token': ['{token}']}}.")
def test_oauth2_implicit_flow_get_failure_if_state_is_not_provided(
@@ -629,7 +636,7 @@ def test_oauth2_implicit_flow_get_failure_if_state_is_not_provided(
== f"state not provided within {{'access_token': ['{token}'], 'requests_auth_redirect': ['1']}}."
)
tab.assert_failure(
- f"Unable to properly perform authentication: state not provided within {{'access_token': ['{token}'], 'requests_auth_redirect': ['1']}}."
+ f"state not provided within {{'access_token': ['{token}'], 'requests_auth_redirect': ['1']}}."
)
@@ -650,7 +657,7 @@ def test_with_invalid_token_request_invalid_request_error(
== "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
+ "invalid_request: The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."
)
@@ -667,9 +674,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description(
auth=requests_auth.OAuth2Implicit("http://provide_token"),
)
assert str(exception_info.value) == "invalid_request: desc"
- tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc"
- )
+ tab.assert_failure("invalid_request: desc")
def test_with_invalid_token_request_invalid_request_error_and_error_description_and_uri(
@@ -689,7 +694,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url"
+ "invalid_request: desc
More information can be found on http://test_url"
)
@@ -710,7 +715,7 @@ def test_with_invalid_token_request_invalid_request_error_and_error_description_
== "invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_request: desc\nMore information can be found on http://test_url\nAdditional information: {'other': ['test']}"
+ "invalid_request: desc
More information can be found on http://test_url
Additional information: {'other': ['test']}"
)
@@ -731,7 +736,7 @@ def test_with_invalid_token_request_unauthorized_client_error(
== "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
+ "unauthorized_client: The client is not authorized to request an authorization code or an access token using this method."
)
@@ -752,7 +757,7 @@ def test_with_invalid_token_request_access_denied_error(
== "access_denied: The resource owner or authorization server denied the request."
)
tab.assert_failure(
- "Unable to properly perform authentication: access_denied: The resource owner or authorization server denied the request."
+ "access_denied: The resource owner or authorization server denied the request."
)
@@ -773,7 +778,7 @@ def test_with_invalid_token_request_unsupported_response_type_error(
== "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
tab.assert_failure(
- "Unable to properly perform authentication: unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
+ "unsupported_response_type: The authorization server does not support obtaining an authorization code or an access token using this method."
)
@@ -794,7 +799,7 @@ def test_with_invalid_token_request_invalid_scope_error(
== "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
tab.assert_failure(
- "Unable to properly perform authentication: invalid_scope: The requested scope is invalid, unknown, or malformed."
+ "invalid_scope: The requested scope is invalid, unknown, or malformed."
)
@@ -815,7 +820,7 @@ def test_with_invalid_token_request_server_error_error(
== "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "server_error: The authorization server encountered an unexpected condition that prevented it from fulfilling the request. (This error code is needed because a 500 Internal Server Error HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -836,7 +841,7 @@ def test_with_invalid_token_request_temporarily_unavailable_error(
== "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
tab.assert_failure(
- "Unable to properly perform authentication: temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
+ "temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. (This error code is needed because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP redirect.)"
)
@@ -899,9 +904,5 @@ def test_oauth2_implicit_flow_token_is_requested_again_if_expired(
)
requests.get("http://authorized_only", auth=auth)
- tab1.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
- tab2.assert_success(
- "You are now authenticated on 42a85b271b7a652ca3cc4c398cfd3f01b9ad36bf9c945ba823b023e8f8b95c4638576a0e3dcc96838b838bec33ec6c0ee2609d62ed82480b3b8114ca494c0521. You may close this tab."
- )
+ tab1.assert_success()
+ tab2.assert_success()