quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Conflict between form-based auth logout and quarkus.http.auth.form.new-cookie-interval #42613

Open ksdev-pl opened 3 months ago

ksdev-pl commented 3 months ago

Describe the bug

Hello. Maybe I'm missing something, but have a look (example project at https://github.com/ksdev-pl/quarkus-logout-conflict):

Let's say we have a simple form-based authentication with logout method implemented according to the documentation (https://quarkus.io/guides/security-authentication-mechanisms#form-auth):

    @GET
    @Path("logout")
    public Response logout() {
        if (identity.getIdentity().isAnonymous()) {
            throw new UnauthorizedException("Not authenticated");
        }
        final NewCookie removeCookie = new NewCookie.Builder(authCookieName)
            .maxAge(0)
            .expiry(Date.from(Instant.EPOCH))
            .path("/")
            .build();
        return Response.seeOther(URI.create("/auth/login"))
            .cookie(removeCookie)
            .build();
    }

Let's test it:

  1. We login using POST http://localhost:8080/j_security_check - this sets the quarkus-credential cookie.
  2. After successful login we access the protected page.
  3. On the protected page we click on "logout", which destroys the cookie and redirects us back to the /login page. Logout response headers look like this:
    HTTP/1.1 303 See Other
    Location: http://localhost:8080/auth/login
    Set-Cookie: quarkus-credential=;Version=1;Path=/;Max-Age=0;Expires=Thu, 01-Jan-1970 00:00:00 GMT
    content-length: 0

    Everything is fine and dandy, we're logged out.

Now let's take the quarkus.http.auth.form.new-cookie-interval into consideration, which by default is 1 minute:

  1. We login using POST http://localhost:8080/j_security_check - this sets the quarkus-credential cookie.
  2. After successful login we access the protected page.
  3. We wait more than 1 minute.
  4. On the protected page we click on "logout", which should destroy the cookie and redirects us back to the /login page. Logout response headers look like this:
    HTTP/1.1 303 See Other
    Location: http://localhost:8080/auth/login
    Set-Cookie: quarkus-credential=;Version=1;Path=/;Max-Age=0;Expires=Thu, 01-Jan-1970 00:00:00 GMT
    content-length: 0
    set-cookie: quarkus-credential=DD0QkzbLhLqcmjoqf6QvrSHRsLZRm0VmXp9ILRCpfMKh4A8dGI9kwHMSo5g89hKt; Path=/; SameSite=Strict

We see the login screen, job well done, we implemented the logout? Nope, the user is still logged in and protected resources are still accessible (and stays logged in for the duration of quarkus.http.auth.form.timeout).

You see the issue in the headers - "destroy" cookie is overwritten by the "new-cookie-interval-cookie", or whatever is its name (at least I guess that it's new-cookie-interval functionality).

It looks like using default Quarkus configuration (new-cookie-interval equal to 1 minute) and example from documentation (logout code) we can easily arrive at a not-obviously non-working logout.

Expected behavior

Auth cookie is destroyed during logout.

Actual behavior

Auth cookie is not destroyed during logout if request was made after new-cookie-interval time.

How to Reproduce?

Steps in description above. Basic example project: https://github.com/ksdev-pl/quarkus-logout-conflict

Output of uname -a or ver

Linux fedora 6.10.4-200.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Aug 11 15:32:50 UTC 2024 x86_64 GNU/Linux

Output of java -version

openjdk 21.0.1 2023-10-17 LTS

Quarkus version or git rev

Quarkus 3.13.2

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.6 (Red Hat 3.9.6-6)

Additional information

No response

michalvavrik commented 1 week ago

hey @ksdev-pl, sorry I missed this issue. I'll try to have a look within a week and get back to you. Thanks for the reproducer.