cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject git commit: [FEDIZ-46, FEDIZ-19] - Added logout support for the CXF plugin + some logout system tests
Date Fri, 05 Sep 2014 15:29:36 GMT
Repository: cxf-fediz
Updated Branches:
  refs/heads/master d073bce10 -> bb7d7488b


[FEDIZ-46,FEDIZ-19] - Added logout support for the CXF plugin + some logout system tests


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

Branch: refs/heads/master
Commit: bb7d7488b8d1707cee00cddec4c85cde30be22bc
Parents: d073bce
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Fri Sep 5 16:29:01 2014 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Fri Sep 5 16:29:01 2014 +0100

----------------------------------------------------------------------
 .../cxf/plugin/FedizRedirectBindingFilter.java  |  44 +++++-
 .../fediz/integrationtests/AbstractTests.java   |  21 ++-
 .../fediz/integrationtests/HTTPTestUtils.java   | 141 +++++++++++++++++++
 3 files changed, 204 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb7d7488/plugins/cxf/src/main/java/org/apache/cxf/fediz/cxf/plugin/FedizRedirectBindingFilter.java
----------------------------------------------------------------------
diff --git a/plugins/cxf/src/main/java/org/apache/cxf/fediz/cxf/plugin/FedizRedirectBindingFilter.java
b/plugins/cxf/src/main/java/org/apache/cxf/fediz/cxf/plugin/FedizRedirectBindingFilter.java
index bd2d198..9ab7d0b 100644
--- a/plugins/cxf/src/main/java/org/apache/cxf/fediz/cxf/plugin/FedizRedirectBindingFilter.java
+++ b/plugins/cxf/src/main/java/org/apache/cxf/fediz/cxf/plugin/FedizRedirectBindingFilter.java
@@ -37,7 +37,6 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 
 import org.w3c.dom.Document;
-
 import org.apache.cxf.fediz.core.FederationConstants;
 import org.apache.cxf.fediz.core.RequestState;
 import org.apache.cxf.fediz.core.SAMLSSOConstants;
@@ -79,6 +78,11 @@ public class FedizRedirectBindingFilter extends AbstractServiceProviderFilter
{
             return;
         }
 
+        // See if it is a Logout request
+        if (isLogoutRequest(context, fedConfig)) {
+            return;
+        }
+        
         if (checkSecurityContext(m)) {
             return;
         } else {
@@ -240,6 +244,44 @@ public class FedizRedirectBindingFilter extends AbstractServiceProviderFilter
{
         return false;
     }
     
+    private boolean isLogoutRequest(ContainerRequestContext context, FedizContext fedConfig)
{
+        //logout
+        String logoutUrl = fedConfig.getLogoutURL();
+        if (logoutUrl != null && !logoutUrl.isEmpty()) {
+            String requestPath = "/" + context.getUriInfo().getPath();
+            if (requestPath.equals(logoutUrl) || requestPath.equals(logoutUrl + "/")) {
+                try {
+                    FedizProcessor processor = 
+                        FedizProcessorFactory.newFedizProcessor(fedConfig.getProtocol());
+                    
+                    HttpServletRequest request = messageContext.getHttpServletRequest();
+                    RedirectionResponse redirectionResponse = 
+                        processor.createSignOutRequest(request, fedConfig);
+                    String redirectURL = redirectionResponse.getRedirectionURL();
+                    if (redirectURL != null) {
+                        ResponseBuilder response = Response.seeOther(new URI(redirectURL));
+                        Map<String, String> headers = redirectionResponse.getHeaders();
+                        if (!headers.isEmpty()) {
+                            for (String headerName : headers.keySet()) {
+                                response.header(headerName, headers.get(headerName));
+                            }
+                        }
+    
+                        context.abortWith(response.build());
+    
+                        return true;
+                    }
+                } catch (Exception ex) {
+                    LOG.debug(ex.getMessage(), ex);
+                    throw ExceptionUtils.toInternalServerErrorException(ex, null);
+                }
+            }
+        }
+        // TODO ACTION_SIGNOUT_CLEANUP
+        
+        return false;
+    }
+    
     private String getMetadataURI(FedizContext fedConfig) {
         if (fedConfig.getProtocol().getMetadataURI() != null) {
             return fedConfig.getProtocol().getMetadataURI();

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb7d7488/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java
----------------------------------------------------------------------
diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java
b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java
index 9962f11..99bc5d4 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java
@@ -98,7 +98,7 @@ public abstract class AbstractTests {
     }
     
     @org.junit.Test
-    public void testliceManagerNoAccess() throws Exception {
+    public void testAliceManagerNoAccess() throws Exception {
         String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/manager/fedservlet";
         String user = "alice";
         String password = "ecila";
@@ -281,4 +281,23 @@ public abstract class AbstractTests {
         }
     }
     
+    @org.junit.Test
+    public void testAliceLogout() throws Exception {
+        // Authenticate as "alice"
+        String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/fedservlet";
+        String user = "alice";
+        String password = "ecila";
+        
+        CloseableHttpClient httpClient = 
+            HTTPTestUtils.sendHttpGetForSignIn(url, user, password, 200, 200, Integer.parseInt(getIdpHttpsPort()));
+        
+        String logoutUrl = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/logout";
+        String logoutResponse = 
+            HTTPTestUtils.sendHttpGetForSignOut(httpClient, logoutUrl, 200, 200, Integer.parseInt(getIdpHttpsPort()));
+        
+        Assert.assertTrue(logoutResponse.contains("IDP SignOut Response Page"));
+        Assert.assertTrue(logoutResponse.contains("Logout status of RP"));
+        Assert.assertTrue(logoutResponse.contains("wsignoutcleanup1.0"));
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb7d7488/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/HTTPTestUtils.java
----------------------------------------------------------------------
diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/HTTPTestUtils.java
b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/HTTPTestUtils.java
index e62275e..ac20e88 100644
--- a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/HTTPTestUtils.java
+++ b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/HTTPTestUtils.java
@@ -239,5 +239,146 @@ public final class HTTPTestUtils {
             }
         }
     }
+    
+    /**
+     * Same as sendHttpGet above, except that we return the HttpClient so that it can
+     * subsequently be re-used (for e.g. logout)
+     */
+    public static CloseableHttpClient sendHttpGetForSignIn(String url, String user, String
password, 
+                                                           int returnCodeIDP, int returnCodeRP,
int idpPort)
+        throws Exception {
+
+        CloseableHttpClient httpClient = null;
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        credsProvider.setCredentials(
+                                     new AuthScope("localhost", idpPort), 
+                                     new UsernamePasswordCredentials(user, password));
+
+        KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
+        FileInputStream instream = new FileInputStream(new File("./target/test-classes/client.jks"));
+        try {
+            trustStore.load(instream, "clientpass".toCharArray());
+        } finally {
+            try {
+                instream.close();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+
+        SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
+        sslContextBuilder.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy());
+        sslContextBuilder.loadKeyMaterial(trustStore, "clientpass".toCharArray());
+
+        SSLContext sslContext = sslContextBuilder.build();
+        SSLConnectionSocketFactory sslSocketFactory = 
+            new SSLConnectionSocketFactory(sslContext);
+
+        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
+        httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
+        httpClientBuilder.setRedirectStrategy(new LaxRedirectStrategy());
+
+        httpClient = httpClientBuilder.build();
+
+        HttpGet httpget = new HttpGet(url);
+
+        HttpResponse response = httpClient.execute(httpget);
+        HttpEntity entity = response.getEntity();
+
+        Assert.assertTrue("IDP HTTP Response code: " + response.getStatusLine().getStatusCode()
+                          + " [Expected: " + returnCodeIDP + "]",
+                          returnCodeIDP == response.getStatusLine().getStatusCode());
+
+        if (response.getStatusLine().getStatusCode() != 200) {
+            return null;
+        }
+
+        //            Redirect to a POST is not supported without user interaction
+        //            http://www.ietf.org/rfc/rfc2616.txt
+        //            If the 301 status code is received in response to a request other
+        //            than GET or HEAD, the user agent MUST NOT automatically redirect the
+        //            request unless it can be confirmed by the user, since this might
+        //            change the conditions under which the request was issued.
+
+        Source source = new Source(EntityUtils.toString(entity));
+        List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+        FormFields formFields = source.getFormFields();
+
+        List<Element> forms = source.getAllElements(HTMLElementName.FORM);
+        Assert.assertEquals("Only one form expected but got " + forms.size(), 1, forms.size());
+        String postUrl = forms.get(0).getAttributeValue("action");
+
+        Assert.assertNotNull("Form field 'wa' not found", formFields.get("wa"));
+        Assert.assertNotNull("Form field 'wresult' not found", formFields.get("wresult"));
+
+        for (FormField formField : formFields) {
+            if (formField.getUserValueCount() != 0) {
+                nvps.add(new BasicNameValuePair(formField.getName(),
+                                                formField.getValues().get(0)));
+            }
+        } 
+        HttpPost httppost = new HttpPost(postUrl);
+        httppost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
+
+        response = httpClient.execute(httppost);
+
+        entity = response.getEntity();
+        Assert.assertTrue("RP HTTP Response code: " + response.getStatusLine().getStatusCode()
+                          + " [Expected: " + returnCodeRP + "]",
+                          returnCodeRP == response.getStatusLine().getStatusCode());
+
+        String responseStr = EntityUtils.toString(entity);
+        Assert.assertTrue("Principal not " + user, responseStr.indexOf("userPrincipal=" +
user) > 0);
+
+        return httpClient;
+    }
+
+    public static String sendHttpGetForSignOut(CloseableHttpClient httpClient, String url,
+                                               int returnCodeIDP, int returnCodeRP, int idpPort)
+        throws Exception {
+        try {
+            // logout to service provider
+            HttpGet httpget = new HttpGet(url);
 
+            HttpResponse response = httpClient.execute(httpget);
+            HttpEntity entity = response.getEntity();
+
+            String parsedEntity = EntityUtils.toString(entity);
+            Assert.assertTrue(parsedEntity.contains("Logout from the following realms"));
+            Source source = new Source(parsedEntity);
+            List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+            FormFields formFields = source.getFormFields();
+
+            List<Element> forms = source.getAllElements(HTMLElementName.FORM);
+            Assert.assertEquals("Only one form expected but got " + forms.size(), 1, forms.size());
+            String postUrl = forms.get(0).getAttributeValue("action");
+
+            Assert.assertNotNull("Form field 'wa' not found", formFields.get("wa"));
+
+            for (FormField formField : formFields) {
+                if (formField.getUserValueCount() != 0) {
+                    nvps.add(new BasicNameValuePair(formField.getName(),
+                                                    formField.getValues().get(0)));
+                }
+            } 
+
+            // Now send logout form to IdP
+            nvps.add(new BasicNameValuePair("_eventId_submit", "Logout"));
+
+            HttpPost httppost = 
+                new HttpPost("https://localhost:" + idpPort + "/" + postUrl);
+            httppost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
+
+            response = httpClient.execute(httppost);
+            entity = response.getEntity();
+
+            return EntityUtils.toString(entity);
+        } finally {
+            if (httpClient != null) {
+                httpClient.close();
+            }
+        }
+    }
+    
 }


Mime
View raw message