You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2026/09/03 15:53:44 UTC

(knox) branch master updated: KNOX-3433: set issued_token_type in KnoxIDF token responses (RFC 8693 §2.2.1) (#1375)

This is an automated email from the ASF dual-hosted git repository.

smolnar82 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 6f9460095 KNOX-3433: set issued_token_type in KnoxIDF token responses (RFC 8693 §2.2.1) (#1375)
6f9460095 is described below

commit 6f94600951397379670ab5aa30d15a5f2f51a6c2
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Thu Sep 3 17:53:38 2026 +0200

    KNOX-3433: set issued_token_type in KnoxIDF token responses (RFC 8693 §2.2.1) (#1375)
---
 .github/workflows/tests/test_knoxidf.py                            | 3 +++
 .../org/apache/knox/gateway/service/knoxidf/TokenResource.java     | 7 +++++++
 .../org/apache/knox/gateway/util/knoxidf/KnoxIDFConstants.java     | 4 ++++
 3 files changed, 14 insertions(+)

diff --git a/.github/workflows/tests/test_knoxidf.py b/.github/workflows/tests/test_knoxidf.py
index b67fd0c52..70c18e08e 100644
--- a/.github/workflows/tests/test_knoxidf.py
+++ b/.github/workflows/tests/test_knoxidf.py
@@ -99,6 +99,7 @@ class TestKnoxIDF(unittest.TestCase):
         tokens = response.json()
         self.assertIn("access_token", tokens)
         self.assertEqual(tokens["token_type"], "Bearer")
+        self.assertEqual(tokens["issued_token_type"], "urn:ietf:params:oauth:token-type:jwt")
 
     def test_authorization_code_flow(self):
         """
@@ -136,6 +137,7 @@ class TestKnoxIDF(unittest.TestCase):
         self.assertIn("access_token", tokens)
         self.assertIn("id_token", tokens)
         self.assertIn("refresh_token", tokens)
+        self.assertEqual(tokens["issued_token_type"], "urn:ietf:params:oauth:token-type:jwt")
 
         refresh_token = tokens["refresh_token"]
         print(f"Refresh token: {refresh_token}")
@@ -154,6 +156,7 @@ class TestKnoxIDF(unittest.TestCase):
         new_tokens = response.json()
         self.assertIn("access_token", new_tokens)
         self.assertIn("refresh_token", new_tokens)
+        self.assertEqual(new_tokens["issued_token_type"], "urn:ietf:params:oauth:token-type:jwt")
 
         # Verify rotation: new refresh token should be different
         self.assertNotEqual(refresh_token, new_tokens["refresh_token"])
diff --git a/gateway-service-knoxidf/src/main/java/org/apache/knox/gateway/service/knoxidf/TokenResource.java b/gateway-service-knoxidf/src/main/java/org/apache/knox/gateway/service/knoxidf/TokenResource.java
index 01e5517ef..e5a198995 100644
--- a/gateway-service-knoxidf/src/main/java/org/apache/knox/gateway/service/knoxidf/TokenResource.java
+++ b/gateway-service-knoxidf/src/main/java/org/apache/knox/gateway/service/knoxidf/TokenResource.java
@@ -71,6 +71,8 @@ import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.CODE_CHALLEN
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.CODE_CHALLENGE_METHOD;
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.CODE_VERIFIER;
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.FEDERATED_IDENTITY_ID;
+import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.ISSUED_TOKEN_TYPE;
+import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.ISSUED_TOKEN_TYPE_JWT_VALUE;
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.OFFLINE_ACCESS_SCOPE;
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.PKCE_METHOD_S256;
 import static org.apache.knox.gateway.util.knoxidf.KnoxIDFConstants.REDIRECT_URI;
@@ -211,6 +213,11 @@ public class TokenResource extends PasscodeTokenResourceBase {
     protected ResponseMap buildResponseMap(JWT token, long expires) throws TokenServiceException {
         final ResponseMap responseMap = super.buildResponseMap(token, expires);
 
+        // RFC 8693 §2.2.1 requires the response to state the type of the issued token. Every KnoxIDF
+        // grant (authorization_code, refresh_token and the client_credentials/other grants routed to
+        // super.doPost()) funnels through here and mints a JWT, so advertise the JWT URN unconditionally.
+        responseMap.map.put(ISSUED_TOKEN_TYPE, ISSUED_TOKEN_TYPE_JWT_VALUE);
+
         // id_token + refresh-token rotation apply to the user-centric grants (authorization_code and
         // refresh_token). client_credentials and other grants routed to super.doPost() must not get an
         // id_token (no end user) and never carry offline_access, so they are excluded here.
diff --git a/gateway-util-common/src/main/java/org/apache/knox/gateway/util/knoxidf/KnoxIDFConstants.java b/gateway-util-common/src/main/java/org/apache/knox/gateway/util/knoxidf/KnoxIDFConstants.java
index 8c8cf6581..102297a34 100644
--- a/gateway-util-common/src/main/java/org/apache/knox/gateway/util/knoxidf/KnoxIDFConstants.java
+++ b/gateway-util-common/src/main/java/org/apache/knox/gateway/util/knoxidf/KnoxIDFConstants.java
@@ -44,6 +44,10 @@ public interface KnoxIDFConstants {
     String STATE = "state";
     String CODE = "code";
     String REFRESH_TOKEN = "refresh_token";
+    // RFC 8693 §2.2.1: the token endpoint response must advertise the type of the issued token.
+    String ISSUED_TOKEN_TYPE = "issued_token_type";
+    //KnoxIDF always mints a JWT so issued_token_type is the JWT URN rather than the generic access_token URN.
+    String ISSUED_TOKEN_TYPE_JWT_VALUE = "urn:ietf:params:oauth:token-type:jwt";
     String REFRESH_TOKEN_TTL= "refresh.token.ttl";
     long REFRESH_TOKEN_TTL_DEFAULT = 86400000L; // 1 day
     String CODE_RESPONSE_TYPE = RESPONSE_TYPE + "=" + CODE;