diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java index 1ec2116..8759593 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java @@ -22,6 +22,7 @@ import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /** @@ -148,4 +149,35 @@ public final class ReflectUtils { throw new RuntimeException("Error setting property " + propertyName, e); } } + + /** + * Gets the value of the given declared field on the target object or any of its superclasses. + * + * @param fieldName Name of field to get. + * @param target Target object that possesses field. + * + * @return Field value. + */ + public static Object getField(final String fieldName, final Object target) { + Class clazz = target.getClass(); + Field field = null; + do { + try { + field = clazz.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + clazz = clazz.getSuperclass(); + } + } while (field == null && clazz != null); + if (field == null) { + throw new IllegalArgumentException(fieldName + " does not exist on " + target); + } + try { + if (!field.isAccessible()) { + field.setAccessible(true); + } + return field.get(target); + } catch (Exception e) { + throw new IllegalArgumentException("Error getting field " + fieldName, e); + } + } } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/util/ReflectUtilsTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/util/ReflectUtilsTests.java index d39e3bb..57d741c 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/util/ReflectUtilsTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/util/ReflectUtilsTests.java @@ -54,6 +54,18 @@ public class ReflectUtilsTests extends TestCase { assertTrue(bean.isFlag()); } + public void testGetField() { + final TestBean bean = new TestBean(); + bean.setName("bob"); + assertEquals(bean.getName(), ReflectUtils.getField("name", bean)); + } + + public void testGetFieldSuperclass() { + final TestSubBean bean = new TestSubBean(); + bean.setName("bob"); + assertEquals(bean.getName(), ReflectUtils.getField("name", bean)); + } + static class TestBean { private int count; private boolean flag; @@ -102,4 +114,16 @@ public class ReflectUtilsTests extends TestCase { } } + + static class TestSubBean extends TestBean { + private String state; + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + } } diff --git a/cas-client-integration-jetty/pom.xml b/cas-client-integration-jetty/pom.xml new file mode 100644 index 0000000..480acbe --- /dev/null +++ b/cas-client-integration-jetty/pom.xml @@ -0,0 +1,73 @@ + + + + cas-client + org.jasig.cas.client + 3.4.2-SNAPSHOT + + 4.0.0 + + org.jasig.cas.client + cas-client-integration-jetty + jar + Jasig CAS Client for Java - Jetty Container Integration + + + + 9.2.14.v20151106 + + + + + org.jasig.cas.client + cas-client-core + ${project.version} + + + org.eclipse.jetty + jetty-security + ${jetty.version} + + + + + org.jasig.cas.client + cas-client-core + ${project.version} + test-jar + test + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + test + + + org.eclipse.jetty + jetty-plus + ${jetty.version} + test + + + org.eclipse.jetty + jetty-annotations + ${jetty.version} + test + + + org.eclipse.jetty + apache-jsp + ${jetty.version} + test + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java new file mode 100644 index 0000000..831ec75 --- /dev/null +++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthentication.java @@ -0,0 +1,46 @@ +package org.jasig.cas.client.jetty; + +import org.eclipse.jetty.security.UserAuthentication; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.validation.Assertion; + +/** + * CAS-specific user authentication. + * + * @author Marvin S. Addison + */ +public class CasAuthentication extends UserAuthentication { + + /** CAS authenticator that produced this authentication. */ + private final CasAuthenticator authenticator; + + /** CAS ticket that was successfully validated to permit authentication. */ + private final String ticket; + + + /** + * Creates a new instance. + * + * @param authenticator The authenticator that produced this authentication. + * @param ticket The CAS ticket that was successfully validated to permit authentication. + * @param assertion The CAS assertion produced from successful ticket validation. + */ + public CasAuthentication(final CasAuthenticator authenticator, final String ticket, final Assertion assertion) { + super(authenticator.getAuthMethod(), new CasUserIdentity(assertion, authenticator.getRoleAttribute())); + CommonUtils.assertNotNull(ticket, "Ticket cannot be null"); + CommonUtils.assertNotNull(authenticator, "CasAuthenticator cannot be null"); + this.authenticator = authenticator; + this.ticket = ticket; + } + + /** @return The CAS ticket that was successfully validated to permit authentication. */ + public String getTicket() { + return ticket; + } + + @Override + public void logout() { + super.logout(); + this.authenticator.clearCachedAuthentication(ticket); + } +} diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java new file mode 100644 index 0000000..21d4c51 --- /dev/null +++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasAuthenticator.java @@ -0,0 +1,248 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig 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 the following location: + * + * 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.jasig.cas.client.jetty; + +import org.eclipse.jetty.security.Authenticator; +import org.eclipse.jetty.security.ServerAuthException; +import org.eclipse.jetty.server.Authentication; +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.jasig.cas.client.Protocol; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.util.ReflectUtils; +import org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator; +import org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator; +import org.jasig.cas.client.validation.Assertion; +import org.jasig.cas.client.validation.TicketValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Jetty authenticator component for container-managed CAS authentication. + *

NOTE: This component does not support CAS gateway mode.

+ * + * @author Marvin S. Addison + * @since 3.4.2 + */ +public class CasAuthenticator extends AbstractLifeCycle implements Authenticator { + + /** Name of authentication method provided by this authenticator. */ + public static final String AUTH_METHOD = "CAS"; + + /** Session attribute used to cache CAS authentication data. */ + private static final String CACHED_AUTHN_ATTRIBUTE = "org.jasig.cas.client.jetty.Authentication"; + + /** Logger instance. */ + private final Logger logger = LoggerFactory.getLogger(CasAuthenticator.class); + + /** Map of tickets to sessions. */ + private final ConcurrentMap> sessionMap = + new ConcurrentHashMap>(); + + /** CAS ticket validator component. */ + private TicketValidator ticketValidator; + + /** Space-delimited list of server names. */ + private String serverNames; + + /** CAS principal attribute containing role data. */ + private String roleAttribute; + + /** URL to /login URI on CAS server. */ + private String casServerLoginUrl; + + /** Protocol used by ticket validator. */ + private Protocol protocol; + + /** CAS renew parameter. */ + private boolean renew; + + + /** + * Sets the CAS ticket validator component. + * + * @param ticketValidator Ticket validator, MUST NOT be null. + */ + public void setTicketValidator(final TicketValidator ticketValidator) { + CommonUtils.assertNotNull(ticketValidator, "TicketValidator cannot be null"); + if (ticketValidator instanceof AbstractUrlBasedTicketValidator) { + if (ticketValidator instanceof AbstractCasProtocolUrlBasedTicketValidator) { + protocol = Protocol.CAS2; + } else { + protocol = Protocol.SAML11; + } + casServerLoginUrl = ReflectUtils.getField("casServerUrlPrefix", ticketValidator) + "/login"; + renew = (Boolean) ReflectUtils.getField("renew", ticketValidator); + } else { + throw new IllegalArgumentException("Unsupported ticket validator " + ticketValidator); + } + this.ticketValidator = ticketValidator; + } + + /** + * Sets the names of the server host running Jetty. + * + * @param nameList Space-delimited list of one or more server names, e.g. "www1.example.com www2.example.com". + * MUST NOT be blank. + */ + public void setServerNames(final String nameList) { + CommonUtils.isNotBlank(nameList); + this.serverNames = nameList; + } + + /** @return The name of the CAS principal attribute that contains role data. */ + public String getRoleAttribute() { + return roleAttribute; + } + + /** + * Sets the name of the CAS principal attribute that contains role data. + * + * @param roleAttribute Role attribute name. MUST NOT be blank. + */ + public void setRoleAttribute(final String roleAttribute) { + CommonUtils.isNotBlank(roleAttribute); + this.roleAttribute = roleAttribute; + } + + @Override + public void setConfiguration(final AuthConfiguration configuration) { + // Nothing to do + // All configuration must be via CAS-specific setter methods + } + + @Override + public String getAuthMethod() { + return AUTH_METHOD; + } + + @Override + public void prepareRequest(final ServletRequest request) { + // Nothing to do + } + + @Override + public Authentication validateRequest( + final ServletRequest servletRequest, final ServletResponse servletResponse, final boolean mandatory) + throws ServerAuthException { + + final HttpServletRequest request = (HttpServletRequest) servletRequest; + final HttpServletResponse response = (HttpServletResponse) servletResponse; + + CasAuthentication authentication = fetchCachedAuthentication(request); + if (authentication != null) { + return authentication; + } + + final String ticket = request.getParameter(protocol.getArtifactParameterName()); + if (ticket != null && mandatory) { + try { + logger.debug("Attempting to validate {}", ticket); + final Assertion assertion = ticketValidator.validate(ticket, serviceUrl(request, response)); + logger.info("Successfully authenticated {}", assertion.getPrincipal()); + authentication = new CasAuthentication(this, ticket, assertion); + cacheAuthentication(request, authentication); + } catch (Exception e) { + throw new ServerAuthException("CAS ticket validation failed", e); + } + } + if (authentication != null) { + return authentication; + } else if (mandatory) { + redirectToCas(request, response); + return Authentication.SEND_CONTINUE; + } + return Authentication.UNAUTHENTICATED; + } + + @Override + public boolean secureResponse( + final ServletRequest request, + final ServletResponse response, + final boolean mandatory, + final Authentication.User user) throws ServerAuthException { + return true; + } + + @Override + protected void doStart() throws Exception { + if (ticketValidator == null) { + throw new RuntimeException("TicketValidator cannot be null"); + } + if (serverNames == null) { + throw new RuntimeException("ServerNames cannot be null"); + } + } + + protected void clearCachedAuthentication(final String ticket) { + final WeakReference sessionRef = sessionMap.remove(ticket); + if (sessionRef != null && sessionRef.get() != null) { + sessionRef.get().removeAttribute(CACHED_AUTHN_ATTRIBUTE); + } + } + + private void cacheAuthentication(final HttpServletRequest request, final CasAuthentication authentication) { + final HttpSession session = request.getSession(true); + if (session != null) { + session.setAttribute(CACHED_AUTHN_ATTRIBUTE, authentication); + sessionMap.put(authentication.getTicket(), new WeakReference(session)); + } + } + + private CasAuthentication fetchCachedAuthentication(final HttpServletRequest request) { + final HttpSession session = request.getSession(false); + if (session != null) { + return (CasAuthentication) session.getAttribute(CACHED_AUTHN_ATTRIBUTE); + } + return null; + } + + private String serviceUrl(final HttpServletRequest request, final HttpServletResponse response) { + return CommonUtils.constructServiceUrl( + request, + response, + null, + serverNames, + protocol.getServiceParameterName(), + protocol.getArtifactParameterName(), + true); + } + + private void redirectToCas( + final HttpServletRequest request, final HttpServletResponse response) throws ServerAuthException { + try { + final String redirectUrl = CommonUtils.constructRedirectUrl( + casServerLoginUrl, protocol.getServiceParameterName(), serviceUrl(request, response), renew, false); + logger.debug("Redirecting to {}", redirectUrl); + response.sendRedirect(redirectUrl); + } catch (IOException e) { + logger.debug("Redirect to CAS failed with error: {}", e); + throw new ServerAuthException("Redirect to CAS failed", e); + } + } +} diff --git a/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java new file mode 100644 index 0000000..aee4212 --- /dev/null +++ b/cas-client-integration-jetty/src/main/java/org/jasig/cas/client/jetty/CasUserIdentity.java @@ -0,0 +1,67 @@ +package org.jasig.cas.client.jetty; + +import org.eclipse.jetty.server.UserIdentity; +import org.jasig.cas.client.authentication.AttributePrincipal; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.validation.Assertion; + +import javax.security.auth.Subject; +import java.security.Principal; +import java.util.Collection; + +/** + * CAS user identity backed by assertion data. + * + * @author Marvin S. Addison + */ +public class CasUserIdentity implements UserIdentity { + + /** CAS principal. */ + private AttributePrincipal principal; + + /** Assertion attribute containing role data. */ + private String roleAttribute; + + + /** + * Creates a new instance from a CAS assertion containing principal information. + * + * @param assertion CAS assertion resulting from successful ticket validation. + * @param roleAttribute Principal attribute containing role data. + */ + public CasUserIdentity(final Assertion assertion, final String roleAttribute) { + CommonUtils.assertNotNull(assertion, "Assertion cannot be null"); + this.principal = assertion.getPrincipal(); + this.roleAttribute = roleAttribute; + } + + @Override + public Subject getSubject() { + final Subject subject = new Subject(); + subject.getPrincipals().add(principal); + return subject; + } + + @Override + public Principal getUserPrincipal() { + return principal; + } + + @Override + public boolean isUserInRole(final String role, final Scope scope) { + if (roleAttribute != null) { + final Object value = principal.getAttributes().get(roleAttribute); + if (value instanceof Collection) { + return ((Collection) value).contains(role); + } else if (value instanceof String) { + return value.equals(role); + } + } + return false; + } + + @Override + public String toString() { + return principal.getName(); + } +} diff --git a/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java b/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java new file mode 100644 index 0000000..462f353 --- /dev/null +++ b/cas-client-integration-jetty/src/test/java/org/jasig/cas/client/jetty/CasAuthenticatorTest.java @@ -0,0 +1,210 @@ +package org.jasig.cas.client.jetty; + +import org.apache.tomcat.InstanceManager; +import org.apache.tomcat.SimpleInstanceManager; +import org.eclipse.jetty.annotations.ServletContainerInitializersStarter; +import org.eclipse.jetty.apache.jsp.JettyJasperInitializer; +import org.eclipse.jetty.jsp.JettyJspServlet; +import org.eclipse.jetty.plus.annotation.ContainerInitializer; +import org.eclipse.jetty.security.ConstraintMapping; +import org.eclipse.jetty.security.ConstraintSecurityHandler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.webapp.WebAppContext; +import org.jasig.cas.client.PublicTestHttpServer; +import org.jasig.cas.client.validation.Cas20ServiceTicketValidator; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +/** + * Unit test for {@link CasAuthenticator}. + * + * @author Marvin S. Addison + */ +public class CasAuthenticatorTest { + + private static final Server server = new Server(8080); + private static final CasAuthenticator authenticator = new CasAuthenticator(); + + @BeforeClass + public static void beforeClass() throws Exception { + final WebAppContext context = new WebAppContext(); + context.setContextPath("/webapp"); + String workingDir = new File(".").getAbsolutePath(); + workingDir = workingDir.substring(0, workingDir.length() - 2); + final String webappDir; + if (workingDir.endsWith("/cas-client-integration-jetty")) { + webappDir = workingDir + "/src/test/webapp"; + } else { + webappDir = workingDir + "/cas-client-integration-jetty/src/test/webapp"; + } + context.setWar(webappDir); + + + // JSP config from https://github.com/jetty-project/embedded-jetty-jsp/ + System.setProperty("org.apache.jasper.compiler.disablejsr199", "false"); + context.setAttribute("javax.servlet.context.tempdir", getScratchDir()); + context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", + ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/.*taglibs.*\\.jar$"); + context.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers()); + context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager()); + context.addBean(new ServletContainerInitializersStarter(context), true); + context.addServlet(jspServletHolder(), "*.jsp"); + + // Wire up CAS authentication + authenticator.setServerNames("localhost:8080"); + authenticator.setTicketValidator(new Cas20ServiceTicketValidator("http://localhost:8081/cas")); + + // Configure security handling for webapp context + final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler(); + final Constraint constraint = new Constraint("CasRealm", Constraint.ANY_AUTH); + constraint.setAuthenticate(true); + final ConstraintMapping secureMapping = new ConstraintMapping(); + secureMapping.setPathSpec("/secure.jsp"); + secureMapping.setConstraint(constraint); + securityHandler.addConstraintMapping(secureMapping); + securityHandler.setAuthenticator(authenticator); + context.setSecurityHandler(securityHandler); + + // Add webapp context and start the server + server.setHandler(context); + server.start(); + } + + @Test + public void testValidateRequestPublicPageNoTicket() throws Exception { + final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/"); + try { + assertEquals(200, uc.getResponseCode()); + assertTrue(readOutput(uc).contains("Welcome everyone")); + } finally { + uc.disconnect(); + } + } + + @Test + public void testValidateRequestPublicPageWithTicket() throws Exception { + final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/?ticket=ST-12345"); + try { + assertEquals(200, uc.getResponseCode()); + assertTrue(readOutput(uc).contains("Welcome everyone")); + } finally { + uc.disconnect(); + } + } + + @Test + public void testValidateRequestSecurePageNoTicket() throws Exception { + final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/secure.jsp"); + try { + assertEquals(302, uc.getResponseCode()); + assertEquals( + "http://localhost:8081/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fwebapp%2Fsecure.jsp", + uc.getHeaderField("Location")); + } finally { + uc.disconnect(); + } + } + + @Test + public void testValidateRequestSecurePageWithTicket() throws Exception { + final String successResponse = "" + + "" + + "bob" + + "" + + ""; + final PublicTestHttpServer server = PublicTestHttpServer.instance(8081); + server.content = successResponse.getBytes(StandardCharsets.UTF_8); + final HttpURLConnection uc = openConnection("http://localhost:8080/webapp/secure.jsp?ticket=ST-12345"); + try { + assertEquals(200, uc.getResponseCode()); + assertTrue(readOutput(uc).contains("Hello bob")); + } finally { + uc.disconnect(); + } + } + + @AfterClass + public static void afterClass() throws Exception { + server.stop(); + } + + private String readOutput(final URLConnection connection) throws IOException { + final InputStreamReader reader = new InputStreamReader(connection.getInputStream()); + final StringBuilder builder = new StringBuilder(); + final CharBuffer buffer = CharBuffer.allocate(1024); + try { + while (reader.read(buffer) > 0) { + builder.append(buffer.flip()); + buffer.clear(); + } + } finally { + reader.close(); + } + return builder.toString(); + } + + private static File getScratchDir() throws IOException + { + final File tempDir = new File(System.getProperty("java.io.tmpdir")); + final File scratchDir = new File(tempDir.toString(), "embedded-jetty-jsp"); + + if (!scratchDir.exists()) + { + if (!scratchDir.mkdirs()) + { + throw new IOException("Unable to create scratch directory: " + scratchDir); + } + } + return scratchDir; + } + + /** + * Ensure the jsp engine is initialized correctly + */ + private static List jspInitializers() + { + return Collections.singletonList(new ContainerInitializer(new JettyJasperInitializer(), null)); + } + + /** + * Create JSP Servlet (must be named "jsp") + */ + private static ServletHolder jspServletHolder() + { + final ServletHolder holderJsp = new ServletHolder("jsp", JettyJspServlet.class); + holderJsp.setInitOrder(0); + holderJsp.setInitParameter("logVerbosityLevel", "DEBUG"); + holderJsp.setInitParameter("fork", "false"); + holderJsp.setInitParameter("xpoweredBy", "false"); + holderJsp.setInitParameter("compilerTargetVM", "1.7"); + holderJsp.setInitParameter("compilerSourceVM", "1.7"); + holderJsp.setInitParameter("keepgenerated", "true"); + return holderJsp; + } + + private static HttpURLConnection openConnection(final String url) throws IOException { + final HttpURLConnection uc; + try { + uc = (HttpURLConnection) new URL(url).openConnection(); + } catch (IOException e) { + throw new RuntimeException("Invalid URL: " + url, e); + } + uc.setInstanceFollowRedirects(false); + uc.connect(); + return uc; + } +} \ No newline at end of file diff --git a/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml b/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml new file mode 100644 index 0000000..a786496 --- /dev/null +++ b/cas-client-integration-jetty/src/test/resources/jetty/context-cas2.xml @@ -0,0 +1,20 @@ + + + + + / + /webapps/yourapp + + + + app.example.com + + + https://cas.example.com/cas + + + + + + + diff --git a/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml b/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml new file mode 100644 index 0000000..5e1d5ad --- /dev/null +++ b/cas-client-integration-jetty/src/test/resources/jetty/context-saml11.xml @@ -0,0 +1,21 @@ + + + + + / + /webapps/yourapp + + + + app.example.com + memberOf + + + https://cas.example.com/cas + + + + + + + diff --git a/cas-client-integration-jetty/src/test/webapp/index.jsp b/cas-client-integration-jetty/src/test/webapp/index.jsp new file mode 100644 index 0000000..6d505bb --- /dev/null +++ b/cas-client-integration-jetty/src/test/webapp/index.jsp @@ -0,0 +1,9 @@ + + + + + Welcome Page + +

Welcome everyone

+ + \ No newline at end of file diff --git a/cas-client-integration-jetty/src/test/webapp/secure.jsp b/cas-client-integration-jetty/src/test/webapp/secure.jsp new file mode 100644 index 0000000..9add84e --- /dev/null +++ b/cas-client-integration-jetty/src/test/webapp/secure.jsp @@ -0,0 +1,9 @@ + + + + + Secure Page + +

Hello <%=request.getUserPrincipal()%>

+ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index a5d3ba8..7a16ddc 100644 --- a/pom.xml +++ b/pom.xml @@ -253,6 +253,7 @@ cas-client-integration-tomcat-v6 cas-client-integration-tomcat-v7 cas-client-integration-tomcat-v8 + cas-client-integration-jetty