diff --git a/tests/oauth2/authorization_code/test_oauth2_authorization_code.py b/tests/oauth2/authorization_code/test_oauth2_authorization_code.py index 328c78e..f54e962 100644 --- a/tests/oauth2/authorization_code/test_oauth2_authorization_code.py +++ b/tests/oauth2/authorization_code/test_oauth2_authorization_code.py @@ -42,7 +42,7 @@ def test_oauth2_authorization_code_flow_uses_provided_session( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -86,7 +86,7 @@ def test_oauth2_authorization_code_flow_uses_redirect_uri_domain( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -128,7 +128,7 @@ def test_oauth2_authorization_code_flow_get_code_is_sent_in_authorization_header ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -177,7 +177,7 @@ def test_oauth2_authorization_code_flow_token_is_expired_after_30_seconds_by_def ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -203,7 +203,7 @@ def test_oauth2_client_credentials_flow_token_custom_expiry( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -239,7 +239,7 @@ def test_refresh_token(token_cache, responses: RequestsMock, browser_mock: Brows ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -270,7 +270,7 @@ def test_refresh_token(token_cache, responses: RequestsMock, browser_mock: Brows ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer rVR7Syg5bjZtZYjbZIW"}),), + match=[header_matcher({"Authorization": "Bearer rVR7Syg5bjZtZYjbZIW"})], ) requests.get("http://authorized_only", auth=auth) @@ -308,7 +308,7 @@ def test_refresh_token_invalid( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -341,7 +341,7 @@ def test_refresh_token_invalid( # if refreshing the token fails, fallback to requesting a new token responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -383,7 +383,7 @@ def test_refresh_token_access_token_not_expired( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -395,7 +395,7 @@ def test_refresh_token_access_token_not_expired( # expect Bearer token to remain the same responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -969,7 +969,7 @@ def test_nonce_is_sent_if_provided_in_authorization_url( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) @@ -1012,7 +1012,7 @@ def test_response_type_can_be_provided_in_url( ) responses.get( "http://authorized_only", - match=(header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"}),), + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) requests.get("http://authorized_only", auth=auth) 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 09f732e..cf5a23b 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 @@ -1,11 +1,10 @@ from responses import RequestsMock -from responses.matchers import urlencoded_params_matcher +from responses.matchers import urlencoded_params_matcher, header_matcher import pytest import requests import requests_auth import requests_auth._oauth2.authorization_code_pkce -from tests.auth_helper import get_header, get_request from requests_auth.testing import BrowserMock, browser_mock, token_cache # noqa: F401 @@ -24,8 +23,7 @@ def test_oauth2_pkce_flow_uses_provided_session( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -34,17 +32,74 @@ def test_oauth2_pkce_flow_uses_provided_session( "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", + } + ), + header_matcher({"x-test": "Test value"}), + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) - request = get_request(responses, "http://provide_access_token/") - assert ( - request.body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&response_type=code&code=SplxlOBeZQQYbYS6WxSbIA" + + requests.get("http://authorized_only", auth=auth) + + tab.assert_success( + "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) - assert request.headers["x-test"] == "Test value" + + +def test_oauth2_pkce_flow_uses_redirect_uri_domain( + 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", + redirect_uri_domain="localhost.mycompany.com", + ) + tab = browser_mock.add_response( + opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost.mycompany.com%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", + reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", + ) + 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.mycompany.com: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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -63,8 +118,7 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -73,15 +127,25 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default( "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", + } + ), + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -107,8 +171,7 @@ def test_oauth2_pkce_flow_token_is_expired_after_30_seconds_by_default( expiry=requests_auth._oauth2.tokens._to_expiry(expires_in=29), ) # Meaning a new one will be requested - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -117,15 +180,25 @@ def test_oauth2_pkce_flow_token_is_expired_after_30_seconds_by_default( "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", + } + ), + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -148,11 +221,13 @@ def test_oauth2_client_credentials_flow_token_custom_expiry( token="2YotnFZFEjr1zCsicMWpAA", expiry=requests_auth._oauth2.tokens._to_expiry(expires_in=29), ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) + requests.get("http://authorized_only", auth=auth) + def test_expires_in_sent_as_str( token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock @@ -167,8 +242,7 @@ def test_expires_in_sent_as_str( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -177,15 +251,25 @@ def test_expires_in_sent_as_str( "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", + } + ), + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -204,8 +288,7 @@ def test_refresh_token( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -226,20 +309,18 @@ def test_refresh_token( ) ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) # response for refresh token grant - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "rVR7Syg5bjZtZYjbZIW", @@ -258,14 +339,13 @@ def test_refresh_token( ) ], ) - - response = requests.get("http://authorized_only", auth=auth) - assert response.request.headers.get("Authorization") == "Bearer rVR7Syg5bjZtZYjbZIW" - assert ( - get_request(responses, "http://provide_access_token/").body - == "grant_type=refresh_token&response_type=code&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer rVR7Syg5bjZtZYjbZIW"})], ) + requests.get("http://authorized_only", auth=auth) + def test_refresh_token_invalid( token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock @@ -280,8 +360,7 @@ def test_refresh_token_invalid( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -302,20 +381,18 @@ def test_refresh_token_invalid( ) ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) # response for refresh token grant - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_request"}, status=400, @@ -337,11 +414,13 @@ def test_refresh_token_invalid( ) # if refreshing the token fails, fallback to requesting a new token - response = requests.get("http://authorized_only", auth=auth) - assert ( - response.request.headers.get("Authorization") == "Bearer 2YotnFZFEjr1zCsicMWpAA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) + requests.get("http://authorized_only", auth=auth) + tab.assert_success( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -360,8 +439,7 @@ def test_refresh_token_access_token_not_expired( 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", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -382,14 +460,13 @@ def test_refresh_token_access_token_not_expired( ) ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -414,8 +491,7 @@ def test_nonce_is_sent_if_provided_in_authorization_url( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -424,15 +500,25 @@ def test_nonce_is_sent_if_provided_in_authorization_url( "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter": "example_value", }, + match=[ + urlencoded_params_matcher( + { + "grant_type": "authorization_code", + "code_verifier": "MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx", + "redirect_uri": "http://localhost:5000/", + "response_type": "code", + "code": "SplxlOBeZQQYbYS6WxSbIA", + } + ) + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&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( "You are now authenticated on 163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de. You may close this tab." ) @@ -451,9 +537,7 @@ def test_with_invalid_grant_request_no_json( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, "http://provide_access_token", body="failure", status=400 - ) + responses.post("http://provide_access_token", body="failure", status=400) with pytest.raises(requests_auth.InvalidGrantRequest) as exception_info: requests.get("http://authorized_only", auth=auth) assert str(exception_info.value) == "failure" @@ -475,8 +559,7 @@ def test_with_invalid_grant_request_invalid_request_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_request"}, status=400, @@ -508,8 +591,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_request", "error_description": "desc of the error"}, status=400, @@ -535,8 +617,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "error": "invalid_request", @@ -569,8 +650,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_ opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "error": "invalid_request", @@ -604,8 +684,7 @@ def test_with_invalid_grant_request_without_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"other": "other info"}, status=400, @@ -631,8 +710,7 @@ def test_with_invalid_grant_request_invalid_client_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_client"}, status=400, @@ -668,8 +746,7 @@ def test_with_invalid_grant_request_invalid_grant_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_grant"}, status=400, @@ -701,8 +778,7 @@ def test_with_invalid_grant_request_unauthorized_client_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "unauthorized_client"}, status=400, @@ -732,8 +808,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "unsupported_grant_type"}, status=400, @@ -763,8 +838,7 @@ def test_with_invalid_grant_request_invalid_scope_error( opened_url="http://provide_code?response_type=code&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&nonce=%5B%27123456%27%5D&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=163f0455b3e9cad3ca04254e5a0169553100d3aa0756c7964d897da316a695ffed5b4f46ef305094fd0a88cfe4b55ff257652015e4aa8f87b97513dba440f8de", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={"error": "invalid_scope"}, status=400, @@ -1033,8 +1107,7 @@ def test_response_type_can_be_provided_in_url( opened_url="http://provide_code?response_type=%5B%27my_code%27%5D&state=b32e05720bd3722e0ac87bf72897a78b669a0810adf8da46b675793dcfe0f41a40f7d7fdda952bd73ea533a2462907d805adf8c1a162d51b99b2ddec0d411feb&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=b32e05720bd3722e0ac87bf72897a78b669a0810adf8da46b675793dcfe0f41a40f7d7fdda952bd73ea533a2462907d805adf8c1a162d51b99b2ddec0d411feb", ) - responses.add( - responses.POST, + responses.post( "http://provide_access_token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -1043,15 +1116,25 @@ def test_response_type_can_be_provided_in_url( "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter": "example_value", }, + match=[ + urlencoded_params_matcher( + { + "grant_type": "authorization_code", + "code_verifier": "MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx", + "redirect_uri": "http://localhost:5000/", + "response_type": "my_code", + "code": "SplxlOBeZQQYbYS6WxSbIA", + } + ) + ], ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request(responses, "http://provide_access_token/").body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&response_type=my_code&code=SplxlOBeZQQYbYS6WxSbIA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) + + requests.get("http://authorized_only", auth=auth) + tab.assert_success( "You are now authenticated on b32e05720bd3722e0ac87bf72897a78b669a0810adf8da46b675793dcfe0f41a40f7d7fdda952bd73ea533a2462907d805adf8c1a162d51b99b2ddec0d411feb. You may close this tab." ) 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 7f02757..1eb8eb3 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 @@ -1,10 +1,10 @@ from responses import RequestsMock +from responses.matchers import urlencoded_params_matcher, header_matcher import pytest import requests import requests_auth import requests_auth._oauth2.authorization_code_pkce -from tests.auth_helper import get_header, get_request from requests_auth.testing import BrowserMock, browser_mock, token_cache # noqa: F401 @@ -25,8 +25,7 @@ def test_oauth2_pkce_flow_uses_provided_session( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -35,19 +34,78 @@ def test_oauth2_pkce_flow_uses_provided_session( "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", + } + ), + header_matcher({"x-test": "Test value"}), + ], + ) + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], + ) + + requests.get("http://authorized_only", auth=auth) + + tab.assert_success( + "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab." ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" + + +def test_oauth2_pkce_flow_uses_redirect_uri_domain( + token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock +): + monkeypatch.setattr( + requests_auth._oauth2.authorization_code_pkce.os, "urandom", lambda x: b"1" * 63 ) - request = get_request( - responses, "https://testserver.okta-emea.com/oauth2/default/v1/token" + auth = requests_auth.OktaAuthorizationCodePKCE( + "testserver.okta-emea.com", + "54239d18-c68c-4c47-8bdd-ce71ea1d50cd", + redirect_uri_domain="localhost.mycompany.com", ) - assert ( - request.body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&code=SplxlOBeZQQYbYS6WxSbIA" + 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.mycompany.com%3A5000%2F&code_challenge=5C_ph_KZ3DstYUc965SiqmKAA-ShvKF4Ut7daKd3fjc&code_challenge_method=S256", + reply_url="http://localhost:5000#code=SplxlOBeZQQYbYS6WxSbIA&state=5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b", ) - assert request.headers["x-test"] == "Test value" + 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.mycompany.com: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( "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab." ) @@ -66,8 +124,7 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -76,17 +133,27 @@ def test_oauth2_pkce_flow_get_code_is_sent_in_authorization_header_by_default( "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter": "example_value", }, - ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request( - responses, "https://testserver.okta-emea.com/oauth2/default/v1/token" - ).body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&code=SplxlOBeZQQYbYS6WxSbIA" - ) + 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( "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab." ) @@ -112,8 +179,7 @@ def test_okta_pkce_flow_token_is_expired_after_30_seconds_by_default( expiry=requests_auth._oauth2.tokens._to_expiry(expires_in=29), ) # Meaning a new one will be requested - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -122,17 +188,27 @@ def test_okta_pkce_flow_token_is_expired_after_30_seconds_by_default( "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter": "example_value", }, - ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request( - responses, "https://testserver.okta-emea.com/oauth2/default/v1/token" - ).body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&code=SplxlOBeZQQYbYS6WxSbIA" - ) + 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( "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab." ) @@ -155,11 +231,13 @@ def test_okta_pkce_flow_token_custom_expiry( token="2YotnFZFEjr1zCsicMWpAA", expiry=requests_auth._oauth2.tokens._to_expiry(expires_in=29), ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" + responses.get( + "http://authorized_only", + match=[header_matcher({"Authorization": "Bearer 2YotnFZFEjr1zCsicMWpAA"})], ) + requests.get("http://authorized_only", auth=auth) + def test_expires_in_sent_as_str( token_cache, responses: RequestsMock, monkeypatch, browser_mock: BrowserMock @@ -174,8 +252,7 @@ def test_expires_in_sent_as_str( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "access_token": "2YotnFZFEjr1zCsicMWpAA", @@ -184,17 +261,27 @@ def test_expires_in_sent_as_str( "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter": "example_value", }, - ) - assert ( - get_header(responses, auth).get("Authorization") - == "Bearer 2YotnFZFEjr1zCsicMWpAA" - ) - assert ( - get_request( - responses, "https://testserver.okta-emea.com/oauth2/default/v1/token" - ).body - == "code_verifier=MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F&client_id=54239d18-c68c-4c47-8bdd-ce71ea1d50cd&scope=openid&response_type=code&code=SplxlOBeZQQYbYS6WxSbIA" - ) + 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( "You are now authenticated on 5264d11c8b268ccf911ce564ca42fd75cea68c4a3c1ec3ac1ab20243891ab7cd5250ad4c2d002017c6e8ac2ba34954293baa5e0e4fd00bb9ffd4a39c45f1960b. You may close this tab." ) @@ -213,8 +300,7 @@ def test_with_invalid_grant_request_no_json( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", body="failure", status=400, @@ -240,8 +326,7 @@ def test_with_invalid_grant_request_invalid_request_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "invalid_request"}, status=400, @@ -273,8 +358,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "invalid_request", "error_description": "desc of the error"}, status=400, @@ -300,8 +384,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_ 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "error": "invalid_request", @@ -334,8 +417,7 @@ def test_with_invalid_grant_request_invalid_request_error_and_error_description_ 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={ "error": "invalid_request", @@ -369,8 +451,7 @@ def test_with_invalid_grant_request_without_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"other": "other info"}, status=400, @@ -396,8 +477,7 @@ def test_with_invalid_grant_request_invalid_client_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "invalid_client"}, status=400, @@ -433,8 +513,7 @@ def test_with_invalid_grant_request_invalid_grant_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "invalid_grant"}, status=400, @@ -466,8 +545,7 @@ def test_with_invalid_grant_request_unauthorized_client_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "unauthorized_client"}, status=400, @@ -497,8 +575,7 @@ def test_with_invalid_grant_request_unsupported_grant_type_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "unsupported_grant_type"}, status=400, @@ -528,8 +605,7 @@ def test_with_invalid_grant_request_invalid_scope_error( 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", ) - responses.add( - responses.POST, + responses.post( "https://testserver.okta-emea.com/oauth2/default/v1/token", json={"error": "invalid_scope"}, status=400,