Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions plugins/user-authenticators/saml2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,11 @@
<version>${cs.xercesImpl.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${cs.assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ public static String buildAuthnRequestUrl(final String authnId, final SAMLProvid
if (spMetadata.getKeyPair() != null) {
privateKey = spMetadata.getKeyPair().getPrivate();
}
redirectUrl = idpMetadata.getSsoUrl() + "?" + SAMLUtils.generateSAMLRequestSignature("SAMLRequest=" + SAMLUtils.encodeSAMLRequest(authnRequest), privateKey, signatureAlgorithm);
String appendOperator = idpMetadata.getSsoUrl().contains("?") ? "&" : "?";
redirectUrl = idpMetadata.getSsoUrl() + appendOperator + SAMLUtils.generateSAMLRequestSignature("SAMLRequest=" + SAMLUtils.encodeSAMLRequest(authnRequest), privateKey, signatureAlgorithm);
} catch (ConfigurationException | FactoryConfigurationError | MarshallingException | IOException | NoSuchAlgorithmException | InvalidKeyException | java.security.SignatureException e) {
s_logger.error("SAML AuthnRequest message building error: " + e.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,22 @@

package org.apache.cloudstack;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.regex.Pattern;

import junit.framework.TestCase;
import org.apache.cloudstack.saml.SAML2AuthManager;
import org.apache.cloudstack.saml.SAMLProviderMetadata;
import org.apache.cloudstack.saml.SAMLUtils;
import org.apache.cloudstack.utils.security.CertUtils;
import org.junit.Test;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.LogoutRequest;

import junit.framework.TestCase;
import java.net.URI;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.regex.Pattern;

import static org.assertj.core.api.Assertions.assertThat;

public class SAMLUtilsTest extends TestCase {

Expand Down Expand Up @@ -60,6 +64,63 @@ public void testBuildAuthnRequestObject() throws Exception {
assertEquals(req.getIssuer().getValue(), spId);
}

@Test
public void testBuildAuthnRequestUrlWithoutQueryParam() throws Exception {
String urlScheme = "http";

String spDomain = "sp.domain.example";
String spUrl = urlScheme + "://" + spDomain;
String spId = "serviceProviderId";

String idpDomain = "idp.domain.example";
String idpUrl = urlScheme + "://" + idpDomain;
String idpId = "identityProviderId";

String authnId = SAMLUtils.generateSecureRandomId();

SAMLProviderMetadata spMetadata = new SAMLProviderMetadata();
spMetadata.setEntityId(spId);
spMetadata.setSsoUrl(spUrl);

SAMLProviderMetadata idpMetadata = new SAMLProviderMetadata();
idpMetadata.setSsoUrl(idpUrl);
idpMetadata.setEntityId(idpId);

URI redirectUrl = new URI(SAMLUtils.buildAuthnRequestUrl(authnId, spMetadata, idpMetadata, SAML2AuthManager.SAMLSignatureAlgorithm.value()));
assertThat(redirectUrl).hasScheme(urlScheme).hasHost(idpDomain).hasParameter("SAMLRequest");
assertEquals(urlScheme, redirectUrl.getScheme());
assertEquals(idpDomain, redirectUrl.getHost());
}

@Test
public void testBuildAuthnRequestUrlWithQueryParam() throws Exception {
String urlScheme = "http";

String spDomain = "sp.domain.example";
String spUrl = urlScheme + "://" + spDomain;
String spId = "cloudstack";

String idpDomain = "idp.domain.example";
String idpQueryParam = "idpid=CX1298373";
String idpUrl = urlScheme + "://" + idpDomain + "?" + idpQueryParam;
String idpId = "identityProviderId";

String authnId = SAMLUtils.generateSecureRandomId();

SAMLProviderMetadata spMetadata = new SAMLProviderMetadata();
spMetadata.setEntityId(spId);
spMetadata.setSsoUrl(spUrl);

SAMLProviderMetadata idpMetadata = new SAMLProviderMetadata();
idpMetadata.setSsoUrl(idpUrl);
idpMetadata.setEntityId(idpId);

URI redirectUrl = new URI(SAMLUtils.buildAuthnRequestUrl(authnId, spMetadata, idpMetadata, SAML2AuthManager.SAMLSignatureAlgorithm.value()));
assertThat(redirectUrl).hasScheme(urlScheme).hasHost(idpDomain).hasParameter("idpid").hasParameter("SAMLRequest");
assertEquals(urlScheme, redirectUrl.getScheme());
assertEquals(idpDomain, redirectUrl.getHost());
}

@Test
public void testBuildLogoutRequest() throws Exception {
String logoutUrl = "http://logoutUrl";
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
<cs.testng.version>7.1.0</cs.testng.version>
<cs.wiremock.version>2.27.2</cs.wiremock.version>
<cs.xercesImpl.version>2.12.2</cs.xercesImpl.version>
<cs.assertj.version>3.23.1</cs.assertj.version>

<!-- Dependencies versions -->
<cs.amqp-client.version>5.10.0</cs.amqp-client.version>
Expand Down