From 57cc5911eefdc92608d13b9e1eed549dd03d8260 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Date: Thu, 15 Oct 2026 09:07:52 +0600 Subject: [PATCH] Set default Bearer token_type in broker token responses Closes #53954 Signed-off-by: Atiqur Rahman --- .../provider/AbstractIdentityProvider.java | 5 +++++ .../AbstractOAuth2IdentityProviderTest.java | 20 +++++++++++++++++++ .../IdentityProviderStoreTokenV2Test.java | 2 ++ ...Auth2IdentityProviderStoreTokenV2Test.java | 2 ++ .../broker/KcOidcBrokerTokenExchangeTest.java | 3 +++ 5 files changed, 32 insertions(+) diff --git a/server-spi-private/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java b/server-spi-private/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java index 7a50e87d61c5..a65fc835f548 100755 --- a/server-spi-private/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java +++ b/server-spi-private/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java @@ -42,6 +42,7 @@ import org.keycloak.representations.AccessTokenResponse; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.util.Booleans; +import org.keycloak.util.TokenUtil; import org.jboss.logging.Logger; @@ -283,6 +284,10 @@ protected Response buildTokenResponse(UriInfo uriInfo, EventBuilder event, Clien tokenResponse.setRefreshExpiresIn(0); tokenResponse.getOtherClaims().clear(); + if (tokenResponse.getTokenType() == null) { + tokenResponse.setTokenType(TokenUtil.TOKEN_TYPE_BEARER); + } + tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, issuedTokenType); if (authorizedClient != null) { diff --git a/services/src/test/java/org/keycloak/test/broker/oidc/AbstractOAuth2IdentityProviderTest.java b/services/src/test/java/org/keycloak/test/broker/oidc/AbstractOAuth2IdentityProviderTest.java index 5f764379f239..89459123185e 100755 --- a/services/src/test/java/org/keycloak/test/broker/oidc/AbstractOAuth2IdentityProviderTest.java +++ b/services/src/test/java/org/keycloak/test/broker/oidc/AbstractOAuth2IdentityProviderTest.java @@ -20,12 +20,17 @@ import java.util.HashMap; import java.util.Map; +import jakarta.ws.rs.core.Response; + +import org.keycloak.OAuth2Constants; import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider; import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig; import org.keycloak.broker.provider.BrokeredIdentityContext; import org.keycloak.broker.provider.IdentityBrokerException; import org.keycloak.models.IdentityProviderModel; +import org.keycloak.representations.AccessTokenResponse; import org.keycloak.util.JsonSerialization; +import org.keycloak.util.TokenUtil; import com.fasterxml.jackson.databind.JsonNode; import org.junit.Assert; @@ -187,6 +192,17 @@ public void oAuthResponse_missingRefreshExpiresInField_shouldNotThrowException() Assert.assertNull(response.getRefreshExpiresIn()); // Should return null, not throw NPE } + @Test + public void buildTokenResponseDefaultsTokenTypeToBearer() { + AccessTokenResponse tokenResponse = new AccessTokenResponse(); + tokenResponse.setToken("access-token"); + + try (Response response = getTested().buildTokenResponse(tokenResponse)) { + AccessTokenResponse result = (AccessTokenResponse) response.getEntity(); + Assert.assertEquals(TokenUtil.TOKEN_TYPE_BEARER, result.getTokenType()); + } + } + private OAuth2IdentityProviderConfig getConfig(final String autorizationUrl, final String defaultScope, final String clientId, final Boolean isLoginHint, final Boolean passMaxAge) { IdentityProviderModel model = new IdentityProviderModel(); OAuth2IdentityProviderConfig config = new OAuth2IdentityProviderConfig(model); @@ -214,6 +230,10 @@ protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) { return new BrokeredIdentityContext(accessToken, getConfig()); }; + private Response buildTokenResponse(AccessTokenResponse tokenResponse) { + return buildTokenResponse(null, null, null, null, tokenResponse, OAuth2Constants.ACCESS_TOKEN_TYPE); + } + }; } diff --git a/tests/base/src/test/java/org/keycloak/tests/broker/IdentityProviderStoreTokenV2Test.java b/tests/base/src/test/java/org/keycloak/tests/broker/IdentityProviderStoreTokenV2Test.java index 41d9e59ee5fe..52f9d88403e3 100644 --- a/tests/base/src/test/java/org/keycloak/tests/broker/IdentityProviderStoreTokenV2Test.java +++ b/tests/base/src/test/java/org/keycloak/tests/broker/IdentityProviderStoreTokenV2Test.java @@ -29,6 +29,7 @@ import org.keycloak.testsuite.util.oauth.AbstractHttpResponse; import org.keycloak.testsuite.util.oauth.AccessTokenResponse; import org.keycloak.testsuite.util.oauth.UserInfoResponse; +import org.keycloak.util.TokenUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -101,6 +102,7 @@ public void checkSuccessfulTokenResponse(AbstractHttpResponse response) { Assertions.assertInstanceOf(AccessTokenResponse.class, response); AccessTokenResponse externalTokens = (AccessTokenResponse) response; Assertions.assertNotNull(externalTokens.getAccessToken()); + Assertions.assertEquals(TokenUtil.TOKEN_TYPE_BEARER, externalTokens.getTokenType()); Assertions.assertNull(externalTokens.getRefreshToken()); Assertions.assertNull(externalTokens.getIdToken()); UserInfoResponse userInfoResponse = getOauthClientExternal().userInfoRequest(externalTokens.getAccessToken()).send(); diff --git a/tests/base/src/test/java/org/keycloak/tests/broker/OAuth2IdentityProviderStoreTokenV2Test.java b/tests/base/src/test/java/org/keycloak/tests/broker/OAuth2IdentityProviderStoreTokenV2Test.java index a2abb6c72ec4..15d67a5d8039 100644 --- a/tests/base/src/test/java/org/keycloak/tests/broker/OAuth2IdentityProviderStoreTokenV2Test.java +++ b/tests/base/src/test/java/org/keycloak/tests/broker/OAuth2IdentityProviderStoreTokenV2Test.java @@ -47,6 +47,7 @@ import org.keycloak.testsuite.util.oauth.AbstractHttpResponse; import org.keycloak.testsuite.util.oauth.AccessTokenResponse; import org.keycloak.testsuite.util.oauth.UserInfoResponse; +import org.keycloak.util.TokenUtil; import com.sun.net.httpserver.HttpServer; import org.junit.jupiter.api.Assertions; @@ -130,6 +131,7 @@ public void checkSuccessfulTokenResponse(AbstractHttpResponse response) { Assertions.assertInstanceOf(AccessTokenResponse.class, response); AccessTokenResponse externalTokens = (AccessTokenResponse) response; Assertions.assertNotNull(externalTokens.getAccessToken()); + Assertions.assertEquals(TokenUtil.TOKEN_TYPE_BEARER, externalTokens.getTokenType()); Assertions.assertNull(externalTokens.getRefreshToken()); Assertions.assertNull(externalTokens.getIdToken()); UserInfoResponse userInfoResponse = oauthExternal.userInfoRequest(externalTokens.getAccessToken()).send(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTokenExchangeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTokenExchangeTest.java index 3b5438c13c52..40c3d8fecdc8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTokenExchangeTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTokenExchangeTest.java @@ -67,6 +67,7 @@ import org.keycloak.testsuite.util.broker.OIDCIdentityProviderConfigRep; import org.keycloak.testsuite.util.oauth.OAuthClient; import org.keycloak.util.BasicAuthHelper; +import org.keycloak.util.TokenUtil; import org.junit.Test; import org.junit.jupiter.api.Assertions; @@ -200,6 +201,7 @@ private void assertExternalToInternalExchange(String subjectIssuer, boolean idTo ))) { assertThat(response.getStatus(), equalTo(200)); AccessTokenResponse internalToExternalTokenResponse = response.readEntity(AccessTokenResponse.class); + assertThat(internalToExternalTokenResponse.getTokenType(), equalTo(TokenUtil.TOKEN_TYPE_BEARER)); } } } @@ -475,6 +477,7 @@ private void exchangeToIdP(ClientRepresentation brokerApp, String subjectToken, AccessTokenResponse exchangeResponse = response.readEntity(AccessTokenResponse.class); assertThat(exchangeResponse.getError(), nullValue()); assertThat(exchangeResponse.getToken(), notNullValue()); + assertThat(exchangeResponse.getTokenType(), equalTo(TokenUtil.TOKEN_TYPE_BEARER)); assertThat(exchangeResponse.getExpiresIn(), greaterThan((long) IdentityProviderModel.DEFAULT_MIN_VALIDITY_TOKEN)); assertThat(exchangeResponse.getExpiresIn(), lessThanOrEqualTo(expires)); }