Commit 94414864 authored by Gradl, Tobias's avatar Gradl, Tobias
Browse files

3: Implement metadata helper methods and access through sample

controller

Task-Url: #3
parent f1c1c05b
Pipeline #17505 passed with stage
in 1 minute and 44 seconds
<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_c53f31e55d93419680d6930ed119421b146a023" entityID="https://c105-229.cloud.gwdg.de/dme" validUntil="2040-10-28T07:32:29.593Z">
<md:Extensions xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport">
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
</md:Extensions>
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:assertion">
<md:Extensions xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init">
<init:RequestInitiator Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="http://localhost:8080/callback?client_name=SAML2Client"/>
</md:Extensions>
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIEOTCCAqGgAwIBAgIUejGvYAjQIqKiG11W7w6PIaNKBIMwDQYJKoZIhvcNAQELBQAwITEfMB0G
A1UEAxMWYzEwNS0yMjkuY2xvdWQuZ3dkZy5kZTAeFw0yMDA0MzAwNzIyMDdaFw0yMzA1MDEwNzIy
MDdaMCExHzAdBgNVBAMTFmMxMDUtMjI5LmNsb3VkLmd3ZGcuZGUwggGiMA0GCSqGSIb3DQEBAQUA
A4IBjwAwggGKAoIBgQDHWlEUUaAnomRLPKUrayShpV0y0Wk7m7vqmZ4WiStLn/dwrDOiIgNqBh/w
boZ6DSfivaiNmb8IfKG2neUn1AyR/9Qony8ydwH0lWT3pFphPpb7tBP0jwiyXSKP425UqlyPsH+4
tHyYkHUlaqyuBBr7tSXN1Zz6c0Y5E3uRHK0KvTtf6akFcRK9PDadztXF+BUn5BaSwnFE/TG9bJ0p
6AmXDhvM54hL62/ueqT3Vg5/gnBIJmrW4VOOX+JCyjD9VcZWm/Q0672dXbZNIHPiWDBpVSVYsO1V
wsATeb7mHAuq2FoWAe03AOkw860cbDiaYpknFxMC6Ac3Jiu1I3MAtW/giFCNsfd9uqL4beq+bgLx
QzLi3HucLxghqI+i4wNBgPd6b9eCHO7X6qB3+X3ibbthxHS7F2xG3pA2VXwMplhGRVnk7t1dDRQz
OtcrnbDab9gPsh8Aw+sxpmDEu4J8GkspSvd4uuwOQ3IJhdNrTqn0QQyoZ34DTGMtA+kfS36ga/8C
AwEAAaNpMGcwRgYDVR0RBD8wPYIWYzEwNS0yMjkuY2xvdWQuZ3dkZy5kZYYjaHR0cHM6Ly9jMTA1
LTIyOS5jbG91ZC5nd2RnLmRlL3NhbWwwHQYDVR0OBBYEFN7qyWPjyg+BTFsq4AtOG0WHX1X9MA0G
CSqGSIb3DQEBCwUAA4IBgQA4Ey0+LtXooX7sxHoP+TogcIpwG3AQ9U64URHMCZH11WM/T73hs/Mp
Ck5AMYjuFXNJ+/+NYmHS7/8Ay6y+X94OzFDECLfMvDQebPNFqxVyQU89lJFh0u68ChUjihW8N/mf
7T3kR69Ekb4l7U9GbpY61fldBOIWuEU1MWyixYTuqwZ57SD5aA+qwIPbP/b4bxZC5vNGecOeAR+U
WdKomI+DM1WppQWECZDu6++PrIhjmvZymUEIgXlOTIxIyGcb/79wvRxwY+5tlvq1hOhDtarSXIPO
pu2ROEtMAexJscrSOE6vBi3QZtRremuZPaPYhOiuoFRVHL6+g1hR/NTeoECQ1tBQKq3g2ppKVt6i
g6vVqLsOeluYvZ/CucQ133ceR50OTGtclQvrPcOBP9Pz89lfcG4JJyfliGrR8t1foUkewciF1aME
DBxjfBjDVW0WKKDlU/qOsVHmNPGavywbKECOkthD/jQWu2OBPspsQQ0Ts8Jp9n7IIJJH7l7dTAyo
rS8=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIEOTCCAqGgAwIBAgIUejGvYAjQIqKiG11W7w6PIaNKBIMwDQYJKoZIhvcNAQELBQAwITEfMB0G
A1UEAxMWYzEwNS0yMjkuY2xvdWQuZ3dkZy5kZTAeFw0yMDA0MzAwNzIyMDdaFw0yMzA1MDEwNzIy
MDdaMCExHzAdBgNVBAMTFmMxMDUtMjI5LmNsb3VkLmd3ZGcuZGUwggGiMA0GCSqGSIb3DQEBAQUA
A4IBjwAwggGKAoIBgQDHWlEUUaAnomRLPKUrayShpV0y0Wk7m7vqmZ4WiStLn/dwrDOiIgNqBh/w
boZ6DSfivaiNmb8IfKG2neUn1AyR/9Qony8ydwH0lWT3pFphPpb7tBP0jwiyXSKP425UqlyPsH+4
tHyYkHUlaqyuBBr7tSXN1Zz6c0Y5E3uRHK0KvTtf6akFcRK9PDadztXF+BUn5BaSwnFE/TG9bJ0p
6AmXDhvM54hL62/ueqT3Vg5/gnBIJmrW4VOOX+JCyjD9VcZWm/Q0672dXbZNIHPiWDBpVSVYsO1V
wsATeb7mHAuq2FoWAe03AOkw860cbDiaYpknFxMC6Ac3Jiu1I3MAtW/giFCNsfd9uqL4beq+bgLx
QzLi3HucLxghqI+i4wNBgPd6b9eCHO7X6qB3+X3ibbthxHS7F2xG3pA2VXwMplhGRVnk7t1dDRQz
OtcrnbDab9gPsh8Aw+sxpmDEu4J8GkspSvd4uuwOQ3IJhdNrTqn0QQyoZ34DTGMtA+kfS36ga/8C
AwEAAaNpMGcwRgYDVR0RBD8wPYIWYzEwNS0yMjkuY2xvdWQuZ3dkZy5kZYYjaHR0cHM6Ly9jMTA1
LTIyOS5jbG91ZC5nd2RnLmRlL3NhbWwwHQYDVR0OBBYEFN7qyWPjyg+BTFsq4AtOG0WHX1X9MA0G
CSqGSIb3DQEBCwUAA4IBgQA4Ey0+LtXooX7sxHoP+TogcIpwG3AQ9U64URHMCZH11WM/T73hs/Mp
Ck5AMYjuFXNJ+/+NYmHS7/8Ay6y+X94OzFDECLfMvDQebPNFqxVyQU89lJFh0u68ChUjihW8N/mf
7T3kR69Ekb4l7U9GbpY61fldBOIWuEU1MWyixYTuqwZ57SD5aA+qwIPbP/b4bxZC5vNGecOeAR+U
WdKomI+DM1WppQWECZDu6++PrIhjmvZymUEIgXlOTIxIyGcb/79wvRxwY+5tlvq1hOhDtarSXIPO
pu2ROEtMAexJscrSOE6vBi3QZtRremuZPaPYhOiuoFRVHL6+g1hR/NTeoECQ1tBQKq3g2ppKVt6i
g6vVqLsOeluYvZ/CucQ133ceR50OTGtclQvrPcOBP9Pz89lfcG4JJyfliGrR8t1foUkewciF1aME
DBxjfBjDVW0WKKDlU/qOsVHmNPGavywbKECOkthD/jQWu2OBPspsQQ0Ts8Jp9n7IIJJH7l7dTAyo
rS8=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/callback?client_name=SAML2Client&amp;logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="http://localhost:8080/callback?client_name=SAML2Client&amp;logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/callback?client_name=SAML2Client&amp;logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/callback?client_name=SAML2Client&amp;logoutendpoint=true"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/callback?client_name=SAML2Client" index="0"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
......@@ -4,5 +4,9 @@ public class Constants {
public enum AUTHENTICATION_STAGE { AUTHENTICATION, ATTRIBUTES }
public enum REQUIRED_ATTRIBUTE_CHECKLOGIC { AND, OR, OPTIONAL }
public final static String SAML_CLIENT_NAME = "Saml2Client";
public final static String LOCAL_CLIENT_NAME = "FormClient";
}
......@@ -18,6 +18,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.FileSystemResource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import eu.dariah.de.dariahsp.sample.CustomAuthorizer;
......@@ -54,12 +55,17 @@ public class SecurityConfig {
cfg.setKeystoreAlias(saml.getKeystore().getAlias());
cfg.setKeystorePath(saml.getKeystore().getPath());
cfg.setPrivateKeyPassword(saml.getKeystore().getAliaspass());
cfg.setKeystorePassword(saml.getKeystore().getPass());
// IdP Metadata
cfg.setIdentityProviderMetadataPath(saml.getMetadata().getUrl());
// SP Metadata
cfg.setServiceProviderMetadataPath(saml.getSp().getExternalMetadata());
if (saml.getSp().getExternalMetadata()!=null) {
cfg.setServiceProviderMetadataPath(saml.getSp().getExternalMetadata());
} else {
cfg.setServiceProviderMetadataPath("/tmp/sp_metadata.xml");
}
cfg.setMaximumAuthenticationLifetime(saml.getSp().getMaxAuthAge());
cfg.setServiceProviderEntityId(saml.getSp().getEntityId());
......@@ -70,6 +76,7 @@ public class SecurityConfig {
//cfg.setAuthnRequestBindingType(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
//cfg.setResponseBindingType(SAMLConstants.SAML2_POST_BINDING_URI);
//cfg.setNameIdPolicyFormat(nameIdPolicyFormat);
// TODO: Refactor old properties
cfg.setWantsAssertionsSigned(saml.getSp().isRequireArtifactResolveSigned());
......@@ -87,9 +94,6 @@ public class SecurityConfig {
cfg.setHttpClient(httpClient.build());*/
// TODO: Produce or provide metadata in controller
//String spMetadata = samlClient.getServiceProviderMetadataResolver().getMetadata();
// Static: Support only SAML2
......
......@@ -17,7 +17,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
@EnableWebSecurity
public class WebSecurityConfig {
/* @Configuration
@Configuration
@Order(5)
public static class FormWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
......@@ -61,7 +61,7 @@ public class WebSecurityConfig {
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
*/
/* @Configuration
@Order(7)
public static class CombinedSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
......@@ -92,7 +92,7 @@ public class WebSecurityConfig {
.addFilterBefore(filter, BasicAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
}*/
@Configuration
......@@ -132,5 +132,5 @@ public class WebSecurityConfig {
.logout()
.logoutSuccessUrl("/");
}
}*/
}
}
......@@ -30,6 +30,10 @@ public class ErrorController extends BasicErrorController {
return new ModelAndView("error401");
} else if (status == HttpStatus.FORBIDDEN) {
return new ModelAndView("error403");
} else if (status == HttpStatus.NOT_FOUND) {
return new ModelAndView("error404");
} else if (status == HttpStatus.NO_CONTENT) {
return new ModelAndView("ok204");
} else {
return new ModelAndView("error500");
}
......
......@@ -10,8 +10,12 @@ import org.pac4j.core.http.adapter.JEEHttpActionAdapter;
import org.pac4j.core.profile.ProfileManager;
import org.pac4j.core.util.Pac4jConstants;
import org.pac4j.http.client.indirect.FormClient;
import org.pac4j.saml.client.SAML2Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
......@@ -19,23 +23,25 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import eu.dariah.de.dariahsp.sample.Constants;
import eu.dariah.de.dariahsp.sample.error.SAML2MetadataNotFoundException;
import eu.dariah.de.dariahsp.sample.metadata.MetadataHelper;
import javassist.NotFoundException;
@Controller
public class SampleController {
private static final String PROFILES = "profiles";
private static final String SESSION_ID = "sessionId";
/*@Value("${auth.salt}")
@Value("${auth.salt}")
private String salt;
@Autowired
private Config config;
@Autowired
private JEEContext jeeContext;
@Autowired
private ProfileManager profileManager;
@Autowired private Config config;
@Autowired private JEEContext jeeContext;
@Autowired private ProfileManager profileManager;
@Autowired private MetadataHelper metadataHelper;
@GetMapping("/")
public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
......@@ -50,7 +56,7 @@ public class SampleController {
@RequestMapping("/loginForm")
public String loginForm(Map<String, Object> map) {
final FormClient formClient = (FormClient) config.getClients().findClient("FormClient").get();
final FormClient formClient = (FormClient) config.getClients().findClient(Constants.LOCAL_CLIENT_NAME).get();
map.put("callbackUrl", formClient.getCallbackUrl());
return "form";
}
......@@ -69,10 +75,27 @@ public class SampleController {
JEEHttpActionAdapter.INSTANCE.adapt(action, jeeContext);
return null;
}
@GetMapping(value = "/metadata", produces = MediaType.APPLICATION_XML_VALUE)
public @ResponseBody String getMetadata(@RequestParam(required=false) boolean generate, @RequestParam(required=false) boolean filesystem) throws Exception {
String metadata;
if ((metadataHelper.isFilesystemMetadataAvailable() && !generate) || filesystem) {
metadata = metadataHelper.getFromFilesystem();
} else {
metadata = metadataHelper.generateFromConfiguration();
}
if (metadata!=null) {
return metadata;
} else {
throw new SAML2MetadataNotFoundException();
}
}
protected String protectedIndex(Map<String, Object> map) {
map.put(PROFILES, profileManager.getAll(true));
return "protectedIndex";
}*/
}
}
package eu.dariah.de.dariahsp.sample.error;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value=HttpStatus.NO_CONTENT, reason="SAML2 metadata not available")
public class SAML2MetadataNotFoundException extends RuntimeException {
private static final long serialVersionUID = 4211017703190145692L;
}
package eu.dariah.de.dariahsp.sample.metadata;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Optional;
import org.pac4j.core.config.Config;
import org.pac4j.saml.client.SAML2Client;
import org.pac4j.saml.config.SAML2Configuration;
import org.pac4j.saml.metadata.SAML2MetadataGenerator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import eu.dariah.de.dariahsp.sample.Constants;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class MetadataHelper implements InitializingBean {
@Autowired private Config config;
private SAML2Configuration saml2Config = null;
@Override
public void afterPropertiesSet() throws Exception {
Optional<?> client = config.getClients().findClient(Constants.SAML_CLIENT_NAME);
if (client.isPresent()) {
saml2Config = SAML2Client.class.cast(client.get()).getConfiguration();
}
}
public boolean isAvailable() {
return saml2Config!=null;
}
public boolean isFilesystemMetadataAvailable() {
if (!isAvailable()) {
return false;
}
Resource md = saml2Config.getServiceProviderMetadataResource();
return md!=null && md.exists();
}
public String generateFromConfiguration() {
if (!isAvailable()) {
return null;
}
SAML2MetadataGenerator gen;
try {
gen = saml2Config.toMetadataGenerator();
return gen.getMetadata(gen.buildEntityDescriptor());
} catch (Exception e) {
log.error("Failed to generate SAML2 metadata", e);
}
return null;
}
public String getFromFilesystem() {
if (!isAvailable()) {
return null;
}
Resource md = saml2Config.getServiceProviderMetadataResource();
if (md==null || !md.exists()) {
return null;
}
try (Reader reader = new InputStreamReader(md.getInputStream(), "UTF-8")) {
return FileCopyUtils.copyToString(reader);
} catch (IOException e) {
log.error("Failed to read SAML2 metadata", e);
}
return null;
}
}
\ No newline at end of file
......@@ -30,13 +30,12 @@ auth:
sp:
#externalMetadata: /etc/dfa/dme/sp_metadata.xml
maxAuthAge: -1
entityId: https://dme.de.dariah.eu/dme
entityId: https://c105-229.cloud.gwdg.de/dme
signMetadata: true
signingAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
requireArtifactResolveSigned: true
requireLogoutRequestSigned: true
requireLogoutResponseSigned: false
allowedNameIds : EMAIL, TRANSIENT, PERSISTENT, UNSPECIFIED, X509_SUBJECT
requiredAttributes:
- stage: ATTRIBUTES
required: true
......
<html>
<body>
<h1>not found</h1>
<br />
<a href="/">Home</a>
</body>
</html>
\ No newline at end of file
<html>
<body>
<h1>no content available</h1>
<br />
<a href="/">Home</a>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment