Skip to content

Commit

Permalink
[TEST] Add SAML Redirect Signing test (#34562)
Browse files Browse the repository at this point in the history
Add a test to verify that we generate correct signatures for our
SAML2 Single Logout requests when using the redirect binding.
  • Loading branch information
jkakavas authored and kcm committed Oct 30, 2018
1 parent e19d361 commit cd07abf
Showing 1 changed file with 49 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.security.x509.X509Credential;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Base64;

import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static org.hamcrest.Matchers.equalTo;
Expand Down Expand Up @@ -67,6 +76,46 @@ public void testRedirectUrlWithTrailingQuestionMark() {
"1yHnLOX4Edtz0eDuf2uJjHy9Z%2Fl5ZEapyLQvGraBZdZm6ER59RV%2F8izGKwLg38VL4B1sji%2FPxxgeIb"));
}

public void testLogoutRequestSigning() throws Exception {
final X509Credential credential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
X509Credential invalidCredential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
while (invalidCredential.getEntityCertificate().getSerialNumber().equals(credential.getEntityCertificate().getSerialNumber())) {
invalidCredential = (X509Credential) buildOpenSamlCredential(readRandomKeyPair()).get(0);
}
final SigningConfiguration spConfig =
new SigningConfiguration(singleton("*"), credential);
final SamlRedirect redirect = new SamlRedirect(buildLogoutRequest(LOGOUT_URL + "?"), spConfig);
final String url = redirect.getRedirectUrl();
final String queryParam = url.split("\\?")[1].split("&Signature")[0];
final String params[] = url.split("\\?")[1].split("&");
assert (params.length == 3);
String sigAlg = parseAndUrlDecodeParameter(params[1]);
// We currently only support signing with SHA256withRSA, this test should be updated if we add support for more
assertThat(sigAlg, equalTo("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"));
sigAlg = "SHA256withRSA";
final String signature = parseAndUrlDecodeParameter(params[2]);
assertThat(validateSignature(queryParam, sigAlg, signature, credential), equalTo(true));
assertThat(validateSignature(queryParam, sigAlg, signature, invalidCredential), equalTo(false));
assertThat(validateSignature(queryParam.substring(0, queryParam.length() - 5), sigAlg, signature, credential), equalTo(false));
}

private String parseAndUrlDecodeParameter(String parameter) throws UnsupportedEncodingException {
final String value = parameter.split("=", 2)[1];
return URLDecoder.decode(value, "UTF-8");
}

private boolean validateSignature(String queryParam, String sigAlg, String signature, X509Credential credential) {
try {
Signature sig = Signature.getInstance(sigAlg);
sig.initVerify(credential.getPublicKey());
sig.update(queryParam.getBytes(StandardCharsets.UTF_8));
return sig.verify(Base64.getDecoder().decode(signature));
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
return false;
}

}

private LogoutRequest buildLogoutRequest(String logoutUrl) {
final LogoutRequest logoutRequest = SamlUtils.buildObject(LogoutRequest.class, LogoutRequest.DEFAULT_ELEMENT_NAME);
logoutRequest.setDestination(logoutUrl);
Expand Down

0 comments on commit cd07abf

Please sign in to comment.