cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [7/8] git commit: Refactor of SAMLP authentication creation to start supporting log request creation as well
Date Wed, 01 Oct 2014 07:52:40 GMT
Refactor of SAMLP authentication creation to start supporting log request creation as well


Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/f3887c20
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/f3887c20
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/f3887c20

Branch: refs/heads/master
Commit: f3887c20f664a1a7d5cbc5ab1da7c26b7ed8759d
Parents: be392d3
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Tue Sep 30 18:11:29 2014 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Tue Sep 30 18:11:29 2014 +0100

----------------------------------------------------------------------
 .../cxf/fediz/core/config/SAMLProtocol.java     |  30 ++--
 .../fediz/core/processor/SAMLProcessorImpl.java |  85 +++++++----
 .../fediz/core/samlsso/AuthnRequestBuilder.java |  36 -----
 .../samlsso/DefaultAuthnRequestBuilder.java     | 105 -------------
 .../samlsso/DefaultSAMLPRequestBuilder.java     | 151 +++++++++++++++++++
 .../fediz/core/samlsso/SAMLPRequestBuilder.java |  47 ++++++
 .../samlsso/SamlpRequestComponentBuilder.java   |  48 ++++++
 .../cxf/fediz/core/samlsso/SAMLRequestTest.java |  16 +-
 8 files changed, 331 insertions(+), 187 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java
index ee59a70..d5a04c5 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java
@@ -22,8 +22,8 @@ package org.apache.cxf.fediz.core.config;
 import org.apache.cxf.fediz.core.config.jaxb.ProtocolType;
 import org.apache.cxf.fediz.core.config.jaxb.SamlProtocolType;
 import org.apache.cxf.fediz.core.saml.SAMLTokenValidator;
-import org.apache.cxf.fediz.core.samlsso.AuthnRequestBuilder;
-import org.apache.cxf.fediz.core.samlsso.DefaultAuthnRequestBuilder;
+import org.apache.cxf.fediz.core.samlsso.DefaultSAMLPRequestBuilder;
+import org.apache.cxf.fediz.core.samlsso.SAMLPRequestBuilder;
 import org.apache.wss4j.common.util.Loader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,7 +32,7 @@ public class SAMLProtocol extends Protocol {
 
     private static final Logger LOG = LoggerFactory.getLogger(SAMLProtocol.class);
     
-    private AuthnRequestBuilder authnRequestBuilder;
+    private SAMLPRequestBuilder samlpRequestBuilder;
     
     public SAMLProtocol(ProtocolType protocolType) {
         super(protocolType);
@@ -60,17 +60,17 @@ public class SAMLProtocol extends Protocol {
         getSAMLProtocol().setSignRequest(signRequest);
     }
     
-    public AuthnRequestBuilder getAuthnRequestBuilder() {
-        if (authnRequestBuilder != null) {
-            return authnRequestBuilder;
+    public SAMLPRequestBuilder getSAMLPRequestBuilder() {
+        if (samlpRequestBuilder != null) {
+            return samlpRequestBuilder;
         }
         
-        // See if we have a custom AuthnRequestBuilder
-        String authnRequestBuilderStr = getSAMLProtocol().getAuthnRequestBuilder();
-        if (authnRequestBuilderStr != null && !"".equals(authnRequestBuilderStr))
{
+        // See if we have a custom SAMLPRequestBuilder
+        String samlpRequestBuilderStr = getSAMLProtocol().getAuthnRequestBuilder();
+        if (samlpRequestBuilderStr != null && !"".equals(samlpRequestBuilderStr))
{
             try {
-                Class<?> authnRequestBuilderClass = Loader.loadClass(authnRequestBuilderStr);
-                authnRequestBuilder = (AuthnRequestBuilder) authnRequestBuilderClass.newInstance();
+                Class<?> samlpRequestBuilderClass = Loader.loadClass(samlpRequestBuilderStr);
+                samlpRequestBuilder = (SAMLPRequestBuilder) samlpRequestBuilderClass.newInstance();
             } catch (ClassNotFoundException ex) {
                 LOG.debug(ex.getMessage(), ex);
             } catch (InstantiationException ex) {
@@ -81,13 +81,13 @@ public class SAMLProtocol extends Protocol {
         }
         
         // Default implementation
-        authnRequestBuilder = new DefaultAuthnRequestBuilder();
+        samlpRequestBuilder = new DefaultSAMLPRequestBuilder();
         
-        return authnRequestBuilder;
+        return samlpRequestBuilder;
     }
 
-    public void setAuthnRequestBuilder(AuthnRequestBuilder authnRequestBuilder) {
-        this.authnRequestBuilder = authnRequestBuilder;
+    public void setSAMLPRequestBuilder(SAMLPRequestBuilder requestBuilder) {
+        this.samlpRequestBuilder = requestBuilder;
     }
     
     public boolean isDisableDeflateEncoding() {

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
index 99703af..b3766e8 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java
@@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import org.apache.cxf.fediz.core.FederationConstants;
 import org.apache.cxf.fediz.core.RequestState;
 import org.apache.cxf.fediz.core.SAMLSSOConstants;
 import org.apache.cxf.fediz.core.TokenValidator;
@@ -45,8 +44,8 @@ import org.apache.cxf.fediz.core.config.SAMLProtocol;
 import org.apache.cxf.fediz.core.exception.ProcessingException;
 import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
 import org.apache.cxf.fediz.core.metadata.MetadataWriter;
-import org.apache.cxf.fediz.core.samlsso.AuthnRequestBuilder;
 import org.apache.cxf.fediz.core.samlsso.CompressionUtils;
+import org.apache.cxf.fediz.core.samlsso.SAMLPRequestBuilder;
 import org.apache.cxf.fediz.core.samlsso.SAMLProtocolResponseValidator;
 import org.apache.cxf.fediz.core.samlsso.SAMLSSOResponseValidator;
 import org.apache.cxf.fediz.core.samlsso.SSOValidatorResponse;
@@ -60,6 +59,7 @@ import org.apache.xml.security.exceptions.Base64DecodingException;
 import org.apache.xml.security.utils.Base64;
 import org.opensaml.common.xml.SAMLConstants;
 import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.LogoutRequest;
 import org.opensaml.xml.XMLObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -286,8 +286,8 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
                 redirectURL = issuerURL;
             }
             
-            AuthnRequestBuilder authnRequestBuilder = 
-                ((SAMLProtocol)config.getProtocol()).getAuthnRequestBuilder();
+            SAMLPRequestBuilder samlpRequestBuilder = 
+                ((SAMLProtocol)config.getProtocol()).getSAMLPRequestBuilder();
             
             Document doc = DOMUtils.createDocument();
             doc.appendChild(doc.createElement("root"));
@@ -296,7 +296,7 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
             String requestURL = request.getRequestURL().toString();
             String realm = resolveWTRealm(request, config);
             AuthnRequest authnRequest = 
-                authnRequestBuilder.createAuthnRequest(realm, requestURL);
+                samlpRequestBuilder.createAuthnRequest(realm, requestURL);
             
             if (((SAMLProtocol)config.getProtocol()).isSignRequest()) {
                 authnRequest.setDestination(redirectURL);
@@ -407,7 +407,7 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
     @Override
     public RedirectionResponse createSignOutRequest(HttpServletRequest request, FedizContext
config)
         throws ProcessingException {
-
+        
         String redirectURL = null;
         try {
             if (!(config.getProtocol() instanceof SAMLProtocol)) {
@@ -420,34 +420,63 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor {
             if (issuerURL != null && issuerURL.length() > 0) {
                 redirectURL = issuerURL;
             }
+            redirectURL = "http://localhost:8081/IDBUS/CXF/CXFIDP/SAML2/SLO/REDIR";
+            
+            SAMLPRequestBuilder samlpRequestBuilder = 
+                ((SAMLProtocol)config.getProtocol()).getSAMLPRequestBuilder();
+            
+            Document doc = DOMUtils.createDocument();
+            doc.appendChild(doc.createElement("root"));
+     
+            // Create the LogoutRequest
+            String requestURL = request.getRequestURL().toString();
+            String realm = resolveWTRealm(request, config);
+            String reason = "urn:oasis:names:tc:SAML:2.0:logout:user";
+            LogoutRequest logoutRequest = 
+                samlpRequestBuilder.createLogoutRequest(realm, reason, null); // TODO
+            
+            if (((SAMLProtocol)config.getProtocol()).isSignRequest()) {
+                logoutRequest.setDestination(redirectURL);
+            }
+            
+            Element logoutRequestElement = OpenSAMLUtil.toDom(logoutRequest, doc);
+            String logoutRequestEncoded = encodeAuthnRequest(logoutRequestElement);
+            
+            String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
+            RequestState requestState = new RequestState();
+            requestState.setTargetAddress(requestURL);
+            requestState.setIdpServiceAddress(redirectURL);
+            requestState.setRequestId(logoutRequest.getID());
+            requestState.setIssuerId(realm);
+            requestState.setWebAppContext(logoutRequest.getIssuer().getValue());
+            requestState.setState(relayState);
+            requestState.setCreatedAt(System.currentTimeMillis());
+            
+            String urlEncodedRequest = 
+                URLEncoder.encode(logoutRequestEncoded, "UTF-8");
 
             StringBuilder sb = new StringBuilder();
-            sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNOUT);
-
-            String logoutRedirectTo = config.getLogoutRedirectTo();
-            if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
-
-                if (logoutRedirectTo.startsWith("/")) {
-                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
-                } else {
-                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
-                }
-
-                LOG.debug("wreply=" + logoutRedirectTo);
-
-                sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
-                sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
+            sb.append(SAMLSSOConstants.SAML_REQUEST).append('=').append(urlEncodedRequest);
+            sb.append("&" + SAMLSSOConstants.RELAY_STATE).append('=').append(relayState);
+            
+            if (((SAMLProtocol)config.getProtocol()).isSignRequest()) {
+                String signature = signRequest(config, sb);
+                sb.append("&" + SAMLSSOConstants.SIGNATURE).append('=').append(signature);
             }
-
+            
+            RedirectionResponse response = new RedirectionResponse();
+            response.addHeader("Cache-Control", "no-cache, no-store");
+            response.addHeader("Pragma", "no-cache");
+            response.setRequestState(requestState);
+            
             redirectURL = redirectURL + "?" + sb.toString();
+            response.setRedirectionURL(redirectURL);
+            
+            return response;
         } catch (Exception ex) {
-            LOG.error("Failed to create SignInRequest", ex);
-            throw new ProcessingException("Failed to create SignInRequest");
+            LOG.error("Failed to create SignOutRequest", ex);
+            throw new ProcessingException("Failed to create SignOutRequest");
         }
-        
-        RedirectionResponse response = new RedirectionResponse();
-        response.setRedirectionURL(redirectURL);
-        return response;
     }
     
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/AuthnRequestBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/AuthnRequestBuilder.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/AuthnRequestBuilder.java
deleted file mode 100644
index bae10dc..0000000
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/AuthnRequestBuilder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * 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.core.samlsso;
-
-import org.opensaml.saml2.core.AuthnRequest;
-
-/**
- * This interface defines a method to create a SAML 2.0 Protocol AuthnRequest.
- */
-public interface AuthnRequestBuilder {
-    
-    /**
-     * Create a SAML 2.0 Protocol AuthnRequest
-     */
-    AuthnRequest createAuthnRequest(
-        String issuerId,
-        String assertionConsumerServiceAddress
-    ) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultAuthnRequestBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultAuthnRequestBuilder.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultAuthnRequestBuilder.java
deleted file mode 100644
index f7383b5..0000000
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultAuthnRequestBuilder.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * 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.core.samlsso;
-
-import java.util.Collections;
-
-import org.opensaml.common.SAMLVersion;
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameIDPolicy;
-import org.opensaml.saml2.core.RequestedAuthnContext;
-
-/**
- * A default implementation of the AuthnRequestBuilder interface to create a SAML 2.0
- * Protocol AuthnRequest.
- */
-public class DefaultAuthnRequestBuilder implements AuthnRequestBuilder {
-    
-    private boolean forceAuthn;
-    private boolean isPassive;
-    private String protocolBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
-    
-    /**
-     * Create a SAML 2.0 Protocol AuthnRequest
-     */
-    public AuthnRequest createAuthnRequest(
-        String issuerId,
-        String assertionConsumerServiceAddress
-    ) throws Exception {
-        Issuer issuer =
-            SamlpRequestComponentBuilder.createIssuer(issuerId);
-        
-        NameIDPolicy nameIDPolicy =
-            SamlpRequestComponentBuilder.createNameIDPolicy(
-                true, "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", issuerId
-            );
-        
-        AuthnContextClassRef authnCtxClassRef =
-            SamlpRequestComponentBuilder.createAuthnCtxClassRef(
-                "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
-            );
-        RequestedAuthnContext authnCtx =
-            SamlpRequestComponentBuilder.createRequestedAuthnCtxPolicy(
-                AuthnContextComparisonTypeEnumeration.EXACT,
-                Collections.singletonList(authnCtxClassRef), null
-            );
-        
-        //CHECKSTYLE:OFF
-        return SamlpRequestComponentBuilder.createAuthnRequest(
-                assertionConsumerServiceAddress, 
-                forceAuthn, 
-                isPassive,
-                protocolBinding, 
-                SAMLVersion.VERSION_20,
-                issuer, 
-                nameIDPolicy, 
-                authnCtx
-        );
-        
-    }
-
-    public boolean isForceAuthn() {
-        return forceAuthn;
-    }
-
-    public void setForceAuthn(boolean forceAuthn) {
-        this.forceAuthn = forceAuthn;
-    }
-
-    public boolean isPassive() {
-        return isPassive;
-    }
-
-    public void setPassive(boolean isPassive) {
-        this.isPassive = isPassive;
-    }
-
-    public String getProtocolBinding() {
-        return protocolBinding;
-    }
-
-    public void setProtocolBinding(String protocolBinding) {
-        this.protocolBinding = protocolBinding;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultSAMLPRequestBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultSAMLPRequestBuilder.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultSAMLPRequestBuilder.java
new file mode 100644
index 0000000..3c80e70
--- /dev/null
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/DefaultSAMLPRequestBuilder.java
@@ -0,0 +1,151 @@
+/**
+ * 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.core.samlsso;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.opensaml.common.SAMLVersion;
+import org.opensaml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.AuthnStatement;
+import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.NameID;
+import org.opensaml.saml2.core.NameIDPolicy;
+import org.opensaml.saml2.core.RequestedAuthnContext;
+
+/**
+ * A default implementation of the SAMLPRequestBuilder interface to create a SAML 2.0
+ * Protocol AuthnRequest and LogoutRequest
+ */
+public class DefaultSAMLPRequestBuilder implements SAMLPRequestBuilder {
+    
+    private boolean forceAuthn;
+    private boolean isPassive;
+    private String protocolBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
+    
+    /**
+     * Create a SAML 2.0 Protocol AuthnRequest
+     */
+    public AuthnRequest createAuthnRequest(
+        String issuerId,
+        String assertionConsumerServiceAddress
+    ) throws Exception {
+        Issuer issuer =
+            SamlpRequestComponentBuilder.createIssuer(issuerId);
+        
+        NameIDPolicy nameIDPolicy =
+            SamlpRequestComponentBuilder.createNameIDPolicy(
+                true, "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", issuerId
+            );
+        
+        AuthnContextClassRef authnCtxClassRef =
+            SamlpRequestComponentBuilder.createAuthnCtxClassRef(
+                "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
+            );
+        RequestedAuthnContext authnCtx =
+            SamlpRequestComponentBuilder.createRequestedAuthnCtxPolicy(
+                AuthnContextComparisonTypeEnumeration.EXACT,
+                Collections.singletonList(authnCtxClassRef), null
+            );
+        
+        //CHECKSTYLE:OFF
+        return SamlpRequestComponentBuilder.createAuthnRequest(
+                assertionConsumerServiceAddress, 
+                forceAuthn, 
+                isPassive,
+                protocolBinding, 
+                SAMLVersion.VERSION_20,
+                issuer, 
+                nameIDPolicy, 
+                authnCtx
+        );
+        
+    }
+
+    public boolean isForceAuthn() {
+        return forceAuthn;
+    }
+
+    public void setForceAuthn(boolean forceAuthn) {
+        this.forceAuthn = forceAuthn;
+    }
+
+    public boolean isPassive() {
+        return isPassive;
+    }
+
+    public void setPassive(boolean isPassive) {
+        this.isPassive = isPassive;
+    }
+
+    public String getProtocolBinding() {
+        return protocolBinding;
+    }
+
+    public void setProtocolBinding(String protocolBinding) {
+        this.protocolBinding = protocolBinding;
+    }
+
+    @Override
+    public LogoutRequest createLogoutRequest(
+        String issuerId,
+        String reason,
+        SamlAssertionWrapper authenticatedAssertion
+    ) throws Exception {
+        Issuer issuer =
+            SamlpRequestComponentBuilder.createIssuer(issuerId);
+        
+        NameID nameID = null;
+        List<String> sessionIndices = new ArrayList<String>();
+        
+        if (authenticatedAssertion != null) {
+            if (authenticatedAssertion.getSaml2() != null) {
+                org.opensaml.saml2.core.Subject subject = 
+                    authenticatedAssertion.getSaml2().getSubject();
+                if (subject != null && subject.getNameID() != null) {
+                    nameID = subject.getNameID();
+                }
+            }
+            List<AuthnStatement> authnStatements = 
+                authenticatedAssertion.getSaml2().getAuthnStatements();
+            if (authnStatements != null && !authnStatements.isEmpty()) {
+                for (AuthnStatement authnStatement : authnStatements) {
+                    if (authnStatement.getSessionIndex() != null) {
+                        sessionIndices.add(authnStatement.getSessionIndex());
+                    }
+                }
+            }
+        }
+        
+        //CHECKSTYLE:OFF
+        return SamlpRequestComponentBuilder.createLogoutRequest(
+            issuer,
+            reason,
+            nameID,
+            sessionIndices
+        );
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLPRequestBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLPRequestBuilder.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLPRequestBuilder.java
new file mode 100644
index 0000000..ba7efba
--- /dev/null
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLPRequestBuilder.java
@@ -0,0 +1,47 @@
+/**
+ * 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.core.samlsso;
+
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.LogoutRequest;
+
+/**
+ * This interface defines a methods to create a SAML 2.0 Protocol AuthnRequest and LogoutRequest.
+ */
+public interface SAMLPRequestBuilder {
+    
+    /**
+     * Create a SAML 2.0 Protocol AuthnRequest
+     */
+    AuthnRequest createAuthnRequest(
+        String issuerId,
+        String assertionConsumerServiceAddress
+    ) throws Exception;
+    
+    /**
+     * Create a SAML 2.0 Protocol LogoutRequest
+     */
+    LogoutRequest createLogoutRequest(
+        String issuerId,
+        String reason,
+        SamlAssertionWrapper authenticatedAssertion
+    ) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SamlpRequestComponentBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SamlpRequestComponentBuilder.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SamlpRequestComponentBuilder.java
index 426dc33..12bec45 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SamlpRequestComponentBuilder.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SamlpRequestComponentBuilder.java
@@ -32,8 +32,11 @@ import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
 import org.opensaml.saml2.core.AuthnContextDeclRef;
 import org.opensaml.saml2.core.AuthnRequest;
 import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.NameID;
 import org.opensaml.saml2.core.NameIDPolicy;
 import org.opensaml.saml2.core.RequestedAuthnContext;
+import org.opensaml.saml2.core.SessionIndex;
 import org.opensaml.xml.XMLObjectBuilderFactory;
 
 /**
@@ -43,6 +46,10 @@ public final class SamlpRequestComponentBuilder {
     
     private static volatile SAMLObjectBuilder<AuthnRequest> authnRequestBuilder;
     
+    private static volatile SAMLObjectBuilder<LogoutRequest> logoutRequestBuilder;
+    
+    private static volatile SAMLObjectBuilder<SessionIndex> sessionIndexBuilder;
+    
     private static volatile SAMLObjectBuilder<Issuer> issuerBuilder;
     
     private static volatile SAMLObjectBuilder<NameIDPolicy> nameIDBuilder;
@@ -90,6 +97,47 @@ public final class SamlpRequestComponentBuilder {
     }
     
     @SuppressWarnings("unchecked")
+    public static LogoutRequest createLogoutRequest(
+        Issuer issuer,
+        String reason,
+        NameID nameId,
+        List<String> sessionIndices
+    ) {
+        if (logoutRequestBuilder == null) {
+            logoutRequestBuilder = (SAMLObjectBuilder<LogoutRequest>)
+                builderFactory.getBuilder(LogoutRequest.DEFAULT_ELEMENT_NAME);
+        }
+        if (sessionIndexBuilder == null) {
+            sessionIndexBuilder = (SAMLObjectBuilder<SessionIndex>)
+                builderFactory.getBuilder(SessionIndex.DEFAULT_ELEMENT_NAME);
+        }
+        
+        LogoutRequest logoutRequest = logoutRequestBuilder.buildObject();
+        
+        logoutRequest.setID(UUID.randomUUID().toString());
+        logoutRequest.setIssueInstant(new DateTime());
+        
+        if (reason != null) {
+            logoutRequest.setReason(reason);
+        }
+        if (nameId != null) {
+            logoutRequest.setNameID(nameId);
+        }
+        
+        if (sessionIndices != null && !sessionIndices.isEmpty()) {
+            for (String sessionIndex : sessionIndices) {
+                SessionIndex sessionIndexObj = sessionIndexBuilder.buildObject();
+                sessionIndexObj.setSessionIndex(sessionIndex);
+                logoutRequest.getSessionIndexes().add(sessionIndexObj);
+            }
+        }
+
+        logoutRequest.setIssuer(issuer);
+
+        return logoutRequest;
+    }
+    
+    @SuppressWarnings("unchecked")
     public static Issuer createIssuer(
         String issuerValue
     ) {

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/f3887c20/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
index 4293565..f14d80e 100644
--- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLRequestTest.java
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.w3c.dom.Document;
-
 import org.apache.cxf.fediz.common.SecurityTestUtil;
 import org.apache.cxf.fediz.core.RequestState;
 import org.apache.cxf.fediz.core.config.FedizConfigurator;
@@ -46,6 +45,7 @@ import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.LogoutRequest;
 
 /**
  * Some tests for creating SAMLRequests using the SAMLProcessorImpl
@@ -214,8 +214,18 @@ public class SAMLRequestTest {
         RedirectionResponse response = wfProc.createSignOutRequest(req, config);
         
         String redirectionURL = response.getRedirectionURL();
-        Assert.assertTrue(redirectionURL.startsWith(TEST_IDP_ISSUER));
-        Assert.assertTrue(redirectionURL.endsWith("wa=wsignout1.0"));
+        String samlRequest = 
+            redirectionURL.substring(redirectionURL.indexOf("SAMLRequest=") + "SAMLRequest=".length(),
+                                     redirectionURL.indexOf("RelayState=") - 1);
+        
+        byte[] deflatedToken = Base64.decode(URLDecoder.decode(samlRequest, "UTF-8"));
+        InputStream tokenStream = CompressionUtils.inflate(deflatedToken);
+
+        Document requestDoc = DOMUtils.readXml(new InputStreamReader(tokenStream, "UTF-8"));
+        LogoutRequest request =
+            (LogoutRequest)OpenSAMLUtil.fromDom(requestDoc.getDocumentElement());
+
+        Assert.assertEquals(TEST_REQUEST_URL, request.getIssuer().getValue());
     }
     
 }
\ No newline at end of file


Mime
View raw message