java - Spring Security SAML - how to configure client auth? -
i'm trying adapt spring security saml sample application use test idp (provided me else) instead of ssocircle. clicking on "saml login" correctly redirects me sso login page of idp after login , redirection sample app exception (apparently during artifact resolution) @ root of is:
org.opensaml.ws.message.decoder.messagedecodingexception: error when sending request artifact resolution service. @ org.springframework.security.saml.websso.artifactresolutionprofileimpl.getartifactresponse(artifactresolutionprofileimpl.java:110) @ org.springframework.security.saml.websso.artifactresolutionprofilebase.resolveartifact(artifactresolutionprofilebase.java:101) ... 34 more caused by: javax.net.ssl.sslpeerunverifiedexception: ssl peer failed hostname validation name: null @ org.opensaml.ws.soap.client.http.tlsprotocolsocketfactory.verifyhostname(tlsprotocolsocketfactory.java:233) @ org.opensaml.ws.soap.client.http.tlsprotocolsocketfactory.createsocket(tlsprotocolsocketfactory.java:186) @ org.apache.commons.httpclient.httpconnection.open(httpconnection.java:707) @ org.apache.commons.httpclient.multithreadedhttpconnectionmanager$httpconnectionadapter.open(multithreadedhttpconnectionmanager.java:1361) @ org.apache.commons.httpclient.httpmethoddirector.executewithretry(httpmethoddirector.java:387) @ org.apache.commons.httpclient.httpmethoddirector.executemethod(httpmethoddirector.java:171) @ org.apache.commons.httpclient.httpclient.executemethod(httpclient.java:397) @ org.apache.commons.httpclient.httpclient.executemethod(httpclient.java:346) @ org.springframework.security.saml.websso.artifactresolutionprofileimpl.getartifactresponse(artifactresolutionprofileimpl.java:99) after digging while, realized server expects client authentication @ relevant port. if connect this, valid response:
curl -k --cert spcert.pem --key spkey.pem https://testidp:8110/idp/profile/saml2/soap/artifactresolution also, exception goes away if disable clientauth on idp editing server.xml of idp tomcat , changing clientauth "false" in relevant <connector> tag.
connecting idp's port 8110 works fine if use apache httpclient so
package at.awst.perkele.httpstest; import java.io.bufferedreader; import java.io.fileinputstream; import java.io.ioexception; import java.io.inputstreamreader; import java.security.keymanagementexception; import java.security.keystore; import java.security.keystoreexception; import java.security.nosuchalgorithmexception; import java.security.unrecoverablekeyexception; import java.security.cert.certificateexception; import javax.net.ssl.sslcontext; import org.apache.http.httpentity; import org.apache.http.client.methods.closeablehttpresponse; import org.apache.http.client.methods.httpget; import org.apache.http.conn.ssl.sslconnectionsocketfactory; import org.apache.http.conn.ssl.trustselfsignedstrategy; import org.apache.http.impl.client.closeablehttpclient; import org.apache.http.impl.client.httpclients; import org.apache.http.ssl.sslcontexts; import org.apache.http.util.entityutils; public class httpstest { private static final string ca_keystore_type = keystore.getdefaulttype(); // "jks"; private static final string ca_keystore_path = "mykeystore.jks"; private static final string ca_keystore_pass = "secret"; private static final string client_keystore_type = keystore.getdefaulttype(); // "jks"; private static final string client_keystore_path = "mykeystore.jks"; private static final string client_keystore_pass = "secret"; private static final string https_url = "https://testidp:8110/idp/profile/saml2/soap/artifactresolution"; public static void main(string[] args) throws exception { sslconnectionsocketfactory csf = new sslconnectionsocketfactory(createsslcustomcontext(), new string[] { "tlsv1" }, null, sslconnectionsocketfactory.getdefaulthostnameverifier()); try (closeablehttpclient httpclient = httpclients.custom().setsslsocketfactory(csf).build()) { httpget req = new httpget(https_url); try (closeablehttpresponse response = httpclient.execute(req)) { httpentity entity = response.getentity(); system.out.println(string.format("reponse status: %s", response.getstatusline())); system.out.println(string.format("response entity: %s", entity.tostring())); bufferedreader in = new bufferedreader(new inputstreamreader(entity.getcontent())); string line = null; while ((line = in.readline()) != null) { system.out.println(line); } entityutils.consume(entity); } } } private static sslcontext createsslcustomcontext() throws keystoreexception, ioexception, nosuchalgorithmexception, certificateexception, keymanagementexception, unrecoverablekeyexception { // trusted ca keystore keystore tks = keystore.getinstance(ca_keystore_type); tks.load(new fileinputstream(ca_keystore_path), ca_keystore_pass.tochararray()); // client keystore keystore cks = keystore.getinstance(client_keystore_type); cks.load(new fileinputstream(client_keystore_path), client_keystore_pass.tochararray()); sslcontext sslcontext = sslcontexts.custom().loadtrustmaterial(tks, new trustselfsignedstrategy()) .loadkeymaterial(cks, client_keystore_pass.tochararray()) .build(); return sslcontext; } } however, don't know how configure spring saml's tlsprotocolconfigurer correctly (or whatever needed use client key).
so, how can tell spring security saml use client key client authentication in tls/ssl connections?
ok, figured out how enable clientauth in tls connections spring saml. service provider config securitycontext.xml:
<bean class="org.springframework.security.saml.metadata.extendedmetadatadelegate"> <constructor-arg> <bean class="org.opensaml.saml2.metadata.provider.filesystemmetadataprovider"> <constructor-arg> <value type="java.io.file">classpath:metadata/sp.xml</value> </constructor-arg> <property name="parserpool" ref="parserpool" /> </bean> </constructor-arg> <constructor-arg> <bean class="org.springframework.security.saml.metadata.extendedmetadata"> <property name="local" value="true" /> <property name="signmetadata" value="true" /> <property name="signingkey" value="mykey" /> <property name="encryptionkey" value="mykey" /> <property name="tlskey" value="mykey" /> </bean> </constructor-arg> </bean> clientauth enabled setting client key via <property name="tlskey" value="mykey" />
the key has declared in jkskeymanager usual:
<bean id="keymanager" class="org.springframework.security.saml.key.jkskeymanager"> <constructor-arg value="classpath:security/keystore.jks" /> <constructor-arg type="java.lang.string" value="secret" /> <constructor-arg> <map> <entry key="mykey" value="secret" /> </map> </constructor-arg> <constructor-arg type="java.lang.string" value="mykey" /> </bean> this mentioned in docs here "populate credential used ssl/tls client authentication. in case extendedmetadata specifies property tlskey used alias lookup key keymanager bean. otherwise no credential provided client authentication." took me while find ;-)
Comments
Post a Comment