Escape $ sign when replacing clientId in the role mappers

Closes https://github.com/keycloak/keycloak/issues/23692
This commit is contained in:
rmartinc 2023-10-05 12:19:04 +02:00 committed by Marek Posolda
parent 70e820469a
commit d7bb59461d
2 changed files with 8 additions and 11 deletions

View file

@ -75,10 +75,7 @@ abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper
}
private static final Pattern CLIENT_ID_PATTERN = Pattern.compile("\\$\\{client_id\\}");
private static final Pattern DOT_PATTERN = Pattern.compile("\\.");
private static final String DOT_REPLACEMENT = "\\\\\\\\.";
private static final Pattern CLIENT_ID_PATTERN = Pattern.compile(Pattern.quote("${client_id}"));
private static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue, String clientId) {
attributeValue = OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, attributeValue);
@ -90,11 +87,10 @@ abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper
}
if (clientId != null) {
// case when clientId contains dots
clientId = DOT_PATTERN.matcher(clientId).replaceAll(DOT_REPLACEMENT);
Matcher matcher = CLIENT_ID_PATTERN.matcher(protocolClaim);
if (matcher.find()) {
protocolClaim = matcher.replaceAll(clientId);
// dots and backslashes in clientId should be escaped first for the claim
protocolClaim = matcher.replaceAll(Matcher.quoteReplacement(clientId.replace("\\", "\\\\").replace(".", "\\.")));
}
}

View file

@ -235,8 +235,9 @@ public class UserInfoTest extends AbstractKeycloakTest {
@Test
public void testSuccess_dotsInClientId() throws Exception {
// Create client with dot in the name
final String clientId = "my.foo.$\\client\\$";
ClientRepresentation clientRep = org.keycloak.testsuite.util.ClientBuilder.create()
.clientId("my.foo.client")
.clientId(clientId)
.addRedirectUri("http://foo.host")
.secret("password")
.directAccessGrants()
@ -258,11 +259,11 @@ public class UserInfoTest extends AbstractKeycloakTest {
userResource.roles().clientLevel(clientUUID).add(Collections.singletonList(fooRole));
// Login to the new client
OAuthClient.AccessTokenResponse accessTokenResponse = oauth.clientId("my.foo.client")
OAuthClient.AccessTokenResponse accessTokenResponse = oauth.clientId(clientId)
.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
AccessToken accessToken = oauth.verifyToken(accessTokenResponse.getAccessToken());
Assert.assertNames(accessToken.getResourceAccess("my.foo.client").getRoles(), "my.foo.role");
Assert.assertNames(accessToken.getResourceAccess(clientId).getRoles(), "my.foo.role");
events.clear();
@ -271,7 +272,7 @@ public class UserInfoTest extends AbstractKeycloakTest {
try {
Response response = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, accessTokenResponse.getAccessToken());
testSuccessfulUserInfoResponse(response, "my.foo.client");
testSuccessfulUserInfoResponse(response, clientId);
} finally {
client.close();
}