Initial Contribution
Signed-off-by: Vinay Vishal <vinay.vishal@oracle.com>
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/pom.xml b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/pom.xml
new file mode 100644
index 0000000..2103a8d
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/pom.xml
@@ -0,0 +1,47 @@
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.soteria.test</groupId>
+ <artifactId>soteria</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>app-custom</artifactId>
+ <packaging>war</packaging>
+
+ <build>
+ <finalName>app-custom</finalName>
+ </build>
+
+ <properties>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.soteria.test</groupId>
+ <artifactId>common</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/ProtectedServlet.java b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/ProtectedServlet.java
new file mode 100644
index 0000000..f7bfe5d
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/ProtectedServlet.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.soteria.test;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.security.enterprise.SecurityContext;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.HttpConstraint;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Test Servlet that prints out the name of the authenticated caller and whether
+ * this caller is in any of the roles {foo, bar, kaz}
+ *
+ *
+ */
+@WebServlet("/protectedServlet")
+@ServletSecurity(@HttpConstraint(rolesAllowed = "foo"))
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Inject
+ private SecurityContext securityContext;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a servlet \n");
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("web username: " + webName + "\n");
+
+ response.getWriter().write("web user has role \"foo\": " + request.isUserInRole("foo") + "\n");
+ response.getWriter().write("web user has role \"bar\": " + request.isUserInRole("bar") + "\n");
+ response.getWriter().write("web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n");
+
+ String contextName = null;
+ if (securityContext.getCallerPrincipal() != null) {
+ contextName = securityContext.getCallerPrincipal().getName();
+ }
+
+ response.getWriter().write("context username: " + contextName + "\n");
+
+ response.getWriter().write("context user has role \"foo\": " + securityContext.isCallerInRole("foo") + "\n");
+ response.getWriter().write("context user has role \"bar\": " + securityContext.isCallerInRole("bar") + "\n");
+ response.getWriter().write("context user has role \"kaz\": " + securityContext.isCallerInRole("kaz") + "\n");
+
+ response.getWriter().write("has access " + securityContext.hasAccessToWebResource("/servlets"));
+
+
+ }
+
+}
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/Servlet.java b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/Servlet.java
new file mode 100644
index 0000000..375f477
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/Servlet.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.soteria.test;
+
+import java.io.IOException;
+
+import javax.annotation.security.DeclareRoles;
+import javax.inject.Inject;
+import javax.security.enterprise.SecurityContext;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.glassfish.soteria.SecurityContextImpl;
+
+/**
+ * Test Servlet that prints out the name of the authenticated caller and whether
+ * this caller is in any of the roles {foo, bar, kaz}
+ *
+ *
+ */
+@DeclareRoles({ "foo", "bar", "kaz" })
+@WebServlet("/servlet")
+public class Servlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Inject
+ private SecurityContext securityContext;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a servlet \n");
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("web username: " + webName + "\n");
+
+ response.getWriter().write("web user has role \"foo\": " + request.isUserInRole("foo") + "\n");
+ response.getWriter().write("web user has role \"bar\": " + request.isUserInRole("bar") + "\n");
+ response.getWriter().write("web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n");
+
+ String contextName = null;
+ if (securityContext.getCallerPrincipal() != null) {
+ contextName = securityContext.getCallerPrincipal().getName();
+ }
+
+ response.getWriter().write("context username: " + contextName + "\n");
+
+ response.getWriter().write("context user has role \"foo\": " + securityContext.isCallerInRole("foo") + "\n");
+ response.getWriter().write("context user has role \"bar\": " + securityContext.isCallerInRole("bar") + "\n");
+ response.getWriter().write("context user has role \"kaz\": " + securityContext.isCallerInRole("kaz") + "\n");
+
+ response.getWriter().write("has access " + securityContext.hasAccessToWebResource("/protectedServlet") + "\n");
+
+ response.getWriter().write("All declared roles of user " + ((SecurityContextImpl)securityContext).getAllDeclaredCallerRoles() + "\n");
+ }
+
+}
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestAuthenticationMechanism.java b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestAuthenticationMechanism.java
new file mode 100644
index 0000000..cae948f
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestAuthenticationMechanism.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.soteria.test;
+
+import static javax.security.enterprise.identitystore.CredentialValidationResult.Status.VALID;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.security.enterprise.AuthenticationStatus;
+import javax.security.enterprise.AuthenticationException;
+import javax.security.auth.message.AuthException;
+import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
+import javax.security.enterprise.authentication.mechanism.http.HttpMessageContext;
+import javax.security.enterprise.identitystore.CredentialValidationResult;
+import javax.security.enterprise.identitystore.IdentityStoreHandler;
+import javax.security.enterprise.credential.UsernamePasswordCredential;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@RequestScoped
+public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {
+
+ @Inject
+ private IdentityStoreHandler identityStoreHandler;
+
+ @Override
+ public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {
+
+ // Get the (caller) name and password from the request
+ // NOTE: This is for the smallest possible example only. In practice
+ // putting the password in a request query parameter is highly
+ // insecure
+ String name = request.getParameter("name");
+ String password = request.getParameter("password");
+
+ if (name != null && password != null) {
+
+ // Delegate the {credentials in -> identity data out} function to
+ // the Identity Store
+ CredentialValidationResult result = identityStoreHandler.validate(
+ new UsernamePasswordCredential(name, password));
+
+ if (result.getStatus() == VALID) {
+ // Communicate the details of the authenticated user to the
+ // container. In many cases the underlying handler will just store the details
+ // and the container will actually handle the login after we return from
+ // this method.
+ return httpMessageContext.notifyContainerAboutLogin(
+ result.getCallerPrincipal(), result.getCallerGroups());
+ } else {
+ return httpMessageContext.responseUnauthorized();
+ }
+ }
+
+ return httpMessageContext.doNothing();
+ }
+
+}
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestIdentityStore.java b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestIdentityStore.java
new file mode 100644
index 0000000..0200b04
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/java/org/glassfish/soteria/test/TestIdentityStore.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.soteria.test;
+
+import static java.util.Arrays.asList;
+import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;
+
+import java.util.HashSet;
+
+import javax.enterprise.context.RequestScoped;
+import javax.security.enterprise.identitystore.CredentialValidationResult;
+import javax.security.enterprise.identitystore.IdentityStore;
+import javax.security.enterprise.credential.UsernamePasswordCredential;
+
+@RequestScoped
+public class TestIdentityStore implements IdentityStore {
+
+ public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {
+
+ if (usernamePasswordCredential.compareTo("reza", "secret1")) {
+ return new CredentialValidationResult("reza", new HashSet<>(asList("foo", "bar")));
+ }
+
+ return INVALID_RESULT;
+ }
+
+}
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/beans.xml b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/beans.xml
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/web.xml b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..09fffb4
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app
+ xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+ version="3.1"
+>
+
+ <!-- Security constraints and roles. -->
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>User pages</web-resource-name>
+ <url-pattern>/protectedServlet</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>foo</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+
+ <security-role>
+ <role-name>foo</role-name>
+ </security-role>
+
+</web-app>
diff --git a/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/test/java/org/glassfish/soteria/test/AppCustomIT.java b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/test/java/org/glassfish/soteria/test/AppCustomIT.java
new file mode 100644
index 0000000..f48f1b8
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/security/soteria/app-custom/src/test/java/org/glassfish/soteria/test/AppCustomIT.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.soteria.test;
+
+import static org.glassfish.soteria.test.Assert.*;
+import static org.glassfish.soteria.test.ShrinkWrap.mavenWar;
+
+import org.glassfish.soteria.test.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.junit.Rule;
+import org.junit.AfterClass;
+import org.junit.rules.TestWatcher;
+
+import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
+import com.gargoylesoftware.htmlunit.WebResponse;
+import com.sun.ejte.ccl.reporter.SimpleReporterAdapter;
+
+@RunWith(Arquillian.class)
+public class AppCustomIT extends ArquillianBase {
+ private static SimpleReporterAdapter stat =
+ new SimpleReporterAdapter("appserv-tests");
+ @Rule
+ public TestWatcher reportWatcher=new ReportWatcher(stat, "Security::soteria::AppCustom");
+
+ @AfterClass
+ public static void printSummary(){
+ stat.printSummary();
+ }
+
+ @Deployment(testable = false)
+ public static Archive<?> createDeployment() {
+ return mavenWar();
+ }
+
+ @Test
+ public void testAuthenticated() {
+ assertDefaultAuthenticated(
+ responseFromServer("/servlet?name=reza&password=secret1"));
+ }
+
+ @Test
+ public void testNotAuthenticated() {
+ assertDefaultNotAuthenticatedUnprotected(
+ responseFromServer("/servlet"));
+ }
+
+ @Test
+ public void testNotAuthenticatedWrongName() {
+ assertDefaultNotAuthenticated(
+ responseFromServer("/servlet?name=romo&password=secret1"));
+ }
+
+ @Test
+ public void testNotAuthenticatedWrongPassword() {
+ assertDefaultNotAuthenticated(
+ responseFromServer("/servlet?name=reza&password=wrongpassword"));
+ }
+
+}