Repository: quarkusio/quarkus
Issue: Quarkus Form Authentication...404 Response

**Description**
I'm using form authentication (quarkus.http.auth.form.enabled = true) with security-jpa and it works fine except when there is a post authorization error.  Also, my spa is located in resources/META-INF/resources

During my development I had a null pointer in the endpoint I set up as a re-direct.  I corrected the logic, then re-submitted my login to j_security_check and got a 404.  This one took me awhile to figure out the issue.  Since the error occured after authentication, my browser had the quarkus-credential cookie and subsequent attempts to login with the cookie present triggers a 404 response.  

I built a unit test to reproduce the error:
public void testFormBasedAuthentication() {

               ValidatableResponse response = given()
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .body("j_username=read.only&j_password=jackplane")
                .post("j_security_check")
                .then()
                .statusCode(Status.FOUND.getStatusCode())
                .cookie("quarkus-credential",notNullValue());
                String cookie = response.extract().cookie("quarkus-credential");

               // submit another login with the cookie received in the prior response
                given()
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .body("j_username=read.only&j_password=jackplane")
                .cookie("quarkus-credential", cookie, "")
                .post("j_security_check")
                .then()
                .statusCode(Status.FOUND.getStatusCode())
                .cookie("xsrf-token",notNullValue());
        }
Is this operating as intended to prevent subsequent login when a cookie is currently valid?  If so, a 404 doesn't seem to be the correct status code.
**Implementation ideas**
Could the form based authentication logic return a different response ?


Changed files:
extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/FormAuthenticationMechanism.java
extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/FormAuthTestCase.java

diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/FormAuthTestCase.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/FormAuthTestCase.java
index c8985925854..e2983588465 100644
--- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/FormAuthTestCase.java
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/FormAuthTestCase.java
@@ -45,7 +45,8 @@ public JavaArchive get() {
     @BeforeAll
     public static void setup() {
         TestIdentityController.resetRoles()
-                .add("admin", "admin", "admin");
+                .add("admin", "admin", "admin")
+                .add("test", "test", "admin");
     }
 
     @Test
@@ -90,6 +91,33 @@ public void testFormBasedAuthSuccess() {
                 .statusCode(200)
                 .body(equalTo("admin:/admin"));
 
+        //now authenticate with a different user
+        RestAssured
+                .given()
+                .filter(cookies)
+                .redirects().follow(false)
+                .when()
+                .formParam("j_username", "test")
+                .formParam("j_password", "test")
+                .post("/j_security_check")
+                .then()
+                .assertThat()
+                .statusCode(302)
+                .header("location", containsString("/admin"))
+                .cookie("quarkus-credential",
+                        RestAssuredMatchers.detailedCookie().value(notNullValue()).secured(false));
+
+        RestAssured
+                .given()
+                .filter(cookies)
+                .redirects().follow(false)
+                .when()
+                .get("/admin")
+                .then()
+                .assertThat()
+                .statusCode(200)
+                .body(equalTo("test:/admin"));
+
     }
 
     @Test
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/FormAuthenticationMechanism.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/FormAuthenticationMechanism.java
index 062965097f7..d30b1ff676f 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/FormAuthenticationMechanism.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/FormAuthenticationMechanism.java
@@ -147,21 +147,21 @@ static Uni<ChallengeData> getRedirect(final RoutingContext exchange, final Strin
     public Uni<SecurityIdentity> authenticate(RoutingContext context,
             IdentityProviderManager identityProviderManager) {
 
-        PersistentLoginManager.RestoreResult result = loginManager.restore(context);
-        if (result != null) {
-            Uni<SecurityIdentity> ret = identityProviderManager
-                    .authenticate(new TrustedAuthenticationRequest(result.getPrincipal()));
-            return ret.onItem().invoke(new Consumer<SecurityIdentity>() {
-                @Override
-                public void accept(SecurityIdentity securityIdentity) {
-                    loginManager.save(securityIdentity, context, result, context.request().isSSL());
-                }
-            });
-        }
-
         if (context.normalisedPath().endsWith(postLocation) && context.request().method().equals(HttpMethod.POST)) {
+            //we always re-auth if it is a post to the auth URL
             return runFormAuth(context, identityProviderManager);
         } else {
+            PersistentLoginManager.RestoreResult result = loginManager.restore(context);
+            if (result != null) {
+                Uni<SecurityIdentity> ret = identityProviderManager
+                        .authenticate(new TrustedAuthenticationRequest(result.getPrincipal()));
+                return ret.onItem().invoke(new Consumer<SecurityIdentity>() {
+                    @Override
+                    public void accept(SecurityIdentity securityIdentity) {
+                        loginManager.save(securityIdentity, context, result, context.request().isSSL());
+                    }
+                });
+            }
             return Uni.createFrom().optional(Optional.empty());
         }
     }