diff --git a/commafeed-server/pom.xml b/commafeed-server/pom.xml
index 2b65e2c7..adac30b4 100644
--- a/commafeed-server/pom.xml
+++ b/commafeed-server/pom.xml
@@ -248,6 +248,10 @@
io.quarkus
quarkus-arc
+
+ io.quarkus
+ quarkus-reactive-routes
+
io.quarkus
quarkus-security
diff --git a/commafeed-server/src/main/java/com/commafeed/security/FormAuthenticationCookieInterceptor.java b/commafeed-server/src/main/java/com/commafeed/security/FormAuthenticationCookieInterceptor.java
new file mode 100644
index 00000000..3692ed2d
--- /dev/null
+++ b/commafeed-server/src/main/java/com/commafeed/security/FormAuthenticationCookieInterceptor.java
@@ -0,0 +1,34 @@
+package com.commafeed.security;
+
+import io.quarkus.vertx.http.runtime.HttpConfiguration;
+import io.quarkus.vertx.http.runtime.security.FormAuthenticationMechanism;
+import io.quarkus.vertx.web.RouteFilter;
+import io.vertx.core.http.Cookie;
+import io.vertx.core.http.impl.ServerCookie;
+import io.vertx.ext.web.RoutingContext;
+import jakarta.inject.Singleton;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Intercepts responses and sets a Max-Age on the cookie created by {@link FormAuthenticationMechanism} because it has no value by default.
+ *
+ * This is a workaround for https://github.com/quarkusio/quarkus/issues/42463
+ */
+@RequiredArgsConstructor
+@Singleton
+public class FormAuthenticationCookieInterceptor {
+
+ private final HttpConfiguration config;
+
+ @RouteFilter(Integer.MAX_VALUE)
+ public void cookieInterceptor(RoutingContext context) {
+ context.addHeadersEndHandler(v -> {
+ Cookie cookie = context.request().getCookie(config.auth.form.cookieName);
+ if (cookie instanceof ServerCookie sc && sc.isChanged()) {
+ cookie.setMaxAge(config.auth.form.timeout.toSeconds());
+ }
+ });
+
+ context.next();
+ }
+}
diff --git a/commafeed-server/src/main/java/com/commafeed/security/mechanism/CookieMaxAgeFormAuthenticationMechanism.java b/commafeed-server/src/main/java/com/commafeed/security/mechanism/CookieMaxAgeFormAuthenticationMechanism.java
deleted file mode 100644
index c5ffa581..00000000
--- a/commafeed-server/src/main/java/com/commafeed/security/mechanism/CookieMaxAgeFormAuthenticationMechanism.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.commafeed.security.mechanism;
-
-import java.security.SecureRandom;
-import java.util.Base64;
-
-import io.quarkus.vertx.http.runtime.FormAuthConfig;
-import io.quarkus.vertx.http.runtime.FormAuthRuntimeConfig;
-import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig;
-import io.quarkus.vertx.http.runtime.HttpConfiguration;
-import io.quarkus.vertx.http.runtime.security.FormAuthenticationMechanism;
-import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
-import io.quarkus.vertx.http.runtime.security.PersistentLoginManager;
-import io.vertx.core.http.Cookie;
-import io.vertx.core.http.impl.ServerCookie;
-import io.vertx.ext.web.RoutingContext;
-import jakarta.annotation.Priority;
-import jakarta.inject.Singleton;
-import lombok.experimental.Delegate;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * HttpAuthenticationMechanism that wraps FormAuthenticationMechanism and sets a Max-Age on the cookie because it has no value by default.
- *
- * This is a workaround for https://github.com/quarkusio/quarkus/issues/42463
- */
-@Priority(1)
-@Singleton
-@Slf4j
-public class CookieMaxAgeFormAuthenticationMechanism implements HttpAuthenticationMechanism {
-
- // the temp encryption key, persistent across dev mode restarts
- static volatile String encryptionKey;
-
- @Delegate
- private final FormAuthenticationMechanism delegate;
-
- public CookieMaxAgeFormAuthenticationMechanism(HttpConfiguration httpConfiguration, HttpBuildTimeConfig buildTimeConfig) {
- String key;
- if (httpConfiguration.encryptionKey.isEmpty()) {
- if (encryptionKey != null) {
- // persist across dev mode restarts
- key = encryptionKey;
- } else {
- byte[] data = new byte[32];
- new SecureRandom().nextBytes(data);
- key = encryptionKey = Base64.getEncoder().encodeToString(data);
- log.warn("Encryption key was not specified for persistent FORM auth, using temporary key {}", key);
- }
- } else {
- key = httpConfiguration.encryptionKey.get();
- }
-
- FormAuthConfig form = buildTimeConfig.auth.form;
- FormAuthRuntimeConfig runtimeForm = httpConfiguration.auth.form;
- String loginPage = startWithSlash(runtimeForm.loginPage.orElse(null));
- String errorPage = startWithSlash(runtimeForm.errorPage.orElse(null));
- String landingPage = startWithSlash(runtimeForm.landingPage.orElse(null));
- String postLocation = startWithSlash(form.postLocation);
- String usernameParameter = runtimeForm.usernameParameter;
- String passwordParameter = runtimeForm.passwordParameter;
- String locationCookie = runtimeForm.locationCookie;
- String cookiePath = runtimeForm.cookiePath.orElse(null);
- boolean redirectAfterLogin = landingPage != null;
- String cookieSameSite = runtimeForm.cookieSameSite.name();
-
- PersistentLoginManager loginManager = new PersistentLoginManager(key, runtimeForm.cookieName, runtimeForm.timeout.toMillis(),
- runtimeForm.newCookieInterval.toMillis(), runtimeForm.httpOnlyCookie, cookieSameSite, cookiePath) {
- @Override
- public void save(String value, RoutingContext context, String cookieName, RestoreResult restoreResult, boolean secureCookie) {
- super.save(value, context, cookieName, restoreResult, secureCookie);
-
- // add max age to the cookie
- Cookie cookie = context.request().getCookie(cookieName);
- if (cookie instanceof ServerCookie sc && sc.isChanged()) {
- cookie.setMaxAge(runtimeForm.timeout.toSeconds());
- }
- }
- };
-
- this.delegate = new FormAuthenticationMechanism(loginPage, postLocation, usernameParameter, passwordParameter, errorPage,
- landingPage, redirectAfterLogin, locationCookie, cookieSameSite, cookiePath, loginManager);
- }
-
- private static String startWithSlash(String page) {
- if (page == null) {
- return null;
- }
- return page.startsWith("/") ? page : "/" + page;
- }
-}