Skip to content

Commit 8ebfba3

Browse files
blucasfhanik
authored andcommitted
Support configuration of protocol binding for authentication requests
1 parent 971ae34 commit 8ebfba3

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.security.saml2.provider.service.authentication;
1818

19+
import org.opensaml.saml.common.xml.SAMLConstants;
1920
import org.springframework.util.Assert;
2021

2122
import org.joda.time.DateTime;
@@ -32,6 +33,7 @@
3233
public class OpenSamlAuthenticationRequestFactory implements Saml2AuthenticationRequestFactory {
3334
private Clock clock = Clock.systemUTC();
3435
private final OpenSamlImplementation saml = OpenSamlImplementation.getInstance();
36+
private String protocolBinding = SAMLConstants.SAML2_POST_BINDING_URI;
3537

3638
/**
3739
* {@inheritDoc}
@@ -43,7 +45,7 @@ public String createAuthenticationRequest(Saml2AuthenticationRequest request) {
4345
auth.setIssueInstant(new DateTime(this.clock.millis()));
4446
auth.setForceAuthn(Boolean.FALSE);
4547
auth.setIsPassive(Boolean.FALSE);
46-
auth.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect");
48+
auth.setProtocolBinding(protocolBinding);
4749
Issuer issuer = this.saml.buildSAMLObject(Issuer.class);
4850
issuer.setValue(request.getIssuer());
4951
auth.setIssuer(issuer);
@@ -67,4 +69,21 @@ public void setClock(Clock clock) {
6769
Assert.notNull(clock, "clock cannot be null");
6870
this.clock = clock;
6971
}
72+
73+
/**
74+
* Sets the {@code protocolBinding} to use when generating authentication requests
75+
* Acceptable values are {@link SAMLConstants#SAML2_POST_BINDING_URI} and
76+
* {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI}
77+
*
78+
* @param protocolBinding
79+
* @throws IllegalArgumentException if the protocolBinding is not valid
80+
*/
81+
public void setProtocolBinding(String protocolBinding) {
82+
boolean isAllowedBinding = SAMLConstants.SAML2_POST_BINDING_URI.equals(protocolBinding) ||
83+
SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(protocolBinding);
84+
if (!isAllowedBinding) {
85+
throw new IllegalArgumentException("Invalid protocol binding: " + protocolBinding);
86+
}
87+
this.protocolBinding = protocolBinding;
88+
}
7089
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2002-2019 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.authentication;
18+
19+
import org.junit.Assert;
20+
import org.junit.Before;
21+
import org.junit.Rule;
22+
import org.junit.Test;
23+
import org.junit.rules.ExpectedException;
24+
import org.opensaml.saml.common.xml.SAMLConstants;
25+
import org.opensaml.saml.saml2.core.AuthnRequest;
26+
27+
import static org.hamcrest.CoreMatchers.containsString;
28+
import static org.springframework.security.saml2.provider.service.authentication.TestSaml2X509Credentials.relyingPartyCredentials;
29+
30+
public class OpenSamlAuthenticationRequestFactoryTests {
31+
32+
private OpenSamlAuthenticationRequestFactory factory;
33+
private Saml2AuthenticationRequest request;
34+
35+
@Rule
36+
public ExpectedException exception = ExpectedException.none();
37+
38+
@Before
39+
public void setUp() {
40+
request = Saml2AuthenticationRequest.builder()
41+
.issuer("https://issuer")
42+
.destination("https://destination/sso")
43+
.assertionConsumerServiceUrl("https://issuer/sso")
44+
.credentials(c -> c.addAll(relyingPartyCredentials()))
45+
.build();
46+
factory = new OpenSamlAuthenticationRequestFactory();
47+
}
48+
49+
@Test
50+
public void createAuthenticationRequestWhenDefaultThenReturnsPostBinding() {
51+
AuthnRequest authn = getAuthNRequest();
52+
Assert.assertEquals(SAMLConstants.SAML2_POST_BINDING_URI, authn.getProtocolBinding());
53+
}
54+
55+
@Test
56+
public void createAuthenticationRequestWhenSetUriThenReturnsCorrectBinding() {
57+
factory.setProtocolBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
58+
AuthnRequest authn = getAuthNRequest();
59+
Assert.assertEquals(SAMLConstants.SAML2_REDIRECT_BINDING_URI, authn.getProtocolBinding());
60+
}
61+
62+
@Test
63+
public void createAuthenticationRequestWhenSetUnsupportredUriThenThrowsIllegalArgumentException() {
64+
exception.expect(IllegalArgumentException.class);
65+
exception.expectMessage(containsString("my-invalid-binding"));
66+
factory.setProtocolBinding("my-invalid-binding");
67+
}
68+
69+
private AuthnRequest getAuthNRequest() {
70+
String xml = factory.createAuthenticationRequest(request);
71+
return (AuthnRequest) OpenSamlImplementation.getInstance().resolve(xml);
72+
}
73+
}

0 commit comments

Comments
 (0)