Invalid redirect uri when identity provider alias has spaces (#22840)

closes #22836


Co-authored-by: Marek Posolda <mposolda@gmail.com>
This commit is contained in:
Pedro Hos 2024-02-19 10:40:42 -03:00 committed by GitHub
parent 95568a547b
commit 6b3fa8b7a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 95 additions and 46 deletions

View file

@ -49,6 +49,21 @@ public class ReservedCharValidator {
} }
} }
public static void validateNoSpace(String str) {
if (str == null) return;
Pattern pattern = Pattern.compile("\\s");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
String message = "Empty Space not allowed.";
logger.warn(message);
throw new ReservedCharException(message);
}
validate(str, RESERVED_CHARS_PATTERN);
}
public static void validate(String str) { public static void validate(String str) {
validate(str, RESERVED_CHARS_PATTERN); validate(str, RESERVED_CHARS_PATTERN);
} }

View file

@ -150,7 +150,7 @@ public class IdentityProvidersResource {
throw new BadRequestException(); throw new BadRequestException();
} }
ReservedCharValidator.validate((String)data.get("alias")); ReservedCharValidator.validateNoSpace((String)data.get("alias"));
String providerId = data.get("providerId").toString(); String providerId = data.get("providerId").toString();
String from = data.get("fromUrl").toString(); String from = data.get("fromUrl").toString();
@ -239,7 +239,7 @@ public class IdentityProvidersResource {
public Response create(@Parameter(description = "JSON body") IdentityProviderRepresentation representation) { public Response create(@Parameter(description = "JSON body") IdentityProviderRepresentation representation) {
this.auth.realm().requireManageIdentityProviders(); this.auth.realm().requireManageIdentityProviders();
ReservedCharValidator.validate(representation.getAlias()); ReservedCharValidator.validateNoSpace(representation.getAlias());
try { try {
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation, session); IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation, session);

View file

@ -17,6 +17,48 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLDSIG_NSURI;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.xml.crypto.dsig.XMLSignature;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.IdentityProviderResource; import org.keycloak.admin.client.resource.IdentityProviderResource;
@ -47,6 +89,7 @@ import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.DocumentUtil; import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.XmlKeyInfoKeyNameTransformer;
import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser; import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.processing.core.util.XMLSignatureUtil; import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
@ -56,55 +99,16 @@ import org.keycloak.testsuite.broker.oidc.OverwrittenMappersTestIdentityProvider
import org.keycloak.testsuite.updaters.RealmAttributeUpdater; import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
import org.keycloak.testsuite.util.AdminEventPaths; import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.KeyUtils; import org.keycloak.testsuite.util.KeyUtils;
import org.keycloak.utils.ReservedCharValidator.ReservedCharException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ClientErrorException; import jakarta.ws.rs.ClientErrorException;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import javax.xml.crypto.dsig.XMLSignature;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLDSIG_NSURI;
import org.keycloak.saml.common.util.XmlKeyInfoKeyNameTransformer;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -272,6 +276,22 @@ public class IdentityProviderTest extends AbstractAdminTest {
} }
} }
@Test
public void shouldFailWhenAliasHasSpaceDuringCreation() {
IdentityProviderRepresentation newIdentityProvider = createRep("New Identity Provider", "oidc");
newIdentityProvider.getConfig().put(IdentityProviderModel.SYNC_MODE, "IMPORT");
newIdentityProvider.getConfig().put("clientId", "clientId");
newIdentityProvider.getConfig().put("clientSecret", "some secret value");
newIdentityProvider.getConfig().put("clientAuthMethod",OIDCLoginProtocol.CLIENT_SECRET_BASIC);
try (Response response = this.realm.identityProviders().create(newIdentityProvider)) {
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
String error = response.readEntity(String.class);
assertTrue(error.contains("Empty Space not allowed."));
}
}
@Test @Test
public void testCreateWithBasicAuth() { public void testCreateWithBasicAuth() {
IdentityProviderRepresentation newIdentityProvider = createRep("new-identity-provider", "oidc"); IdentityProviderRepresentation newIdentityProvider = createRep("new-identity-provider", "oidc");
@ -681,6 +701,20 @@ public class IdentityProviderTest extends AbstractAdminTest {
response.close(); response.close();
} }
@Test
public void importShouldFailDueAliasWithSpace() {
Map<String, Object> data = new HashMap<>();
data.put("providerId", "saml");
data.put("alias", "Alias With Space");
data.put("fromUrl", "http://");
assertThrows(BadRequestException.class, () -> {
realm.identityProviders().importFrom(data);
});
}
@Test @Test
public void testSamlImportAndExport() throws URISyntaxException, IOException, ParsingException { public void testSamlImportAndExport() throws URISyntaxException, IOException, ParsingException {