You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2026/10/20 18:30:20 UTC

(causeway) branch main updated: CAUSEWAY-4054: [Wicket Viewer] Signin Remember Me Feature is now deprecated

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

andi-huber pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/main by this push:
     new 6b50a784be5 CAUSEWAY-4054: [Wicket Viewer] Signin Remember Me Feature is now deprecated
6b50a784be5 is described below

commit 6b50a784be54b1a083f65099728a4c4fe5f57209
Author: andi-huber <ah...@apache.org>
AuthorDate: Tue Oct 20 20:29:28 2026 +0200

    CAUSEWAY-4054: [Wicket Viewer] Signin Remember Me Feature is now
    deprecated
    
    Redefines the meaning of RememberMe, that is only remember the
    'username' of the last login.Let the browser handle passwords.
---
 .../core/config/CausewayConfiguration.java         |  47 ++----
 .../icontitle/ObjectIconAndTitlePanelFactory.java  |   1 -
 .../components/widgets/bootstrap/ModalDialog.java  |   2 +-
 .../wicket/ui/pages/login/CausewaySignInPanel.html |   5 +-
 .../wicket/ui/pages/login/CausewaySignInPanel.java |  10 +-
 .../wicket/ui/pages/login/SignInPanelAbstract.java | 171 ++++++++++-----------
 .../wicketapp/CausewayWicketApplication.java       |  71 +++------
 .../wicket/viewer/wicketapp/_CryptFactory.java     | 111 -------------
 .../wicket/viewer/wicketapp/CryptFactoryTest.java  | 161 -------------------
 9 files changed, 121 insertions(+), 458 deletions(-)

diff --git a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
index bcb4e86b507..53eab840e1c 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
@@ -90,6 +90,8 @@
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.commons.internal.base._StableValue;
 import org.apache.causeway.commons.internal.context._Context;
+import org.apache.causeway.core.config.CausewayConfiguration.Core;
+import org.apache.causeway.core.config.CausewayConfiguration.Viewer;
 import org.apache.causeway.core.config.metamodel.facets.ActionConfigOptions;
 import org.apache.causeway.core.config.metamodel.facets.AssociationLayoutConfigOptions;
 import org.apache.causeway.core.config.metamodel.facets.CollectionLayoutConfigOptions;
@@ -2648,10 +2650,9 @@ public record Collections(
                     int maxWindowSize) {
 
                 public Collections {
-                    if (defaultWindowSize > maxWindowSize) {
-                        throw new IllegalArgumentException(
+                    if (defaultWindowSize > maxWindowSize)
+						throw new IllegalArgumentException(
                                 "causeway.viewer.graphql.collections.default-window-size must not exceed max-window-size");
-                    }
                 }
             }
 
@@ -2673,10 +2674,9 @@ public record Autocomplete(
                     int maxWindowSize) {
 
                 public Autocomplete {
-                    if (defaultWindowSize > maxWindowSize) {
-                        throw new IllegalArgumentException(
+                    if (defaultWindowSize > maxWindowSize)
+						throw new IllegalArgumentException(
                                 "causeway.viewer.graphql.autocomplete.default-window-size must not exceed max-window-size");
-                    }
                 }
             }
 
@@ -3390,43 +3390,20 @@ public record RememberMe(
                  * Whether the sign-in page should have a 'remember me' link (the default), or if it should
                  * be suppressed.
                  *
-                 * <p>
-                 *     If 'remember me' is available and checked, then the viewer will allow users to login
-                 *     based on encrypted credentials stored in a cookie.  An {@link #getEncryptionKey() encryption key}
-                 *     can optionally be specified.
-                 *
+                 * <p> If 'remember me' is available and checked, then the viewer will remember 'username' and 'timezone'
+                 * for the login page using cookies. This does not include any secrets nor requires encryption.
                  */
                 @DefaultValue("false")
                 boolean suppress,
 
                 /**
-                 * If the 'remember me' feature is available, specifies the key to hold the encrypted
-                 * credentials in the cookie.
+                 * If the 'remember me' feature is available, specifies the cookie name prefix that is used for cookies to store timezone and username data.
                  */
                 @DefaultValue("causewayWicketRememberMe")
                 String cookieKey,
-                /**
-                 * If the 'remember me' feature is available, optionally specifies an encryption key
-                 * (a complex string acting as salt to the encryption algorithm) for computing the encrypted
-                 * credentials.
-                 *
-                 * <p>
-                 *     If not set, then (in production mode) the Wicket viewer will compute a random key each time it
-                 *     is started.  This will mean that any credentials stored between sessions will become invalid.
-                 *
-                 *
-                 * <p>
-                 *     Conversely, if set then (in production mode) then the same salt will be used each time the app
-                 *     is started, meaning that cached credentials can continue to be used across restarts.
-                 *
-                 *
-                 * <p>
-                 *     In prototype mode this setting is effectively ignored, because the same key will always be
-                 *     provided (either as set, or a fixed literal otherwise).
-                 *
-                 */
-                @DefaultValue
-                Optional<String> encryptionKey) {
+
+                @DefaultValue("Remember 'username' and 'timezone' for the next login.")
+                String description) {
 
             }
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
index 35be61c5a5f..9a18fd1c33d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
@@ -99,7 +99,6 @@ public Component createComponent(final String id, final IModel<?> model) {
     /**
      * refactoring hint: go through proper ComponentFactory channels instead
      */
-    @Deprecated
     public static Component entityIconAndTitlePanel(
             final String componentId,
             final ObjectAdapterModel objectAdapterModel) {
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
index 0634472c776..4b984ef4d02 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
@@ -47,7 +47,7 @@ public ModalDialog(final String markupId) {
     public ModalDialog(final String id, final IModel<T> model) {
         super(id, model);
         setFadeIn(false);
-        setUseKeyboard(true);
+        setCloseOnEscapeKey(true);
         setDisableEnforceFocus(true);
         setOutputMarkupPlaceholderTag(true);
         Wkt.containerAdd(this, getContentId()); // initial empty content
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.html b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.html
index 3fa80d1d8f1..683ad9014f2 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.html
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.html
@@ -33,10 +33,13 @@
                     <label wicket:for="timezone"><wicket:message key="timezoneLabel"/></label>
                     <select class="form-control" wicket:id="timezone" name="timezone" data-noreset="true"/>
                 </div>
-                <div class="form-check mb-3" wicket:id="rememberMeContainer">
+                <div class="form-check mb-3" wicket:id="rememberMeContainer" style="padding-left: 0px;">
                     <label>
                         <input type="checkbox" wicket:id="rememberMe"/> <wicket:message key="rememberMeLabel"/>
                     </label>
+                    <small class="d-block text-muted mt-1">
+                        <label wicket:id="rememberMeDescription"></label>
+                    </small>
                 </div>
 
                 <button type="submit" class="btn btn-primary"><wicket:message key="signInButtonLabel"/></button>
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.java
index 07448e6ab38..d4fed14f0c9 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/CausewaySignInPanel.java
@@ -27,6 +27,7 @@
 import org.apache.wicket.Page;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.jspecify.annotations.NonNull;
 
 import org.apache.causeway.applib.services.iactn.InteractionService;
 import org.apache.causeway.applib.services.inject.ServiceInjector;
@@ -40,7 +41,6 @@
 import org.apache.causeway.viewer.wicket.model.models.PageType;
 import org.apache.causeway.viewer.wicket.ui.pages.PageClassRegistry;
 
-import org.jspecify.annotations.NonNull;
 import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel;
 
 /**
@@ -114,14 +114,6 @@ protected void onSignInSucceeded() {
         super.onSignInSucceeded();
     }
 
-    @Override
-    protected void onSignInRemembered() {
-        if(isClearOriginalDestination) {
-            clearOriginalDestination();
-        }
-        super.onSignInRemembered();
-    }
-
     @Override
     protected void storeUserTimeZoneToSession(final @NonNull ZoneId zoneId) {
         userCurrentSessionTimeZoneHolder.setUserTimeZone(zoneId);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/SignInPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
index a8ea93c58e2..aaf3bcbf2c1 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/login/SignInPanelAbstract.java
@@ -21,10 +21,11 @@
 import java.time.ZoneId;
 import java.util.Optional;
 
-import org.apache.wicket.RestartResponseException;
-import org.apache.wicket.authentication.IAuthenticationStrategy;
+import jakarta.servlet.http.Cookie;
+
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.CheckBox;
 import org.apache.wicket.markup.html.form.PasswordTextField;
 import org.apache.wicket.markup.html.form.StatelessForm;
@@ -36,14 +37,18 @@
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
 import org.apache.wicket.request.resource.ResourceReference;
 import org.apache.wicket.util.cookies.CookieUtils;
+import org.jspecify.annotations.NonNull;
+
+import org.springframework.util.StringUtils;
 
+import org.apache.causeway.applib.services.i18n.TranslationContext;
 import org.apache.causeway.applib.value.semantics.TimeZoneChoiceProvider;
 import org.apache.causeway.commons.internal.base._Strings;
+import org.apache.causeway.core.config.CausewayConfiguration.Viewer.Wicket.RememberMe;
 import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt;
 
 import lombok.Getter;
-import org.jspecify.annotations.NonNull;
 import lombok.Setter;
 
 /**
@@ -63,7 +68,10 @@ public abstract class SignInPanelAbstract
     /** True if the panel should display a remember-me checkbox */
     private boolean includeRememberMe = true;
 
-    /** True if the user should be remembered via form persistence (cookies) */
+    /**
+     * True if the username and timezone should be remembered via form persistence (cookies).
+     * This does not include any secrets.
+     */
     @Getter @Setter
     private boolean rememberMe = true;
 
@@ -115,32 +123,11 @@ protected SignInFormWithTimeZone getSignInFormWithTimeZone() {
     protected void onConfigure() {
         // logged in already?
         if (isSignedIn() == false) {
-            var authenticationStrategy = authenticationStrategy();
-            // get username, password and zoneID from persistence store
-            final String[] data = authenticationStrategy.load();
-
-            if ((data != null) && (data.length > 1)) {
-                // try to sign in the user
-                if (signIn(data[0], data[1])) {
-                    username = data[0];
-                    password = data[1];
-
-                    var tzMememnto = recoverTimezone();
-                    if(_Strings.isNotEmpty(tzMememnto)) {
-                        try {
-                            timezone = ZoneId.of(tzMememnto);
-                        } catch (Exception e) {
-                            timezone = null;
-                            e.printStackTrace();
-                        }
-                    }
-
-                    onSignInRemembered();
-                } else {
-                    // the loaded credentials are wrong. erase them.
-                    authenticationStrategy.remove();
-                }
-            }
+            // get username and zoneID from cookies (if available)
+        	username = usernameCookie().recoverUsername()
+            		.orElse(null);
+        	timezone = timezoneCookie().recoverTimezone()
+            		.orElse(null);
         }
 
         super.onConfigure();
@@ -181,63 +168,17 @@ protected void onSignInFailed() {
      */
     protected void onSignInSucceeded() {
         Optional.ofNullable(getTimezone())
-            .ifPresent(zoneId->storeUserTimeZoneToSession(zoneId));
+            .ifPresent(this::storeUserTimeZoneToSession);
         // If login has been called because the user was not yet logged in, than continue to the
         // original destination, otherwise to the Home page
         continueToOriginalDestination();
         setResponsePage(getApplication().getHomePage());
     }
 
-    /**
-     * Called when sign-in was remembered.
-     * <p>
-     * By default tries to continue to the original destination or switches to the application's
-     * home page.
-     * <p>
-     * Note: This method will be called during rendering of this panel, thus a
-     * {@link RestartResponseException} has to be used to switch to a different page.
-     *
-     * @see #onConfigure()
-     */
-    protected void onSignInRemembered() {
-        Optional.ofNullable(getTimezone())
-            .ifPresent(zoneId->storeUserTimeZoneToSession(zoneId));
-
-        // logon successful. Continue to the original destination
-        continueToOriginalDestination();
-
-        // Ups, no original destination. Go to the home page
-        throw new RestartResponseException(getApplication().getHomePage());
-    }
-
     @Getter(lazy = true) private static final ResourceReference jsForTimezoneSelectDefault =
             new JavaScriptResourceReference(SignInPanelAbstract.class,
                     "js/client-side-timezone-select.js");
 
-    private IAuthenticationStrategy authenticationStrategy() {
-        return getApplication().getSecuritySettings()
-            .getAuthenticationStrategy();
-    }
-
-    // -- TIME ZONE COOKIES
-
-    private void rememberTimezone(final String tzMemento) {
-        new CookieUtils().save(timezoneCookieName(), tzMemento);
-    }
-
-    private String recoverTimezone() {
-        var cookie = new CookieUtils().getCookie(timezoneCookieName());
-        return cookie!=null
-                ? cookie.getValue()
-                : null;
-    }
-
-    private String timezoneCookieName() {
-        var rememberMe = getConfiguration().viewer().wicket().rememberMe();
-        var cookieName = rememberMe.cookieKey()+"_tz";
-        return cookieName;
-    }
-
     /**
      * Sign in form.
      */
@@ -268,11 +209,15 @@ public SignInFormWithTimeZone(final String id) {
                 .setMarkupId(TIME_ZONE_SELECT));
 
             // container for remember me checkbox
-            WebMarkupContainer rememberMeContainer = new WebMarkupContainer("rememberMeContainer");
+            var rememberMeContainer = new WebMarkupContainer("rememberMeContainer");
             add(rememberMeContainer);
 
             // Add rememberMe checkbox
             rememberMeContainer.add(new CheckBox("rememberMe"));
+            rememberMeContainer.add(new Label("rememberMeDescription",
+            		getTranslationService().translate(
+            				TranslationContext.named("Login"),
+            				getConfiguration().viewer().wicket().rememberMe().description())));
 
             // Show remember me checkbox?
             rememberMeContainer.setVisible(includeRememberMe);
@@ -283,26 +228,23 @@ public SignInFormWithTimeZone(final String id) {
          */
         @Override
         public final void onSubmit() {
-            var authenticationStrategy = authenticationStrategy();
-
             if (signIn(username, password)) {
-                if (rememberMe) {
-                    authenticationStrategy.save(
-                            username,
-                            password);
-
-                    // remember time-zone selection
-                    rememberTimezone(timezone!=null
-                          ? timezone.getId()
-                          : "");
-                } else {
-                    authenticationStrategy.remove();
+                if (isRememberMe()
+                		&& StringUtils.hasLength(username)) {
+                	// remember latest username
+                	usernameCookie()
+                		.rememberUsername(username);
                 }
+                if (isRememberMe()
+                		&& timezone!=null) {
+                	// remember time-zone selection
 
+                	timezoneCookie()
+                		.rememberTimezone(timezone);
+                }
                 onSignInSucceeded();
             } else {
                 onSignInFailed();
-                authenticationStrategy.remove();
             }
         }
 
@@ -323,4 +265,49 @@ private TimeZoneChoiceProvider getTimeZoneChoiceProvider() {
      */
     protected abstract void clearUserTimeZoneFromSession();
 
+    // -- USER NAME COOKIES
+
+    private record UsernameCookie(String cookieName) {
+    	UsernameCookie(final RememberMe conf) {
+    		this(conf.cookieKey() + "_usr");
+    	}
+    	void rememberUsername(final String username) {
+    		new CookieUtils().save(cookieName, username);
+    	}
+    	Optional<String> recoverUsername() {
+    		return Optional.ofNullable(new CookieUtils().getCookie(cookieName))
+					.map(Cookie::getValue)
+					.map(_Strings::emptyToNull);
+    	}
+    }
+
+    private UsernameCookie usernameCookie() {
+    	return new UsernameCookie(getConfiguration().viewer().wicket().rememberMe());
+    }
+
+    // -- TIME ZONE COOKIES
+
+    private record TimezoneCookie(String cookieName) {
+    	TimezoneCookie(final RememberMe conf) {
+    		this(conf.cookieKey() + "_tz");
+    	}
+    	void rememberTimezone(final ZoneId zoneId) {
+    		new CookieUtils().save(cookieName, zoneId.getId());
+    	}
+    	Optional<ZoneId> recoverTimezone() {
+    		try {
+    			return Optional.ofNullable(new CookieUtils().getCookie(cookieName))
+    					.map(Cookie::getValue)
+    					.map(_Strings::emptyToNull)
+    					.map(ZoneId::of);
+    		} catch (Exception e) {
+    			e.printStackTrace();
+    			return Optional.empty();
+    		}
+    	}
+    }
+
+    private TimezoneCookie timezoneCookie() {
+    	return new TimezoneCookie(getConfiguration().viewer().wicket().rememberMe());
+    }
 }
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
index dcff1904d92..323bda68155 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CausewayWicketApplication.java
@@ -21,9 +21,32 @@
 import java.time.Duration;
 import java.util.Collections;
 import java.util.List;
-import java.util.UUID;
 import java.util.function.Function;
 
+import jakarta.inject.Inject;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.ConverterLocator;
+import org.apache.wicket.IConverterLocator;
+import org.apache.wicket.IPageFactory;
+import org.apache.wicket.Page;
+import org.apache.wicket.RuntimeConfigurationType;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
+import org.apache.wicket.core.request.mapper.MountedMapper;
+import org.apache.wicket.markup.head.ResourceAggregator;
+import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.cycle.PageRequestHandlerTracker;
+import org.apache.wicket.request.resource.CssResourceReference;
+import org.apache.wicket.settings.RequestCycleSettings;
+import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
 import org.apache.causeway.applib.services.inject.ServiceInjector;
 import org.apache.causeway.applib.services.metrics.MetricsService;
 import org.apache.causeway.commons.internal.concurrent._ConcurrentContext;
@@ -50,30 +73,7 @@
 import org.apache.causeway.viewer.wicket.viewer.integration.TelemetryStartHandler;
 import org.apache.causeway.viewer.wicket.viewer.integration.TelemetryStopHandler;
 import org.apache.causeway.viewer.wicket.viewer.integration.WebRequestCycleForCauseway;
-import org.apache.wicket.Application;
-import org.apache.wicket.ConverterLocator;
-import org.apache.wicket.IConverterLocator;
-import org.apache.wicket.IPageFactory;
-import org.apache.wicket.Page;
-import org.apache.wicket.RuntimeConfigurationType;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
-import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
-import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
-import org.apache.wicket.core.request.mapper.MountedMapper;
-import org.apache.wicket.markup.head.ResourceAggregator;
-import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.cycle.PageRequestHandlerTracker;
-import org.apache.wicket.request.resource.CssResourceReference;
-import org.apache.wicket.settings.RequestCycleSettings;
-import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
-import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Component;
-import org.springframework.web.context.support.WebApplicationContextUtils;
 
-import jakarta.inject.Inject;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -252,35 +252,12 @@ protected IPageFactory newPageFactory() {
     protected void configureSecurity(final CausewayConfiguration configuration) {
         // since Wicket 9, CSP is enabled by default [https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP]
         getCspSettings().blocking().disabled();
-        getSecuritySettings().setAuthenticationStrategy(newAuthenticationStrategy(configuration));
 
         // TODO CAUSEWAY-987 Either make the API better (no direct access to the map) or use DB records
         final int maxEntries = 1000;
         setMetaData(AccountConfirmationMap.KEY, new AccountConfirmationMap(maxEntries, Duration.ofDays(1)));
     }
 
-    /**
-     * protected visibility to allow ad-hoc overriding of some other authentication strategy.
-     */
-    protected IAuthenticationStrategy newAuthenticationStrategy(final CausewayConfiguration configuration) {
-        var rememberMe = configuration.viewer().wicket().rememberMe();
-        var cookieKey = rememberMe.cookieKey();
-        var encryptionKey = rememberMe.encryptionKey().orElse(defaultEncryptionKey());
-        return new DefaultAuthenticationStrategy(cookieKey, _CryptFactory.sunJceCrypt(encryptionKey));
-    }
-
-    /**
-     * As called by {@link #newAuthenticationStrategy(CausewayConfiguration)}.
-     * If an encryption key for the 'rememberMe' cookie hasn't been configured,
-     * then use a different encryption key for the 'rememberMe'
-     * cookie each time the app is restarted.
-     */
-    protected String defaultEncryptionKey() {
-        return systemEnvironment.isPrototyping()
-                ? _CryptFactory.FIXED_SALT_FOR_PROTOTYPING
-                : UUID.randomUUID().toString();
-    }
-
     // //////////////////////////////////////
 
     protected static final Function<ComponentFactory, Iterable<CssResourceReference>> getCssResourceReferences =
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/_CryptFactory.java b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/_CryptFactory.java
deleted file mode 100644
index 05cb2b76dae..00000000000
--- a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/_CryptFactory.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *  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.causeway.viewer.wicket.viewer.wicketapp;
-
-import java.security.SecureRandom;
-import java.security.spec.KeySpec;
-import java.util.Random;
-
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.wicket.core.random.DefaultSecureRandomSupplier;
-import org.apache.wicket.core.random.ISecureRandomSupplier;
-import org.apache.wicket.core.util.crypt.AESCrypt;
-import org.apache.wicket.util.crypt.ICrypt;
-import org.apache.wicket.util.crypt.NoCrypt;
-import org.apache.wicket.util.crypt.SunJceCrypt;
-
-import org.apache.causeway.commons.internal.os._OsUtil;
-
-import lombok.SneakyThrows;
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-class _CryptFactory {
-
-    static final String FIXED_SALT_FOR_PROTOTYPING = "PrototypingEncryptionKey";
-
-    ICrypt sunJceCrypt(final String encryptionKey) {
-        final byte[] salt = getSalt(8, encryptionKey);
-        var crypt = new SunJceCrypt(salt, 1000);
-        crypt.setKey(encryptionKey);
-        return crypt;
-    }
-
-    @SneakyThrows
-    ICrypt aesCrypt(final String encryptionKey) {
-
-        final byte[] salt = getSalt(8, encryptionKey);
-
-        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
-        KeySpec spec = new PBEKeySpec(encryptionKey.toCharArray(), salt, 65536, 256);
-        SecretKey tmp = factory.generateSecret(spec);
-        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
-
-        ISecureRandomSupplier rGen = new DefaultSecureRandomSupplier();
-
-        return new AESCrypt(secret, rGen);
-    }
-
-    ICrypt noCrypt(final String encryptionKey) {
-        return new NoCrypt();
-    }
-
-    //XXX what about BCryptPasswordEncoder (Spring);
-
-    // -- HELPER
-
-    /**
-     * @param size
-     *      must be 8 bytes - for anything else PBES1Core throws
-     *      InvalidAlgorithmParameterException: Salt must be 8 bytes long
-     */
-    private byte[] getSalt(final int size, final String encryptionKey) {
-        final byte[] salt = FIXED_SALT_FOR_PROTOTYPING.equals(encryptionKey)
-                ? machineFixedSalt(size)
-                : secureSalt(size);
-        return salt;
-    }
-
-    /**
-     * Cloned from {@link SunJceCrypt#randomSalt()},
-     * but using {@link SecureRandom} instead of {@link Random}.
-     */
-    private byte[] secureSalt(final int size) {
-        var salt = new byte[size];
-        new SecureRandom().nextBytes(salt);
-        return salt;
-    }
-
-    private byte[] machineFixedSalt(final int size) {
-        var machineFixedSeed = _OsUtil.machineId();
-        if(machineFixedSeed.isEmpty()){
-            return secureSalt(size);
-        }
-        var salt = new byte[size];
-        /*sonar-ignore-on*/
-        new Random(machineFixedSeed.getAsLong()).nextBytes(salt); // not required to be secure
-        /*sonar-ignore-off*/
-        return salt;
-    }
-
-}
diff --git a/viewers/wicket/viewer/src/test/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CryptFactoryTest.java b/viewers/wicket/viewer/src/test/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CryptFactoryTest.java
deleted file mode 100644
index 3a292b85c9d..00000000000
--- a/viewers/wicket/viewer/src/test/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/CryptFactoryTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *  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.causeway.viewer.wicket.viewer.wicketapp;
-
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-
-import org.apache.wicket.ThreadContext;
-import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
-import org.apache.wicket.mock.MockWebResponse;
-import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
-import org.apache.wicket.request.IExceptionMapper;
-import org.apache.wicket.request.IRequestMapper;
-import org.apache.wicket.request.Url;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.apache.wicket.request.cycle.RequestCycleContext;
-import org.apache.wicket.util.crypt.ICrypt;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.mock;
-
-import org.apache.causeway.core.internaltestsupport.annotations.DisabledIfRunningWithSurefire;
-
-/**
- * Requires resource {@code jakarta/servlet/http/LocalStrings.properties} for Cookie testing.
- */
-class CryptFactoryTest {
-
-    private ServletWebRequest servletWebRequest;
-    private MockWebResponse mockWebResponse;
-    private HttpServletRequest mockHttpServletRequest;
-
-    @BeforeEach
-    void setUp() throws Exception {
-
-        // quite a bit of ceremony to allow Cookie testing ...
-
-        mockHttpServletRequest = new org.springframework.mock.web.MockHttpServletRequest() {
-            @Override
-            public Cookie[] getCookies() {
-                return mockWebResponse.getCookies().toArray(new Cookie[] {});
-            }
-        };
-
-        servletWebRequest = new ServletWebRequest(mockHttpServletRequest, "", Url.parse("/"));
-        mockWebResponse = new MockWebResponse();
-
-        ThreadContext.setRequestCycle(new RequestCycle(new RequestCycleContext(
-                servletWebRequest,
-                mockWebResponse,
-                mock(IRequestMapper.class),
-                mock(IExceptionMapper.class))));
-
-    }
-
-    @AfterEach
-    void cleanUp() throws Exception {
-        ThreadContext.setRequestCycle(null);
-    }
-
-    @DisabledIfRunningWithSurefire
-    @ParameterizedTest(name = "{index} {0}")
-    @MethodSource("provideCryptoCandidates")
-    void authenticationStrategyRoundtrip_whenProduction(
-            final String displayName,
-            final Function<String, ICrypt> cryptFactory) {
-
-        var encryptionKey = "any other than FIXED_SALT_FOR_PROTOTYPING";
-
-        var strategy =
-                new DefaultAuthenticationStrategy("cookieKey", cryptFactory.apply(encryptionKey));
-        strategy.save("hello", "world", "appendix");
-
-        var data = strategy.load();
-
-        assertNotNull(data);
-        assertEquals(2, data.length);
-        assertEquals("hello", data[0]);
-        assertEquals("world", data[1]);
-
-        // simulated application restart
-
-        var strategy2 =
-                new DefaultAuthenticationStrategy("cookieKey", cryptFactory.apply(encryptionKey));
-        var data2 = strategy2.load();
-
-        //XXX occasionally fails with surefire
-        assertNull(data2);
-    }
-
-    @ParameterizedTest(name = "{index} {0}")
-    @MethodSource("provideCryptoCandidates")
-    void authenticationStrategyRoundtrip_whenPrototyping(
-            final String displayName,
-            final Function<String, ICrypt> cryptFactory) {
-
-        var encryptionKey = _CryptFactory.FIXED_SALT_FOR_PROTOTYPING;
-
-        var strategy1 =
-                new DefaultAuthenticationStrategy("cookieKey", cryptFactory.apply(encryptionKey));
-        strategy1.save("hello", "world", "appendix");
-
-        // simulated application restart
-
-        var strategy2 =
-                new DefaultAuthenticationStrategy("cookieKey", cryptFactory.apply(encryptionKey));
-        var data = strategy2.load();
-
-        assertNotNull(data);
-        assertEquals(2, data.length);
-        assertEquals("hello", data[0]);
-        assertEquals("world", data[1]);
-    }
-
-    // -- HELPER
-
-    private static Stream<Arguments> provideCryptoCandidates() {
-        return Stream.of(
-                scenario(
-                  "sunJceCrypt",
-                  _CryptFactory::sunJceCrypt),
-                scenario(
-                  "aesCrypt",
-                  _CryptFactory::aesCrypt)
-        );
-    }
-
-    private static Arguments scenario(
-            final String displayName,
-            final Function<String, ICrypt> cryptFactory) {
-        return Arguments.of(
-                displayName, cryptFactory);
-    }
-
-}