Skip to content

Commit 7330ec4

Browse files
surkoff-vjzheaux
authored andcommitted
Adding keyInfo section to LogoutRequest from RP side
Issue gh-10438
1 parent b4ffe15 commit 7330ec4

File tree

4 files changed

+113
-0
lines changed

4 files changed

+113
-0
lines changed

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlSigningUtils.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
4343
import org.opensaml.xmlsec.crypto.XMLSigningUtil;
4444
import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
45+
import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager;
46+
import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager;
47+
import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
4548
import org.opensaml.xmlsec.signature.SignableXMLObject;
4649
import org.opensaml.xmlsec.signature.support.SignatureConstants;
4750
import org.opensaml.xmlsec.signature.support.SignatureSupport;
@@ -103,6 +106,7 @@ private static SignatureSigningParameters resolveSigningParameters(
103106
signingConfiguration.setSignatureAlgorithms(algorithms);
104107
signingConfiguration.setSignatureReferenceDigestMethods(digests);
105108
signingConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);
109+
signingConfiguration.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
106110
criteria.add(new SignatureSigningConfigurationCriterion(signingConfiguration));
107111
try {
108112
SignatureSigningParameters parameters = resolver.resolveSingle(criteria);
@@ -114,6 +118,22 @@ private static SignatureSigningParameters resolveSigningParameters(
114118
}
115119
}
116120

121+
private static NamedKeyInfoGeneratorManager buildSignatureKeyInfoGeneratorManager() {
122+
final NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager();
123+
124+
namedManager.setUseDefaultManager(true);
125+
final KeyInfoGeneratorManager defaultManager = namedManager.getDefaultManager();
126+
127+
// Generator for X509Credentials
128+
final X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
129+
x509Factory.setEmitEntityCertificate(true);
130+
x509Factory.setEmitEntityCertificateChain(true);
131+
132+
defaultManager.registerFactory(x509Factory);
133+
134+
return namedManager;
135+
}
136+
117137
private static List<Credential> resolveSigningCredentials(RelyingPartyRegistration relyingPartyRegistration) {
118138
List<Credential> credentials = new ArrayList<>();
119139
for (Saml2X509Credential x509Credential : relyingPartyRegistration.getSigningX509Credentials()) {

saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,22 @@ public static LogoutResponse assertingPartyLogoutResponse(RelyingPartyRegistrati
384384
return logoutResponse;
385385
}
386386

387+
public static LogoutRequest relyingPartyLogoutRequest(RelyingPartyRegistration registration) {
388+
LogoutRequestBuilder logoutRequestBuilder = new LogoutRequestBuilder();
389+
LogoutRequest logoutRequest = logoutRequestBuilder.buildObject();
390+
logoutRequest.setID("id");
391+
NameIDBuilder nameIdBuilder = new NameIDBuilder();
392+
NameID nameId = nameIdBuilder.buildObject();
393+
nameId.setValue("user");
394+
logoutRequest.setNameID(nameId);
395+
IssuerBuilder issuerBuilder = new IssuerBuilder();
396+
Issuer issuer = issuerBuilder.buildObject();
397+
issuer.setValue(registration.getAssertingPartyDetails().getEntityId());
398+
logoutRequest.setIssuer(issuer);
399+
logoutRequest.setDestination(registration.getAssertingPartyDetails().getSingleLogoutServiceLocation());
400+
return logoutRequest;
401+
}
402+
387403
static <T extends XMLObject> T build(QName qName) {
388404
return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
389405
}

saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlSigningUtils.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
4343
import org.opensaml.xmlsec.crypto.XMLSigningUtil;
4444
import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
45+
import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager;
46+
import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager;
47+
import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
4548
import org.opensaml.xmlsec.signature.SignableXMLObject;
4649
import org.opensaml.xmlsec.signature.support.SignatureConstants;
4750
import org.opensaml.xmlsec.signature.support.SignatureSupport;
@@ -103,6 +106,7 @@ private static SignatureSigningParameters resolveSigningParameters(
103106
signingConfiguration.setSignatureAlgorithms(algorithms);
104107
signingConfiguration.setSignatureReferenceDigestMethods(digests);
105108
signingConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);
109+
signingConfiguration.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
106110
criteria.add(new SignatureSigningConfigurationCriterion(signingConfiguration));
107111
try {
108112
SignatureSigningParameters parameters = resolver.resolveSingle(criteria);
@@ -114,6 +118,22 @@ private static SignatureSigningParameters resolveSigningParameters(
114118
}
115119
}
116120

121+
private static NamedKeyInfoGeneratorManager buildSignatureKeyInfoGeneratorManager() {
122+
final NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager();
123+
124+
namedManager.setUseDefaultManager(true);
125+
final KeyInfoGeneratorManager defaultManager = namedManager.getDefaultManager();
126+
127+
// Generator for X509Credentials
128+
final X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
129+
x509Factory.setEmitEntityCertificate(true);
130+
x509Factory.setEmitEntityCertificateChain(true);
131+
132+
defaultManager.registerFactory(x509Factory);
133+
134+
return namedManager;
135+
}
136+
117137
private static List<Credential> resolveSigningCredentials(RelyingPartyRegistration relyingPartyRegistration) {
118138
List<Credential> credentials = new ArrayList<>();
119139
for (Saml2X509Credential x509Credential : relyingPartyRegistration.getSigningX509Credentials()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2002-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.saml2.provider.service.web.authentication.logout;
18+
19+
import org.junit.jupiter.api.BeforeEach;
20+
import org.junit.jupiter.api.Test;
21+
import org.opensaml.saml.saml2.core.LogoutRequest;
22+
import org.opensaml.xmlsec.signature.Signature;
23+
24+
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
25+
import org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects;
26+
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
30+
/**
31+
* Test open SAML Logout signatures
32+
*/
33+
public class Saml2LogoutSigningUtilsTests {
34+
35+
private RelyingPartyRegistration registration;
36+
37+
@BeforeEach
38+
public void setup() {
39+
this.registration = RelyingPartyRegistration.withRegistrationId("saml-idp")
40+
.entityId("https://some.idp.example.com/entity-id").signingX509Credentials((c) -> {
41+
c.add(TestSaml2X509Credentials.relyingPartySigningCredential());
42+
c.add(TestSaml2X509Credentials.assertingPartySigningCredential());
43+
}).assertingPartyDetails((c) -> c.entityId("https://some.idp.example.com/entity-id")
44+
.singleSignOnServiceLocation("https://some.idp.example.com/service-location"))
45+
.build();
46+
}
47+
48+
@Test
49+
public void whenSigningLogoutRequestRPThenKeyInfoIsPartOfTheSignature() {
50+
LogoutRequest logoutRequest = TestOpenSamlObjects.relyingPartyLogoutRequest(this.registration);
51+
OpenSamlSigningUtils.sign(logoutRequest, this.registration);
52+
Signature signature = logoutRequest.getSignature();
53+
assertThat(signature).isNotNull();
54+
assertThat(signature.getKeyInfo()).isNotNull();
55+
}
56+
57+
}

0 commit comments

Comments
 (0)