From a0b01b6ef4fc4d35964353696a2a7cd8ac74c69f Mon Sep 17 00:00:00 2001 From: carlChen Date: Sun, 1 Aug 2021 16:55:30 +0800 Subject: [PATCH] KEYCLOAK-16703 The username returned by token introspect endpoint is null when remove or modify username mapper --- .../AccessTokenIntrospectionProvider.java | 13 +++++++++- .../oauth/TokenIntrospectionTest.java | 24 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/services/src/main/java/org/keycloak/protocol/oidc/AccessTokenIntrospectionProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/AccessTokenIntrospectionProvider.java index 12ebd69df8..1261aa4083 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/AccessTokenIntrospectionProvider.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/AccessTokenIntrospectionProvider.java @@ -25,6 +25,7 @@ import org.keycloak.crypto.SignatureProvider; import org.keycloak.crypto.SignatureVerifierContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; import org.keycloak.representations.AccessToken; import org.keycloak.services.Urls; import org.keycloak.util.JsonSerialization; @@ -56,7 +57,17 @@ public class AccessTokenIntrospectionProvider implements TokenIntrospectionProvi if (accessToken != null) { tokenMetadata = JsonSerialization.createObjectNode(accessToken); tokenMetadata.put("client_id", accessToken.getIssuedFor()); - tokenMetadata.put("username", accessToken.getPreferredUsername()); + + if (!tokenMetadata.has("username")) { + if (accessToken.getPreferredUsername() != null) { + tokenMetadata.put("username", accessToken.getPreferredUsername()); + } else { + UserModel userModel = session.users().getUserById(realm, accessToken.getSubject()); + if (userModel != null) { + tokenMetadata.put("username", userModel.getUsername()); + } + } + } } else { tokenMetadata = JsonSerialization.createObjectNode(); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java index aab01071d7..096921ec29 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java @@ -31,15 +31,17 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.OAuthErrorException; +import org.keycloak.admin.client.resource.ClientScopesResource; import org.keycloak.crypto.Algorithm; import org.keycloak.events.Errors; import org.keycloak.jose.jws.JWSInput; import org.keycloak.protocol.oidc.OIDCLoginProtocol; -import org.keycloak.representations.RefreshToken; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.representations.idm.OAuth2ErrorRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.oidc.TokenMetadataRepresentation; @@ -62,6 +64,7 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -106,6 +109,25 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest { testRealm.getUsers().add(user); } + @Override + protected void afterAbstractKeycloakTestRealmImport() { + ClientScopesResource clientScopesResource = testRealm().clientScopes(); + List clientScopeRepresentations = clientScopesResource.findAll(); + for (ClientScopeRepresentation scope : clientScopeRepresentations) { + List mappers = scope.getProtocolMappers(); + if (mappers != null) { + for (ProtocolMapperRepresentation mapper : mappers) { + if ("username".equals(mapper.getName())) { + Map config = mapper.getConfig(); + config.put("user.attribute", "username"); + config.put("claim.name", "preferred_username12"); + clientScopesResource.get(scope.getId()).getProtocolMappers().update(mapper.getId(), mapper); + } + } + } + } + } + @Test public void testConfidentialClientCredentialsBasicAuthentication() throws Exception { oauth.doLogin("test-user@localhost", "password");