This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch TOMEE-4108
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit dd2eb4ac5afba150f680bf55db0b41866463f364
Author: Jean-Louis Monteiro <[email protected]>
AuthorDate: Tue Nov 8 18:27:20 2022 +0100

    TOMEE-4108: Backport TOMEE-4065: Fix to allow @LoginToContinue to be used 
directly in the HttpAuthenticationMechanism instead of requiring the interface 
to be implemented. Thanks Stefan Kalscheuer for reporting and for the fix
---
 itests/pom.xml                                     |   1 +
 itests/tomee-security-itests/pom.xml               | 100 +++++++
 .../tomee/security/itest/AnotherAuthMechanism.java |  83 ++++++
 .../apache/tomee/security/itest/AuthMechanism.java |  69 +++++
 .../tomee/security/itest/FormAuthConfig.java       |  54 ++++
 .../tomee/security/itest/LoginToContinueTest.java  | 310 +++++++++++++++++++++
 .../security/cdi/LoginToContinueInterceptor.java   |   6 +-
 ...curityServletAuthenticationMechanismMapper.java |   4 +-
 8 files changed, 624 insertions(+), 3 deletions(-)

diff --git a/itests/pom.xml b/itests/pom.xml
index 298368e994..7d593d7afc 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -48,6 +48,7 @@
     <module>openejb-itests-web</module>
     <module>jaxrs</module>
     <module>ejb</module>
+    <module>tomee-security-itests</module>
   </modules>
 
 </project>
diff --git a/itests/tomee-security-itests/pom.xml 
b/itests/tomee-security-itests/pom.xml
new file mode 100644
index 0000000000..1f69b24cac
--- /dev/null
+++ b/itests/tomee-security-itests/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+-->
+<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/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <artifactId>itests</artifactId>
+    <groupId>org.apache.tomee</groupId>
+    <version>8.0.14-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>tomee-security-itests</artifactId>
+  <packaging>jar</packaging>
+  <name>TomEE :: iTests :: TomEE Security</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <version>${project.version}</version>
+          </systemPropertyVariables>
+          <!--
+          <reuseForks>true</reuseForks>
+          <forkCount>1C</forkCount>
+          -->
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>tomee-server-composer</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>apache-tomee</artifactId>
+      <version>8.0.14-SNAPSHOT</version>
+      <type>tar.gz</type>
+      <classifier>microprofile</classifier>
+      <exclusions>
+        <exclusion>
+          <groupId>*</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>javaee-api</artifactId>
+      <version>8.0-6</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>openejb-cxf-rs</artifactId>
+      <version>${tomee.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>tomee-security</artifactId>
+      <version>8.0.14-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.sourceforge.htmlunit</groupId>
+      <artifactId>htmlunit</artifactId>
+      <version>2.33</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
+
diff --git 
a/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AnotherAuthMechanism.java
 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AnotherAuthMechanism.java
new file mode 100644
index 0000000000..2aa10773b0
--- /dev/null
+++ 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AnotherAuthMechanism.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tomee.security.itest;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.security.enterprise.AuthenticationException;
+import javax.security.enterprise.AuthenticationStatus;
+import 
javax.security.enterprise.authentication.mechanism.http.AutoApplySession;
+import 
javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
+import 
javax.security.enterprise.authentication.mechanism.http.HttpMessageContext;
+import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.HttpMethod;
+import org.apache.tomee.security.http.LoginToContinueMechanism;
+
+import static java.util.Collections.singleton;
+
+@ApplicationScoped
+@AutoApplySession
+@LoginToContinue
+public class AnotherAuthMechanism implements HttpAuthenticationMechanism, 
LoginToContinueMechanism {
+
+    @Override
+    public AuthenticationStatus validateRequest(
+        HttpServletRequest request,
+        HttpServletResponse response,
+        HttpMessageContext httpMessageContext) throws
+                                               AuthenticationException {
+        final String token = request.getParameter("token");
+
+        if (validateForm(httpMessageContext.getRequest(), token)) {
+
+            // validating the token would go here. We obviously send only a 
random string so
+            // not doing anything
+            if (!"1234ABCD".equals(token)) {
+                return httpMessageContext.responseUnauthorized();
+            }
+
+            return httpMessageContext.notifyContainerAboutLogin("jwt-token", 
singleton("tomcat"));
+        }
+
+        return httpMessageContext.doNothing();
+    }
+
+    private boolean validateForm(final HttpServletRequest request, final 
String token) {
+        return request.getMethod().equals(HttpMethod.POST) &&
+               request.getRequestURI().endsWith("/login-jwt") &&
+               token != null && !token.isEmpty();
+    }
+
+    @Override
+    public LoginToContinue getLoginToContinue() {
+        return FakeAnnotationHolder.class.getAnnotation(LoginToContinue.class);
+    }
+
+    // to make sure we use the method and not the annotation, we use this 
class instead of adding the annotation on the
+    // mechanism. If the annotation isn't read from this definition, it will 
fail because loginPage and errorPage are
+    // by default different
+    @LoginToContinue(
+        loginPage = "/login-app",
+        errorPage = "/login-error-app"
+    )
+    public static class FakeAnnotationHolder {
+
+    }
+}
\ No newline at end of file
diff --git 
a/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AuthMechanism.java
 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AuthMechanism.java
new file mode 100644
index 0000000000..615e08dec4
--- /dev/null
+++ 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/AuthMechanism.java
@@ -0,0 +1,69 @@
+/*
+ * 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.tomee.security.itest;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.security.enterprise.AuthenticationException;
+import javax.security.enterprise.AuthenticationStatus;
+import 
javax.security.enterprise.authentication.mechanism.http.AutoApplySession;
+import 
javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
+import 
javax.security.enterprise.authentication.mechanism.http.HttpMessageContext;
+import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.HttpMethod;
+
+import static java.util.Collections.singleton;
+
+@ApplicationScoped
+@AutoApplySession
+@LoginToContinue(
+    loginPage = "/login-app",
+    errorPage = "/login-error-app"
+)
+public class AuthMechanism implements HttpAuthenticationMechanism {
+
+    @Override
+    public AuthenticationStatus validateRequest(
+        HttpServletRequest request,
+        HttpServletResponse response,
+        HttpMessageContext httpMessageContext) throws
+                                               AuthenticationException {
+        final String token = request.getParameter("token");
+
+        if (validateForm(httpMessageContext.getRequest(), token)) {
+
+            // validating the token would go here. We obviously send only a 
random string so
+            // not doing anything
+            if (!"1234ABCD".equals(token)) {
+                return httpMessageContext.responseUnauthorized();
+            }
+
+            return httpMessageContext.notifyContainerAboutLogin("jwt-token", 
singleton("tomcat"));
+        }
+
+        return httpMessageContext.doNothing();
+    }
+
+    private boolean validateForm(final HttpServletRequest request, final 
String token) {
+        return request.getMethod().equals(HttpMethod.POST) &&
+               request.getRequestURI().endsWith("/login-jwt") &&
+               token != null && !token.isEmpty();
+    }
+}
\ No newline at end of file
diff --git 
a/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/FormAuthConfig.java
 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/FormAuthConfig.java
new file mode 100644
index 0000000000..36a6471029
--- /dev/null
+++ 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/FormAuthConfig.java
@@ -0,0 +1,54 @@
+/*
+ * 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.tomee.security.itest;
+
+import javax.enterprise.context.ApplicationScoped;
+import 
javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;
+import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
+import javax.security.enterprise.credential.Credential;
+import javax.security.enterprise.credential.UsernamePasswordCredential;
+import javax.security.enterprise.identitystore.CredentialValidationResult;
+import javax.security.enterprise.identitystore.IdentityStore;
+
+import static 
javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT;
+import static 
javax.security.enterprise.identitystore.CredentialValidationResult.NOT_VALIDATED_RESULT;
+import static java.util.Collections.singleton;
+
+@ApplicationScoped
+@FormAuthenticationMechanismDefinition(
+        loginToContinue = @LoginToContinue(
+                loginPage = "/login-form-app",
+                errorPage = "/login-error-app"
+        )
+)
+public class FormAuthConfig implements IdentityStore {
+    @Override
+    public CredentialValidationResult validate(Credential credential) {
+        if (credential instanceof UsernamePasswordCredential) {
+            if ("testuser".equalsIgnoreCase(((UsernamePasswordCredential) 
credential).getCaller())
+                    && 
"1234ABCD".equalsIgnoreCase(((UsernamePasswordCredential) 
credential).getPasswordAsString())) {
+                return new CredentialValidationResult("testuser", 
singleton("tomcat"));
+            } else {
+                return INVALID_RESULT;
+            }
+        } else {
+            return NOT_VALIDATED_RESULT;
+        }
+    }
+}
diff --git 
a/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/LoginToContinueTest.java
 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/LoginToContinueTest.java
new file mode 100644
index 0000000000..5a8fe17987
--- /dev/null
+++ 
b/itests/tomee-security-itests/src/test/java/org/apache/tomee/security/itest/LoginToContinueTest.java
@@ -0,0 +1,310 @@
+/*
+ * 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.tomee.security.itest;
+
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import javax.enterprise.context.ApplicationScoped;
+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;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.johnzon.jaxrs.JohnzonProvider;
+import org.apache.tomee.security.cdi.TomcatUserIdentityStoreDefinition;
+import org.apache.tomee.server.composer.Archive;
+import org.apache.tomee.server.composer.TomEE;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Optional;
+
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class LoginToContinueTest {
+
+    @Test
+    public void testAnnotation() throws Exception {
+        final File appJar = Archive.archive()
+                                   .add(this.getClass())
+                                   .add(ColorService.class)
+                                   .add(Api.class)
+                                   .add(LoginServlet.class)
+                                   .add(FormLoginServlet.class)
+                                   .add(ErrorServlet.class)
+                                   .add(TestServlet.class)
+                                   .add(AuthMechanism.class)
+                                   .asJar();
+
+        final ArrayList<String> output = new ArrayList<>();
+        final TomEE tomee = TomEE.microprofile()
+                                 //.debug(5005, true)
+                                 .add("webapps/test/WEB-INF/beans.xml", "")
+                                 .add("webapps/test/WEB-INF/lib/app.jar", 
appJar)
+                                 .watch("org.apache.tomee.", "\n", output::add)
+                                 .update()
+                                 .build();
+
+
+        { // do something
+            final WebClient webClient = 
createWebClient(tomee.toURI().resolve("/test").toURL());
+            final Response response = webClient.reset()
+                                               .path("/colors")
+                                               .header("Content-Type", 
"application/json")
+                                               .get();
+            assertEquals(200, response.getStatus());
+        }
+
+        // assert logs
+        assertNotPresent(output, "\tat org."); // no stack traces
+
+        {
+            final com.gargoylesoftware.htmlunit.WebClient webClient = new 
com.gargoylesoftware.htmlunit.WebClient();
+            final HtmlPage page = 
webClient.getPage(tomee.toURI().resolve("/test/auth-app").toURL());
+            assertEquals(200, page.getWebResponse().getStatusCode());
+
+            final HtmlForm login = page.getFormByName("login");
+            login.getInputByName("token").setValueAttribute("1234ABCD");
+
+            final Page result = login.getInputByName("submit").click();
+            assertEquals(200, result.getWebResponse().getStatusCode());
+            assertEquals("ok!", result.getWebResponse().getContentAsString());
+        }
+    }
+
+    @Test
+    public void testInterface() throws Exception {
+        final File appJar = Archive.archive()
+                                   .add(this.getClass())
+                                   .add(ColorService.class)
+                                   .add(Api.class)
+                                   .add(LoginServlet.class)
+                                   .add(FormLoginServlet.class)
+                                   .add(ErrorServlet.class)
+                                   .add(TestServlet.class)
+                                   .add(AnotherAuthMechanism.class)
+                                   
.add(AnotherAuthMechanism.FakeAnnotationHolder.class)
+                                   .asJar();
+
+        final ArrayList<String> output = new ArrayList<>();
+        final TomEE tomee = TomEE.microprofile()
+                                 //.debug(5005, true)
+                                 .add("webapps/test/WEB-INF/beans.xml", "")
+                                 .add("webapps/test/WEB-INF/lib/app.jar", 
appJar)
+                                 .watch("org.apache.tomee.", "\n", output::add)
+                                 .update()
+                                 .build();
+
+
+        { // do something
+            final WebClient webClient = 
createWebClient(tomee.toURI().resolve("/test").toURL());
+            final Response response = webClient.reset()
+                                               .path("/colors")
+                                               .header("Content-Type", 
"application/json")
+                                               .get();
+            assertEquals(200, response.getStatus());
+        }
+
+        // assert logs
+        assertNotPresent(output, "\tat org."); // no stack traces
+
+        {
+            final com.gargoylesoftware.htmlunit.WebClient webClient = new 
com.gargoylesoftware.htmlunit.WebClient();
+            final HtmlPage page = 
webClient.getPage(tomee.toURI().resolve("/test/auth-app").toURL());
+            assertEquals(200, page.getWebResponse().getStatusCode());
+
+            final HtmlForm login = page.getFormByName("login");
+            login.getInputByName("token").setValueAttribute("1234ABCD");
+
+            final Page result = login.getInputByName("submit").click();
+            assertEquals(200, result.getWebResponse().getStatusCode());
+            assertEquals("ok!", result.getWebResponse().getContentAsString());
+        }
+    }
+
+    @Test
+    public void testFormDefinition() throws Exception {
+        final File appJar = Archive.archive()
+                                   .add(this.getClass())
+                                   .add(ColorService.class)
+                                   .add(Api.class)
+                                   .add(LoginServlet.class)
+                                   .add(FormLoginServlet.class)
+                                   .add(ErrorServlet.class)
+                                   .add(TestServlet.class)
+                                   .add(FormAuthConfig.class)
+                                   .asJar();
+
+        final ArrayList<String> output = new ArrayList<>();
+        final TomEE tomee = TomEE.microprofile()
+                                 //.debug(5005, true)
+                                 .add("webapps/test/WEB-INF/beans.xml", "")
+                                 .add("webapps/test/WEB-INF/lib/app.jar", 
appJar)
+                                 .watch("org.apache.tomee.", "\n", output::add)
+                                 .update()
+                                 .build();
+
+
+        { // do something
+            final WebClient webClient = 
createWebClient(tomee.toURI().resolve("/test").toURL());
+            final Response response = webClient.reset()
+                                               .path("/colors")
+                                               .header("Content-Type", 
"application/json")
+                                               .get();
+            assertEquals(200, response.getStatus());
+        }
+
+        // assert logs
+        assertNotPresent(output, "\tat org."); // no stack traces
+
+        {
+            final com.gargoylesoftware.htmlunit.WebClient webClient = new 
com.gargoylesoftware.htmlunit.WebClient();
+            final HtmlPage page = 
webClient.getPage(tomee.toURI().resolve("/test/auth-app").toURL());
+            assertEquals(200, page.getWebResponse().getStatusCode());
+
+            final HtmlForm login = page.getFormByName("login");
+            login.getInputByName("j_username").setValueAttribute("testuser");
+            login.getInputByName("j_password").setValueAttribute("1234ABCD");
+
+            final Page result = login.getInputByName("submit").click();
+            assertEquals(200, result.getWebResponse().getStatusCode());
+            assertEquals("ok!", result.getWebResponse().getContentAsString());
+        }
+    }
+
+    public void assertPresent(final ArrayList<String> output, final String s) {
+        final Optional<String> actual = output.stream()
+                .filter(line -> line.contains(s))
+                .findFirst();
+
+        assertTrue(actual.isPresent());
+    }
+    public void assertNotPresent(final ArrayList<String> output, final String 
s) {
+        final Optional<String> actual = output.stream()
+                .filter(line -> line.contains(s))
+                .findFirst();
+
+        assertTrue(!actual.isPresent());
+    }
+
+    private static WebClient createWebClient(final URL base) {
+        return WebClient.create(base.toExternalForm(), singletonList(new 
JohnzonProvider<>()),
+                                singletonList(new LoggingFeature()), null);
+    }
+
+    @ApplicationPath("/api")
+    public class Api extends Application {
+    }
+
+    @Path("/colors")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @ApplicationScoped
+    public static class ColorService {
+
+        @GET
+        public String getColor() {
+            return "Green";
+        }
+    }
+
+    @TomcatUserIdentityStoreDefinition
+    @WebServlet(urlPatterns = "/login-app")
+    public static class LoginServlet extends HttpServlet {
+        @Override
+        protected void doGet(final HttpServletRequest req, final 
HttpServletResponse resp)
+            throws ServletException, IOException {
+            final String loginPage =
+                "<html>" +
+                "<body>" +
+                "  <h1>Login Page</h1>" +
+                "  <form name=\"login\" method=post action=\"login-jwt\">\n" +
+                "    <p>JWT Token:</p>" +
+                "    <input type=\"text\" name=\"token\">\n" +
+                "    <input type=\"submit\" name=\"submit\" 
value=\"Submit\">\n" +
+                "    <input type=\"reset\" value=\"Reset\">" +
+                "  </form>" +
+                "</body>" +
+                "</html>";
+            resp.getWriter().write(loginPage);
+        }
+    }
+
+    @TomcatUserIdentityStoreDefinition
+    @WebServlet(urlPatterns = "/login-form-app")
+    public static class FormLoginServlet extends HttpServlet {
+        @Override
+        protected void doGet(final HttpServletRequest req, final 
HttpServletResponse resp)
+            throws ServletException, IOException {
+            final String loginPage =
+                    "<html>" +
+                    "<body>" +
+                    "  <h1>Login Page</h1>" +
+                    "  <form name=\"login\" method=post 
action=\"j_security_check\">\n" +
+                    "    <p>Credentials:</p>" +
+                    "    <input type=\"text\" name=\"j_username\">\n" +
+                    "    <input type=\"password\" name=\"j_password\">\n" +
+                    "    <input type=\"submit\" name=\"submit\" 
value=\"Submit\">\n" +
+                    "    <input type=\"reset\" value=\"Reset\">" +
+                    "  </form>" +
+                    "</body>" +
+                    "</html>";
+            resp.getWriter().write(loginPage);
+        }
+    }
+
+    @WebServlet(urlPatterns = "/login-error-app")
+    public static class ErrorServlet extends HttpServlet {
+        @Override
+        protected void doGet(final HttpServletRequest req, final 
HttpServletResponse resp)
+            throws ServletException, IOException {
+
+        }
+    }
+
+    @TomcatUserIdentityStoreDefinition
+    @WebServlet(urlPatterns = "/auth-app")
+    @ServletSecurity(@HttpConstraint(rolesAllowed = "tomcat"))
+    public static class TestServlet extends HttpServlet {
+        @Override
+        protected void doGet(final HttpServletRequest req, final 
HttpServletResponse resp)
+            throws ServletException, IOException {
+            resp.getWriter().write("ok!");
+        }
+    }
+
+}
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/LoginToContinueInterceptor.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/LoginToContinueInterceptor.java
index 1f7ac9963d..071f5256a7 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/LoginToContinueInterceptor.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/LoginToContinueInterceptor.java
@@ -218,6 +218,10 @@ public class LoginToContinueInterceptor {
             return ((LoginToContinueMechanism) 
invocationContext.getTarget()).getLoginToContinue();
         }
 
-        throw new IllegalArgumentException();
+        if 
(invocationContext.getTarget().getClass().isAnnotationPresent(LoginToContinue.class))
 {
+            return 
invocationContext.getTarget().getClass().getAnnotation(LoginToContinue.class);
+        }
+
+        throw new IllegalArgumentException("Missing @LoginToContinue on type " 
+ invocationContext.getTarget().getClass());
     }
 }
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java
index 7ac4772f55..81d2935e7b 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityServletAuthenticationMechanismMapper.java
@@ -74,7 +74,7 @@ public class 
TomEESecurityServletAuthenticationMechanismMapper {
 
         final Set<HttpAuthenticationMechanism> availableBeans = 
authenticationMechanisms.stream().collect(Collectors.toSet());
         availableBeans.removeAll(servletAuthenticationMapper.values());
-        availableBeans.remove(defaultAuthenticationMechanism); // this our 
wrapper
+        availableBeans.remove(defaultAuthenticationMechanism); // this is our 
wrapper
 
         if (availableBeans.size() == 1) {
             
defaultAuthenticationMechanism.setDelegate(availableBeans.iterator().next());
@@ -89,7 +89,7 @@ public class 
TomEESecurityServletAuthenticationMechanismMapper {
                     "Deploy a single one for the application, or associate it 
with a @WebServlet.");
 
         } else if (servletAuthenticationMapper.size() == 1) {
-            // don't think it's covered by the spec but sotera seems to 
support such a case
+            // don't think it's covered by the spec but soteria seems to 
support such a case
             
defaultAuthenticationMechanism.setDelegate(servletAuthenticationMapper.values().iterator().next());
 
         }

Reply via email to