From 2a3ebb616b4d2c2c099959e83daa094e0caab2b0 Mon Sep 17 00:00:00 2001 From: Jens L Date: Thu, 16 Mar 2023 15:58:38 +0100 Subject: [PATCH] providers/oauth2: fix response for response_type code and response_mode fragment (#4975) --- .../providers/oauth2/tests/test_authorize.py | 56 +++++++++++++++++++ authentik/providers/oauth2/views/authorize.py | 7 ++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/authentik/providers/oauth2/tests/test_authorize.py b/authentik/providers/oauth2/tests/test_authorize.py index 17c07e350..76688fdda 100644 --- a/authentik/providers/oauth2/tests/test_authorize.py +++ b/authentik/providers/oauth2/tests/test_authorize.py @@ -355,6 +355,62 @@ class TestAuthorize(OAuthTestCase): delta=5, ) + def test_full_fragment_code(self): + """Test full authorization""" + flow = create_test_flow() + provider: OAuth2Provider = OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + client_secret=generate_key(), + authorization_flow=flow, + redirect_uris="http://localhost", + signing_key=self.keypair, + ) + Application.objects.create(name="app", slug="app", provider=provider) + state = generate_id() + user = create_test_admin_user() + self.client.force_login(user) + with patch( + "authentik.providers.oauth2.id_token.get_login_event", + MagicMock( + return_value=Event( + action=EventAction.LOGIN, + context={PLAN_CONTEXT_METHOD: "password"}, + created=now(), + ) + ), + ): + # Step 1, initiate params and get redirect to flow + self.client.get( + reverse("authentik_providers_oauth2:authorize"), + data={ + "response_type": "code", + "response_mode": "fragment", + "client_id": "test", + "state": state, + "scope": "openid", + "redirect_uri": "http://localhost", + "nonce": generate_id(), + }, + ) + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + ) + code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first() + self.assertJSONEqual( + response.content.decode(), + { + "component": "xak-flow-redirect", + "type": ChallengeTypes.REDIRECT.value, + "to": (f"http://localhost#code={code.code}" f"&state={state}"), + }, + ) + self.assertAlmostEqual( + code.expires.timestamp() - now().timestamp(), + timedelta_from_string(provider.access_code_validity).total_seconds(), + delta=5, + ) + def test_full_form_post_id_token(self): """Test full authorization (form_post response)""" flow = create_test_flow() diff --git a/authentik/providers/oauth2/views/authorize.py b/authentik/providers/oauth2/views/authorize.py index 5c7497732..12752130b 100644 --- a/authentik/providers/oauth2/views/authorize.py +++ b/authentik/providers/oauth2/views/authorize.py @@ -514,7 +514,12 @@ class OAuthFulfillmentStage(StageView): return urlunsplit(uri) if self.params.response_mode == ResponseMode.FRAGMENT: - query_fragment = self.create_implicit_response(code) + query_fragment = {} + if self.params.grant_type in [GrantTypes.AUTHORIZATION_CODE]: + query_fragment["code"] = code.code + query_fragment["state"] = [str(self.params.state) if self.params.state else ""] + else: + query_fragment = self.create_implicit_response(code) uri = uri._replace( fragment=uri.fragment + urlencode(query_fragment, doseq=True),