You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2015/03/16 18:51:29 UTC
[1/4] cxf-fediz git commit: Adding a switch to sign a request to a
trusted IdP
Repository: cxf-fediz
Updated Branches:
refs/heads/master ecd25ab9d -> 799afc9a2
Adding a switch to sign a request to a trusted 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/fd366100
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/fd366100
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/fd366100
Branch: refs/heads/master
Commit: fd366100082d221c1c8b75cc85552b6d04ee4afc
Parents: ecd25ab
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 15:55:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 15:55:50 2015 +0000
----------------------------------------------------------------------
.../cxf/fediz/service/idp/domain/TrustedIdp.java | 13 ++++++++++++-
.../service/idp/service/jpa/TrustedIdpEntity.java | 11 +++++++++++
.../cxf/fediz/service/idp/util/MetadataWriter.java | 3 ++-
3 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
index dbdea59..6469372 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
@@ -26,7 +26,7 @@ import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "trustedIdp", namespace = "http://org.apache.cxf.fediz/")
@XmlType(propOrder = {"realm", "url", "name", "description", "protocol", "trustType",
- "certificate", "federationType", "cacheTokens", "logo", "id" })
+ "certificate", "federationType", "cacheTokens", "logo", "id", "signRequest" })
//@XmlAttribute on Id must be set on getter, not on attribute, otherwise error
public class TrustedIdp implements Serializable {
@@ -68,6 +68,9 @@ public class TrustedIdp implements Serializable {
//optional (to provide a list of IDPs)
protected String logo;
+
+ // Whether to sign a request to the trusted IdP or not
+ private boolean signRequest;
@XmlAttribute
@@ -158,6 +161,14 @@ public class TrustedIdp implements Serializable {
public void setTrustType(TrustType trustType) {
this.trustType = trustType;
}
+
+ public boolean isSignRequest() {
+ return signRequest;
+ }
+
+ public void setSignRequest(boolean signRequest) {
+ this.signRequest = signRequest;
+ }
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
index 7f41186..11785c7 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
@@ -76,6 +76,9 @@ public class TrustedIdpEntity {
//optional (to provide a list of IDPs)
private String logo;
+ // Whether to sign a request to the trusted IdP or not
+ private boolean signRequest;
+
public int getId() {
return id;
@@ -165,4 +168,12 @@ public class TrustedIdpEntity {
this.trustType = trustType;
}
+ public boolean isSignRequest() {
+ return signRequest;
+ }
+
+ public void setSignRequest(boolean signRequest) {
+ this.signRequest = signRequest;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
index bc34ab4..bcc7e37 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
@@ -104,7 +104,8 @@ public class MetadataWriter {
writer.writeStartElement("", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
try {
- X509Certificate cert = CertsUtils.getX509Certificate(crypto, null);
+ String keyAlias = crypto.getDefaultX509Identifier();
+ X509Certificate cert = CertsUtils.getX509Certificate(crypto, keyAlias);
writer.writeCharacters(Base64.encode(cert.getEncoded()));
} catch (Exception ex) {
LOG.error("Failed to add certificate information to metadata. Metadata incomplete", ex);
[3/4] cxf-fediz git commit: Systest update as part of last commit
Posted by co...@apache.org.
Systest update as part of last commit
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/a18bc7c1
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/a18bc7c1
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/a18bc7c1
Branch: refs/heads/master
Commit: a18bc7c1667deaf9af6c352e0ae764a20ce95f31
Parents: 03d9a99
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 16:24:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 16:24:50 2015 +0000
----------------------------------------------------------------------
systests/federation/samlsso/src/test/resources/entities-realma.xml | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/a18bc7c1/systests/federation/samlsso/src/test/resources/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/resources/entities-realma.xml b/systests/federation/samlsso/src/test/resources/entities-realma.xml
index 8f8f319..649b88c 100644
--- a/systests/federation/samlsso/src/test/resources/entities-realma.xml
+++ b/systests/federation/samlsso/src/test/resources/entities-realma.xml
@@ -88,6 +88,7 @@
<property name="federationType" value="FEDERATE_IDENTITY" />
<property name="name" value="Realm B" />
<property name="description" value="Realm B description" />
+ <property name="signRequest" value="true" />
</bean>
<bean id="srv-fedizhelloworld" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
[4/4] cxf-fediz git commit: Properly validate SAML SSO responses
Posted by co...@apache.org.
Properly validate SAML SSO responses
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/799afc9a
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/799afc9a
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/799afc9a
Branch: refs/heads/master
Commit: 799afc9a2ad771eebc42533c6d4727642948ca42
Parents: a18bc7c
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 17:45:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 17:45:50 2015 +0000
----------------------------------------------------------------------
.../TrustedIdpSAMLProtocolHandler.java | 222 +++++++------------
1 file changed, 80 insertions(+), 142 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/799afc9a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
index 18465f8..2cc03c3 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
@@ -19,7 +19,6 @@
package org.apache.cxf.fediz.service.idp.protocols;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -29,6 +28,8 @@ import java.net.URL;
import java.net.URLEncoder;
import java.security.PrivateKey;
import java.security.Signature;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.zip.DataFormatException;
@@ -38,10 +39,12 @@ import javax.ws.rs.core.UriBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+
import org.apache.cxf.common.util.Base64Exception;
import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
import org.apache.cxf.fediz.core.util.CertsUtils;
import org.apache.cxf.fediz.service.idp.domain.Idp;
import org.apache.cxf.fediz.service.idp.domain.TrustedIdp;
@@ -52,15 +55,18 @@ import org.apache.cxf.jaxrs.utils.ExceptionUtils;
import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
import org.apache.cxf.rs.security.saml.sso.AuthnRequestBuilder;
import org.apache.cxf.rs.security.saml.sso.DefaultAuthnRequestBuilder;
+import org.apache.cxf.rs.security.saml.sso.SAMLProtocolResponseValidator;
+import org.apache.cxf.rs.security.saml.sso.SAMLSSOResponseValidator;
import org.apache.cxf.rs.security.saml.sso.SSOConstants;
+import org.apache.cxf.rs.security.saml.sso.SSOValidatorResponse;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.wss4j.common.crypto.CertificateStore;
import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.util.DOM2Writer;
-import org.apache.wss4j.common.util.XMLUtils;
-import org.apache.wss4j.dom.WSConstants;
import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.apache.xml.security.utils.Base64;
import org.opensaml.saml2.core.AuthnRequest;
@@ -147,37 +153,29 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
public SecurityToken mapSignInResponse(RequestContext context, Idp idp, TrustedIdp trustedIdp) {
try {
- String relayState = (String) WebUtils.getAttributeFromFlowScope(context,
- SSOConstants.RELAY_STATE);
+ //String relayState = (String) WebUtils.getAttributeFromFlowScope(context,
+ // SSOConstants.RELAY_STATE);
// TODO Validate RelayState
- System.out.println("RS: " + relayState);
String encodedSAMLResponse = (String) WebUtils.getAttributeFromFlowScope(context,
SSOConstants.SAML_RESPONSE);
// Read the response + convert to an OpenSAML Response Object
- Element responseElement = readSAMLResponse(false, encodedSAMLResponse);
- // org.opensaml.saml2.core.Response samlResponse = convertToResponse(responseElement);
-
+ org.opensaml.saml2.core.Response samlResponse = readSAMLResponse(encodedSAMLResponse);
+
+ Crypto crypto = getCrypto(trustedIdp.getCertificate());
+ validateSamlResponseProtocol(samlResponse, crypto);
// Validate the Response
- /*
- * TODOvalidateSamlResponseProtocol(samlResponse);
SSOValidatorResponse validatorResponse =
- validateSamlSSOResponse(false, samlResponse, requestState);
+ validateSamlSSOResponse(samlResponse, idp, trustedIdp, context);
- String assertion = validatorResponse.getAssertion();
- SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion);
- */
- Element assertionElement =
- XMLUtils.getDirectChildElement(responseElement, "Assertion", WSConstants.SAML2_NS);
// Create new Security token with new id.
// Parameters for freshness computation are copied from original IDP_TOKEN
String id = IDGenerator.generateID("_");
- SecurityToken idpToken = new SecurityToken(id);
- // new SecurityToken(id, new Date(), validatorResponse.getSessionNotOnOrAfter());
- // TODO new Date() above incorrect
+ SecurityToken idpToken =
+ new SecurityToken(id, validatorResponse.getCreated(), validatorResponse.getSessionNotOnOrAfter());
- idpToken.setToken(assertionElement);
+ idpToken.setToken(validatorResponse.getAssertionElement());
// LOG.info("[IDP_TOKEN={}] for user '{}' created from [RP_TOKEN={}] issued by home realm [{}/{}]",
// id, wfResp.getUsername(), wfResp.getUniqueTokenId(), whr, wfResp.getIssuer());
//.debug("Created date={}", wfResp.getTokenCreated());
@@ -213,7 +211,7 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
Idp config,
UriBuilder ub
) throws Exception {
- Crypto crypto = CertsUtils.createCrypto(config.getCertificate());
+ Crypto crypto = getCrypto(config.getCertificate());
if (crypto == null) {
LOG.error("No crypto instance of properties file configured for signature");
throw new IllegalStateException("Invalid IdP configuration");
@@ -261,44 +259,57 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
ub.queryParam(SSOConstants.SIGNATURE, URLEncoder.encode(encodedSignature, "UTF-8"));
}
-
- private Element readSAMLResponse(
- boolean postBinding, String samlResponse
- ) {
+ private Crypto getCrypto(String certificate) throws ProcessingException {
+ if (certificate == null) {
+ return null;
+ }
+
+ // First see if it's a certificate file
+ InputStream is = null;
+ try {
+ is = Merlin.loadInputStream(Thread.currentThread().getContextClassLoader(), certificate);
+
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is);
+ return new CertificateStore(new X509Certificate[]{cert});
+ } catch (WSSecurityException ex) {
+ LOG.error("Failed to load keystore " + certificate, ex);
+ throw new RuntimeException("Failed to load keystore " + certificate);
+ } catch (IOException ex) {
+ LOG.error("Failed to read keystore", ex);
+ throw new RuntimeException("Failed to read keystore");
+ } catch (CertificateException ex) {
+ // This is ok as it could be a WSS4J properties file
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // Do nothing
+ }
+ }
+ }
+
+ // Maybe it's a WSS4J properties file...
+ return CertsUtils.createCrypto(certificate);
+ }
+
+ private org.opensaml.saml2.core.Response readSAMLResponse(String samlResponse) {
if (StringUtils.isEmpty(samlResponse)) {
throw ExceptionUtils.toBadRequestException(null, null);
}
String samlResponseDecoded = samlResponse;
- /*
- // URL Decoding only applies for the re-direct binding
- if (!postBinding) {
- try {
- samlResponseDecoded = URLDecoder.decode(samlResponse, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw ExceptionUtils.toBadRequestException(null, null);
- }
- }
- */
+
InputStream tokenStream = null;
- // (isSupportBase64Encoding()) { TODO
try {
byte[] deflatedToken = Base64Utility.decode(samlResponseDecoded);
- tokenStream = !postBinding //&& isSupportDeflateEncoding()
- ? new DeflateEncoderDecoder().inflateToken(deflatedToken)
- : new ByteArrayInputStream(deflatedToken);
+ tokenStream = new DeflateEncoderDecoder().inflateToken(deflatedToken);
} catch (Base64Exception ex) {
throw ExceptionUtils.toBadRequestException(ex, null);
} catch (DataFormatException ex) {
throw ExceptionUtils.toBadRequestException(ex, null);
}
- /*} else { TODO
- try {
- tokenStream = new ByteArrayInputStream(samlResponseDecoded.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException ex) {
- throw ExceptionUtils.toBadRequestException(ex, null);
- }
- }*/
Document responseDoc = null;
try {
@@ -306,17 +317,12 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
} catch (Exception ex) {
throw new WebApplicationException(400);
}
-
+
LOG.debug("Received response: " + DOM2Writer.nodeToString(responseDoc.getDocumentElement()));
- return responseDoc.getDocumentElement();
-
- }
-
- protected org.opensaml.saml2.core.Response convertToResponse(Element samlResponseElement) {
XMLObject responseObject = null;
try {
- responseObject = OpenSAMLUtil.fromDom(samlResponseElement);
+ responseObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
} catch (WSSecurityException ex) {
throw ExceptionUtils.toBadRequestException(ex, null);
}
@@ -324,122 +330,54 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
throw ExceptionUtils.toBadRequestException(null, null);
}
return (org.opensaml.saml2.core.Response)responseObject;
- }
+ }
+
/**
* Validate the received SAML Response as per the protocol
- protected void validateSamlResponseProtocol(
- org.opensaml.saml2.core.Response samlResponse
+ */
+ private void validateSamlResponseProtocol(
+ org.opensaml.saml2.core.Response samlResponse, Crypto crypto
) {
try {
SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator();
- protocolValidator.setKeyInfoMustBeAvailable(true); // TODO
- protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), null);
+ protocolValidator.setKeyInfoMustBeAvailable(true);
+ protocolValidator.validateSamlResponse(samlResponse, crypto, null);
} catch (WSSecurityException ex) {
LOG.debug(ex.getMessage(), ex);
+ ex.printStackTrace();
throw ExceptionUtils.toBadRequestException(null, null);
}
}
- */
+
/**
* Validate the received SAML Response as per the Web SSO profile
- protected SSOValidatorResponse validateSamlSSOResponse(
- boolean postBinding,
+ */
+ private SSOValidatorResponse validateSamlSSOResponse(
org.opensaml.saml2.core.Response samlResponse,
Idp idp,
- TrustedIdp trustedIdp
+ TrustedIdp trustedIdp,
+ RequestContext requestContext
) {
try {
SAMLSSOResponseValidator ssoResponseValidator = new SAMLSSOResponseValidator();
- ssoResponseValidator.setAssertionConsumerURL(idp.getIdpUrl());
+ ssoResponseValidator.setAssertionConsumerURL(idp.getIdpUrl().toString());
- // ssoResponseValidator.setClientAddress(client_ip);
+ HttpServletRequest servletRequest = WebUtils.getHttpServletRequest(requestContext);
+ ssoResponseValidator.setClientAddress(servletRequest.getRemoteAddr());
ssoResponseValidator.setIssuerIDP(trustedIdp.getUrl());
- // ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
+ // TODO ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
ssoResponseValidator.setSpIdentifier(idp.getRealm());
- ssoResponseValidator.setEnforceAssertionsSigned(true); // TODO
- // ssoResponseValidator.setEnforceKnownIssuer(enforceKnownIssuer);
+ ssoResponseValidator.setEnforceAssertionsSigned(true);
+ ssoResponseValidator.setEnforceKnownIssuer(true);
- return ssoResponseValidator.validateSamlResponse(samlResponse, postBinding);
+ return ssoResponseValidator.validateSamlResponse(samlResponse, false);
} catch (WSSecurityException ex) {
LOG.debug(ex.getMessage(), ex);
throw ExceptionUtils.toBadRequestException(ex, null);
}
}
- */
-
-/*
- private FedizContext getFedizContext(Idp idpConfig,
- TrustedIdp trustedIdpConfig) throws ProcessingException {
-
- ContextConfig config = new ContextConfig();
-
- config.setName("whatever");
-
- // Configure certificate store
- String certificate = trustedIdpConfig.getCertificate();
- boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE");
- if (isCertificateLocation) {
- CertificateStores certStores = new CertificateStores();
- TrustManagersType tm0 = new TrustManagersType();
- KeyStoreType ks0 = new KeyStoreType();
- ks0.setType("PEM");
- // ks0.setType("JKS");
- // ks0.setPassword("changeit");
- ks0.setFile(trustedIdpConfig.getCertificate());
- tm0.setKeyStore(ks0);
- certStores.getTrustManager().add(tm0);
- config.setCertificateStores(certStores);
- }
-
- // Configure trusted IDP
- TrustedIssuers trustedIssuers = new TrustedIssuers();
- TrustedIssuerType ti0 = new TrustedIssuerType();
- ti0.setCertificateValidation(ValidationType.PEER_TRUST);
- ti0.setName(trustedIdpConfig.getName());
- // ti0.setSubject(".*CN=www.sts.com.*");
- trustedIssuers.getIssuer().add(ti0);
- config.setTrustedIssuers(trustedIssuers);
-
- FederationProtocolType protocol = new FederationProtocolType();
- config.setProtocol(protocol);
-
- AudienceUris audienceUris = new AudienceUris();
- audienceUris.getAudienceItem().add(idpConfig.getRealm());
- config.setAudienceUris(audienceUris);
-
- FedizContext fedContext = new FedizContext(config);
- if (!isCertificateLocation) {
- CertificateStore cs = null;
-
- X509Certificate cert;
- try {
- cert = parseCertificate(trustedIdpConfig.getCertificate());
- } catch (Exception ex) {
- LOG.error("Failed to parse trusted certificate", ex);
- throw new ProcessingException("Failed to parse trusted certificate");
- }
- cs = new CertificateStore(Collections.singletonList(cert).toArray(new X509Certificate[0]));
-
- TrustManager tm = new TrustManager(cs);
- fedContext.getCertificateStores().add(tm);
- }
- fedContext.init();
- return fedContext;
- }
-
- private X509Certificate parseCertificate(String certificate)
- throws CertificateException, Base64DecodingException {
-
- //before decoding we need to get rod off the prefix and suffix
- byte [] decoded = Base64.decode(certificate.replaceAll("-----BEGIN CERTIFICATE-----", "").
- replaceAll("-----END CERTIFICATE-----", ""));
-
- return (X509Certificate)CertificateFactory.getInstance("X.509").
- generateCertificate(new ByteArrayInputStream(decoded));
- }
-*/
}
[2/4] cxf-fediz git commit: Add the ability to sign SAML SSO requests
Posted by co...@apache.org.
Add the ability to sign SAML SSO requests
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/03d9a99c
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/03d9a99c
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/03d9a99c
Branch: refs/heads/master
Commit: 03d9a99c93dccf8d4faf17722ef26d0e7d858f30
Parents: fd36610
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 16:24:16 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 16:24:16 2015 +0000
----------------------------------------------------------------------
.../TrustedIdpSAMLProtocolHandler.java | 102 +++++++++++++++----
.../idp/service/jpa/TrustedIdpDAOJPAImpl.java | 5 +-
2 files changed, 85 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/03d9a99c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
index e1b8879..18465f8 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
@@ -27,6 +27,9 @@ import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
import java.util.zip.DataFormatException;
import javax.servlet.http.HttpServletRequest;
@@ -39,6 +42,7 @@ import org.apache.cxf.common.util.Base64Exception;
import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.util.CertsUtils;
import org.apache.cxf.fediz.service.idp.domain.Idp;
import org.apache.cxf.fediz.service.idp.domain.TrustedIdp;
import org.apache.cxf.fediz.service.idp.spi.TrustedIdpProtocolHandler;
@@ -51,12 +55,14 @@ import org.apache.cxf.rs.security.saml.sso.DefaultAuthnRequestBuilder;
import org.apache.cxf.rs.security.saml.sso.SSOConstants;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.util.DOM2Writer;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.xml.security.stax.impl.util.IDGenerator;
+import org.apache.xml.security.utils.Base64;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.xml.XMLObject;
import org.slf4j.Logger;
@@ -100,9 +106,9 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
authnRequestBuilder.createAuthnRequest(
null, idp.getRealm(), idp.getIdpUrl().toString()
);
- // if (isSignRequest()) {
- // authnRequest.setDestination(idpServiceAddress);
- //}
+ if (trustedIdp.isSignRequest()) {
+ authnRequest.setDestination(trustedIdp.getUrl());
+ }
Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc);
String authnRequestEncoded = encodeAuthnRequest(authnRequestElement);
@@ -116,15 +122,13 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
if (wctx != null) {
ub.queryParam(SSOConstants.RELAY_STATE, wctx);
}
- //if (isSignRequest()) {
- // signRequest(urlEncodedRequest, info.getRelayState(), ub);
- //}
-
- /*context.abortWith(Response.seeOther(ub.build())
- .header(HttpHeaders.CACHE_CONTROL, "no-cache, no-store")
- .header("Pragma", "no-cache")
- .build());*/
+ if (trustedIdp.isSignRequest()) {
+ signRequest(urlEncodedRequest, wctx, idp, ub);
+ }
+ // TODO How to set headers here?
+ // .header(HttpHeaders.CACHE_CONTROL, "no-cache, no-store")
+ // .header("Pragma", "no-cache")
return ub.build().toURL();
} catch (MalformedURLException ex) {
LOG.error("Invalid Redirect URL for Trusted Idp", ex);
@@ -139,15 +143,6 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
}
- protected String encodeAuthnRequest(Element authnRequest) throws IOException {
- String requestMessage = DOM2Writer.nodeToString(authnRequest);
-
- DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
- byte[] deflatedBytes = encoder.deflateToken(requestMessage.getBytes("UTF-8"));
-
- return Base64Utility.encode(deflatedBytes);
- }
-
@Override
public SecurityToken mapSignInResponse(RequestContext context, Idp idp, TrustedIdp trustedIdp) {
@@ -199,6 +194,73 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
throw new IllegalStateException("Unexpected exception occured: " + ex.getMessage());
}
}
+
+ private String encodeAuthnRequest(Element authnRequest) throws IOException {
+ String requestMessage = DOM2Writer.nodeToString(authnRequest);
+
+ DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
+ byte[] deflatedBytes = encoder.deflateToken(requestMessage.getBytes("UTF-8"));
+
+ return Base64Utility.encode(deflatedBytes);
+ }
+
+ /**
+ * Sign a request according to the redirect binding spec for Web SSO
+ */
+ private void signRequest(
+ String authnRequest,
+ String relayState,
+ Idp config,
+ UriBuilder ub
+ ) throws Exception {
+ Crypto crypto = CertsUtils.createCrypto(config.getCertificate());
+ if (crypto == null) {
+ LOG.error("No crypto instance of properties file configured for signature");
+ throw new IllegalStateException("Invalid IdP configuration");
+ }
+
+ String alias = crypto.getDefaultX509Identifier();
+ X509Certificate cert = CertsUtils.getX509Certificate(crypto, alias);
+ if (cert == null) {
+ LOG.error("No cert was found to sign the request using alias: " + alias);
+ throw new IllegalStateException("Invalid IdP configuration");
+ }
+
+ String sigAlgo = SSOConstants.RSA_SHA1;
+ String pubKeyAlgo = cert.getPublicKey().getAlgorithm();
+ String jceSigAlgo = "SHA1withRSA";
+ LOG.debug("automatic sig algo detection: " + pubKeyAlgo);
+ if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+ sigAlgo = SSOConstants.DSA_SHA1;
+ jceSigAlgo = "SHA1withDSA";
+ }
+ LOG.debug("Using Signature algorithm " + sigAlgo);
+
+ ub.queryParam(SSOConstants.SIG_ALG, URLEncoder.encode(sigAlgo, "UTF-8"));
+
+ // Get the password
+ String password = config.getCertificatePassword();
+
+ // Get the private key
+ PrivateKey privateKey = crypto.getPrivateKey(alias, password);
+
+ // Sign the request
+ Signature signature = Signature.getInstance(jceSigAlgo);
+ signature.initSign(privateKey);
+
+ String requestToSign =
+ SSOConstants.SAML_REQUEST + "=" + authnRequest + "&"
+ + SSOConstants.RELAY_STATE + "=" + relayState + "&"
+ + SSOConstants.SIG_ALG + "=" + URLEncoder.encode(sigAlgo, "UTF-8");
+
+ signature.update(requestToSign.getBytes("UTF-8"));
+ byte[] signBytes = signature.sign();
+
+ String encodedSignature = Base64.encode(signBytes);
+
+ ub.queryParam(SSOConstants.SIGNATURE, URLEncoder.encode(encodedSignature, "UTF-8"));
+ }
+
private Element readSAMLResponse(
boolean postBinding, String samlResponse
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/03d9a99c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
index 8d0f208..a7b5472 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
@@ -54,8 +54,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
Query query = null;
query = em.createQuery("select t from TrustedIDP t");
- //@SuppressWarnings("rawtypes")
- List idpEntities = query
+ List<?> idpEntities = query
.setFirstResult(start)
.setMaxResults(size)
.getResultList();
@@ -130,6 +129,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
entity.setRealm(trustedIDP.getRealm());
entity.setTrustType(trustedIDP.getTrustType());
entity.setUrl(trustedIDP.getUrl());
+ entity.setSignRequest(trustedIDP.isSignRequest());
}
public static TrustedIdp entity2domain(TrustedIdpEntity entity) {
@@ -145,6 +145,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
trustedIDP.setRealm(entity.getRealm());
trustedIDP.setTrustType(entity.getTrustType());
trustedIDP.setUrl(entity.getUrl());
+ trustedIDP.setSignRequest(entity.isSignRequest());
return trustedIDP;
}