Repository: cxf-fediz Updated Branches: refs/heads/master fe30273fd -> f49b28e67
Adding support for client certificate authentication in the IdP Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/23cc34fc Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/23cc34fc Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/23cc34fc Branch: refs/heads/master Commit: 23cc34fc05f3b38b1a68098fdf404aed4e608efc Parents: fe30273 Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Thu Mar 5 17:20:21 2015 +0000 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Thu Mar 5 17:20:21 2015 +0000 ---------------------------------------------------------------------- pom.xml | 2 +- .../service/idp/STSAuthenticationProvider.java | 61 ++++++++++++++++++- .../service/sts/FedizX509DelegationHandler.java | 63 ++++++++++++++++++++ .../src/main/webapp/WEB-INF/cxf-transport.xml | 11 +++- 4 files changed, 131 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/23cc34fc/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 4173077..8b03090 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ <properties> <commons.lang.version>3.3.2</commons.lang.version> <commons.logging.version>1.1.3</commons.logging.version> - <cxf.version>3.0.4</cxf.version> + <cxf.version>3.0.5-SNAPSHOT</cxf.version> <cxf.build-utils.version>3.0.0</cxf.build-utils.version> <easymock.version>3.3</easymock.version> <ehcache.version>2.8.5</ehcache.version> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/23cc34fc/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/STSAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/STSAuthenticationProvider.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/STSAuthenticationProvider.java index af76d64..bdd7727 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/STSAuthenticationProvider.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/STSAuthenticationProvider.java @@ -21,6 +21,7 @@ package org.apache.cxf.fediz.service.idp; import java.net.URI; import java.security.Principal; import java.security.PrivilegedActionException; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -29,8 +30,10 @@ import java.util.Map; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; +import javax.servlet.http.HttpServletRequest; import javax.xml.namespace.QName; +import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; @@ -40,6 +43,8 @@ import org.apache.cxf.fediz.core.ClaimTypes; import org.apache.cxf.fediz.service.idp.kerberos.KerberosServiceRequestToken; import org.apache.cxf.fediz.service.idp.kerberos.KerberosTokenValidator; import org.apache.cxf.fediz.service.idp.kerberos.PassThroughKerberosClient; +import org.apache.cxf.fediz.service.idp.util.WebUtils; +import org.apache.cxf.helpers.DOMUtils; //import org.apache.cxf.transport.http.HTTPConduit; //import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.apache.cxf.ws.security.SecurityConstants; @@ -48,6 +53,8 @@ import org.apache.wss4j.common.kerberos.KerberosServiceContext; import org.apache.wss4j.common.principal.SAMLTokenPrincipalImpl; import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.dom.WSConstants; +import org.apache.xml.security.exceptions.XMLSecurityException; +import org.apache.xml.security.keys.content.X509Data; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSException; @@ -63,6 +70,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; public class STSAuthenticationProvider implements AuthenticationProvider { @@ -109,6 +117,9 @@ public class STSAuthenticationProvider implements AuthenticationProvider { private boolean requireDelegation; + private String technicalUser; + private String technicalPassword; + @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { @@ -145,6 +156,26 @@ public class STSAuthenticationProvider implements AuthenticationProvider { kerberosClient.setToken(((KerberosServiceRequestToken)authentication).getToken()); sts.getProperties().put(SecurityConstants.KERBEROS_CLIENT, kerberosClient); } + } else if (authentication instanceof PreAuthenticatedAuthenticationToken) { + sts.getProperties().put(SecurityConstants.USERNAME, technicalUser); + sts.getProperties().put(SecurityConstants.PASSWORD, technicalPassword); + + X509Certificate cert = + (X509Certificate)((PreAuthenticatedAuthenticationToken)authentication).getCredentials(); + if (cert == null) { + return null; + } + + // Convert the received certificate to a DOM Element to write it out "OnBehalfOf" + Document doc = DOMUtils.newDocument(); + X509Data certElem = new X509Data(doc); + try { + certElem.addCertificate(cert); + sts.setOnBehalfOf(certElem.getElement()); + } catch (XMLSecurityException e) { + LOG.debug("Error parsing a client certificate", e); + return null; + } } else { sts.getProperties().put(SecurityConstants.USERNAME, authentication.getName()); sts.getProperties().put(SecurityConstants.PASSWORD, (String)authentication.getCredentials()); @@ -213,6 +244,16 @@ public class STSAuthenticationProvider implements AuthenticationProvider { LOG.debug("[IDP_TOKEN={}] provided for user '{}'", token.getId(), kerberosPrincipal.getName()); return ksrt; + } else if (authentication instanceof PreAuthenticatedAuthenticationToken) { + STSUserDetails details = new STSUserDetails(authentication.getName(), + "", + authorities, + token); + + ((PreAuthenticatedAuthenticationToken)authentication).setDetails(details); + + LOG.debug("[IDP_TOKEN={}] provided for user '{}'", token.getId(), authentication.getName()); + return authentication; } else { UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken( authentication.getName(), authentication.getCredentials(), authorities); @@ -297,10 +338,10 @@ public class STSAuthenticationProvider implements AuthenticationProvider { } - @Override public boolean supports(Class<?> authentication) { - return authentication.equals(UsernamePasswordAuthenticationToken.class) + return authentication.equals(PreAuthenticatedAuthenticationToken.class) + || authentication.equals(UsernamePasswordAuthenticationToken.class) || authentication.equals(KerberosServiceRequestToken.class); } @@ -503,6 +544,22 @@ public class STSAuthenticationProvider implements AuthenticationProvider { this.requireDelegation = requireDelegation; } + public String getTechnicalPassword() { + return technicalPassword; + } + + public void setTechnicalPassword(String technicalPassword) { + this.technicalPassword = technicalPassword; + } + + public String getTechnicalUser() { + return technicalUser; + } + + public void setTechnicalUser(String technicalUser) { + this.technicalUser = technicalUser; + } + //May be uncommented for debugging // private void setTimeout(Client client, Long timeout) { // HTTPConduit conduit = (HTTPConduit) client.getConduit(); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/23cc34fc/services/sts/src/main/java/org/apache/cxf/fediz/service/sts/FedizX509DelegationHandler.java ---------------------------------------------------------------------- diff --git a/services/sts/src/main/java/org/apache/cxf/fediz/service/sts/FedizX509DelegationHandler.java b/services/sts/src/main/java/org/apache/cxf/fediz/service/sts/FedizX509DelegationHandler.java new file mode 100644 index 0000000..a597cf3 --- /dev/null +++ b/services/sts/src/main/java/org/apache/cxf/fediz/service/sts/FedizX509DelegationHandler.java @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.cxf.fediz.service.sts; + +import org.w3c.dom.Element; +import org.apache.cxf.sts.request.ReceivedToken; +import org.apache.cxf.sts.request.ReceivedToken.STATE; +import org.apache.cxf.sts.token.delegation.TokenDelegationHandler; +import org.apache.cxf.sts.token.delegation.TokenDelegationParameters; +import org.apache.cxf.sts.token.delegation.TokenDelegationResponse; +import org.apache.wss4j.dom.WSConstants; + +/** + * A delegation handler to allow X.509 Certificates. + */ +public class FedizX509DelegationHandler implements TokenDelegationHandler { + + public boolean canHandleToken(ReceivedToken delegateTarget) { + Object token = delegateTarget.getToken(); + if (token instanceof Element) { + Element tokenElement = (Element)token; + String namespace = tokenElement.getNamespaceURI(); + String localname = tokenElement.getLocalName(); + if ((WSConstants.SIG_NS.equals(namespace) && WSConstants.X509_DATA_LN.equals(localname))) { + return true; + } + } + return false; + } + + public TokenDelegationResponse isDelegationAllowed(TokenDelegationParameters tokenParameters) { + TokenDelegationResponse response = new TokenDelegationResponse(); + ReceivedToken delegateTarget = tokenParameters.getToken(); + response.setToken(delegateTarget); + + if (!delegateTarget.isDOMElement()) { + return response; + } + + if (delegateTarget.getState() == STATE.VALID && delegateTarget.getPrincipal() != null) { + response.setDelegationAllowed(true); + } + + return response; + } + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/23cc34fc/services/sts/src/main/webapp/WEB-INF/cxf-transport.xml ---------------------------------------------------------------------- diff --git a/services/sts/src/main/webapp/WEB-INF/cxf-transport.xml b/services/sts/src/main/webapp/WEB-INF/cxf-transport.xml index 6eec84f..1ddd388 100644 --- a/services/sts/src/main/webapp/WEB-INF/cxf-transport.xml +++ b/services/sts/src/main/webapp/WEB-INF/cxf-transport.xml @@ -57,8 +57,12 @@ </cxf:features> </cxf:bus> - <bean id="samlDelegationHandler" - class="org.apache.cxf.fediz.service.sts.FedizSAMLDelegationHandler" /> + <util:list id="delegationHandlers"> + <bean id="samlDelegationHandler" + class="org.apache.cxf.fediz.service.sts.FedizSAMLDelegationHandler" /> + <bean id="x509DelegationHandler" + class="org.apache.cxf.fediz.service.sts.FedizX509DelegationHandler" /> + </util:list> <bean id="transportSTSProviderBean" class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider"> @@ -73,7 +77,7 @@ <property name="claimsManager" ref="claimsManager" /> <property name="tokenValidators" ref="transportTokenValidators" /> <property name="eventListener" ref="loggerListener" /> - <property name="delegationHandlers" ref="samlDelegationHandler" /> + <property name="delegationHandlers" ref="delegationHandlers" /> <property name="encryptIssuedToken" value="true"/> </bean> @@ -104,6 +108,7 @@ <util:list id="transportTokenValidators"> <ref bean="transportSamlTokenValidator" /> + <bean class="org.apache.cxf.sts.token.validator.X509TokenValidator" /> </util:list> <bean id="realmA" class="org.apache.cxf.sts.token.realm.SAMLRealm">