4 changed files with 30 additions and 224 deletions
@ -1,81 +0,0 @@
@@ -1,81 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.saml2.provider.service.servlet.filter; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; |
||||
import org.springframework.util.StringUtils; |
||||
import org.springframework.web.util.UriComponents; |
||||
import org.springframework.web.util.UriComponentsBuilder; |
||||
|
||||
import static org.springframework.security.web.util.UrlUtils.buildFullRequestUrl; |
||||
import static org.springframework.web.util.UriComponentsBuilder.fromHttpUrl; |
||||
|
||||
/** |
||||
* @since 5.3 |
||||
*/ |
||||
final class Saml2ServletUtils { |
||||
|
||||
private static final char PATH_DELIMITER = '/'; |
||||
|
||||
static String resolveUrlTemplate(String template, String baseUrl, RelyingPartyRegistration relyingParty) { |
||||
if (!StringUtils.hasText(template)) { |
||||
return baseUrl; |
||||
} |
||||
|
||||
String entityId = relyingParty.getAssertingPartyDetails().getEntityId(); |
||||
String registrationId = relyingParty.getRegistrationId(); |
||||
Map<String, String> uriVariables = new HashMap<>(); |
||||
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl) |
||||
.replaceQuery(null) |
||||
.fragment(null) |
||||
.build(); |
||||
String scheme = uriComponents.getScheme(); |
||||
uriVariables.put("baseScheme", scheme == null ? "" : scheme); |
||||
String host = uriComponents.getHost(); |
||||
uriVariables.put("baseHost", host == null ? "" : host); |
||||
// following logic is based on HierarchicalUriComponents#toUriString()
|
||||
int port = uriComponents.getPort(); |
||||
uriVariables.put("basePort", port == -1 ? "" : ":" + port); |
||||
String path = uriComponents.getPath(); |
||||
if (StringUtils.hasLength(path)) { |
||||
if (path.charAt(0) != PATH_DELIMITER) { |
||||
path = PATH_DELIMITER + path; |
||||
} |
||||
} |
||||
uriVariables.put("basePath", path == null ? "" : path); |
||||
uriVariables.put("baseUrl", uriComponents.toUriString()); |
||||
uriVariables.put("entityId", StringUtils.hasText(entityId) ? entityId : ""); |
||||
uriVariables.put("registrationId", StringUtils.hasText(registrationId) ? registrationId : ""); |
||||
|
||||
return UriComponentsBuilder.fromUriString(template) |
||||
.buildAndExpand(uriVariables) |
||||
.toUriString(); |
||||
} |
||||
|
||||
static String getApplicationUri(HttpServletRequest request) { |
||||
UriComponents uriComponents = fromHttpUrl(buildFullRequestUrl(request)) |
||||
.replacePath(request.getContextPath()) |
||||
.replaceQuery(null) |
||||
.fragment(null) |
||||
.build(); |
||||
return uriComponents.toUriString(); |
||||
} |
||||
} |
||||
@ -1,73 +0,0 @@
@@ -1,73 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.saml2.provider.service.servlet.filter; |
||||
|
||||
import org.apache.commons.codec.binary.Base64; |
||||
import org.springframework.security.saml2.Saml2Exception; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.util.zip.Deflater; |
||||
import java.util.zip.DeflaterOutputStream; |
||||
import java.util.zip.Inflater; |
||||
import java.util.zip.InflaterOutputStream; |
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8; |
||||
import static java.util.zip.Deflater.DEFLATED; |
||||
|
||||
/** |
||||
* @since 5.3 |
||||
*/ |
||||
final class Saml2Utils { |
||||
|
||||
|
||||
private static Base64 BASE64 = new Base64(0, new byte[]{'\n'}); |
||||
|
||||
static String samlEncode(byte[] b) { |
||||
return BASE64.encodeAsString(b); |
||||
} |
||||
|
||||
static byte[] samlDecode(String s) { |
||||
return BASE64.decode(s); |
||||
} |
||||
|
||||
static byte[] samlDeflate(String s) { |
||||
try { |
||||
ByteArrayOutputStream b = new ByteArrayOutputStream(); |
||||
DeflaterOutputStream deflater = new DeflaterOutputStream(b, new Deflater(DEFLATED, true)); |
||||
deflater.write(s.getBytes(UTF_8)); |
||||
deflater.finish(); |
||||
return b.toByteArray(); |
||||
} |
||||
catch (IOException e) { |
||||
throw new Saml2Exception("Unable to deflate string", e); |
||||
} |
||||
} |
||||
|
||||
static String samlInflate(byte[] b) { |
||||
try { |
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||
InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true)); |
||||
iout.write(b); |
||||
iout.finish(); |
||||
return new String(out.toByteArray(), UTF_8); |
||||
} |
||||
catch (IOException e) { |
||||
throw new Saml2Exception("Unable to inflate string", e); |
||||
} |
||||
} |
||||
} |
||||
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.saml2.provider.service.servlet.filter; |
||||
|
||||
import org.apache.commons.codec.binary.Base64; |
||||
import org.junit.Test; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.util.StreamUtils; |
||||
import org.springframework.web.util.UriUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8; |
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class Saml2UtilsTests { |
||||
|
||||
private static Base64 UNCHUNKED_ENCODER = new Base64(0, new byte[]{'\n'}); |
||||
private static final Base64 CHUNKED_ENCODER = new Base64(76, new byte[] { '\n' }); |
||||
|
||||
@Test |
||||
public void decodeWhenUsingApacheCommonsBase64ThenXmlIsValid() throws Exception { |
||||
String responseUrlDecoded = getSsoCircleEncodedXml(); |
||||
String xml = new String(UNCHUNKED_ENCODER.decode(responseUrlDecoded.getBytes(UTF_8)), UTF_8); |
||||
validateSsoCircleXml(xml); |
||||
} |
||||
|
||||
@Test |
||||
public void decodeWhenUsingApacheCommonsBase64ChunkedThenXmlIsValid() throws Exception { |
||||
String responseUrlDecoded = getSsoCircleEncodedXml(); |
||||
String xml = new String(CHUNKED_ENCODER.decode(responseUrlDecoded.getBytes(UTF_8)), UTF_8); |
||||
validateSsoCircleXml(xml); |
||||
} |
||||
|
||||
@Test |
||||
public void decodeWhenUsingSamlUtilsBase64ThenXmlIsValid() throws Exception { |
||||
String responseUrlDecoded = getSsoCircleEncodedXml(); |
||||
String xml = new String(Saml2Utils.samlDecode(responseUrlDecoded), UTF_8); |
||||
validateSsoCircleXml(xml); |
||||
} |
||||
|
||||
private void validateSsoCircleXml(String xml) { |
||||
assertThat(xml) |
||||
.contains("InResponseTo=\"ARQ9a73ead-7dcf-45a8-89eb-26f3c9900c36\"") |
||||
.contains(" ID=\"s246d157446618e90e43fb79bdd4d9e9e19cf2c7c4\"") |
||||
.contains("<saml:Issuer>https://idp.ssocircle.com</saml:Issuer>"); |
||||
} |
||||
|
||||
private String getSsoCircleEncodedXml() throws IOException { |
||||
ClassPathResource resource = new ClassPathResource("saml2-response-sso-circle.encoded"); |
||||
String response = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); |
||||
return UriUtils.decode(response, UTF_8); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue