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

Popular posts from this blog

authentication - Mongodb revoke acccess to connect test database -

r - Update two sets of radiobuttons reactively - shiny -

ios - Realm over CoreData should I use NSFetchedResultController or a Dictionary? -