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

papegaaij pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/master by this push:
     new a68214425a WICKET-7193 Remove the authentication strategy and the 
remember-me panel
a68214425a is described below

commit a68214425a95a62df44c7b971a1226a173971ba0
Author: Emond Papegaaij <[email protected]>
AuthorDate: Fri Aug 21 13:37:36 2026 +0200

    WICKET-7193 Remove the authentication strategy and the remember-me panel
    
    IAuthenticationStrategy existed to persist sign-in credentials so that a 
later
    visit signed the user in automatically. Its contract was credential-shaped 
and
    could not be anything else: load() handed its result straight to
    AuthenticatedWebSession.signIn(String, String), so what was stored on the 
client
    was the password, replayed on every visit for as long as the cookie lived.
    
    DefaultAuthenticationStrategy, the only real implementation, joined the 
username
    and the password with "-sep-" and wrote them to a cookie named LoggedIn 
with a
    thirty day lifetime and no Secure attribute. AuthenticatedWebSession already
    documents that a cookie based login "may not rely on putting username and
    password into the cookie but something else that safely identifies the 
user", and
    the contract could not express that: load() returned credentials for
    authenticate(String, String) to check, so a token could only be carried by 
making
    the application accept that token as a password. That is the design rather 
than
    the implementation, so there is no replacement. An application that needs a
    persistent login has to implement one, with a random, revocable, per-device 
token.
    
    Removed: the interface, DefaultAuthenticationStrategy and
    NoOpAuthenticationStrategy -- both packages go with them, along with their 
JPMS
    and OSGi exports -- and SecuritySettings#getAuthenticationStrategy() and
    #setAuthenticationStrategy(). WebSession's invalidate() override existed 
only to
    call remove() on the strategy, since Session.invalidate() just sets a 
metadata
    flag, so it goes too. Nothing in Wicket 11 clears a LoggedIn cookie left 
behind by
    a Wicket 10 deployment; those expire on their own within thirty days.
    
    The remember-me support went with it, so SignInPanel and SignInPage in
    wicket-auth-roles are replaced by UsernamePasswordPanel and 
UsernamePasswordPage.
    The new types keep everything else, including the package, the member 
names, the
    "signInForm" component id, the signInFailed resource key and all nine
    localizations, so migrating is a change of type name; getRememberMe(),
    setRememberMe(), onSignInRemembered() and the two-argument SignInPanel
    constructor have no equivalent. UsernamePasswordPage additionally passes its
    PageParameters to super, which SignInPage never did. SignInPanelTest becomes
    UsernamePasswordPanelTest and gains two checks: that the panel renders in 
each of
    its nine localizations, and that a successful sign in leaves no cookie 
behind.
    
    wicket.yml records the removal and rewrites both types. The user guide no 
longer
    recommends SignInPanel for login forms, and the three places that named the
    "remember me" cookie among the things Wicket encrypts no longer do. The 
comment in
    WicketExampleApplication warning that NoCrypt leaves passwords in cookies 
was
    already stale -- since the crypt unification the strategy did not go through
    getCryptFactory() -- and now says what NoCrypt actually affects.
    
    All of the removed API is deprecated in 8.19.0, 9.24.0 and 10.11.0.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 SECURITY.md                                        |   4 +-
 .../{SignInPage.html => UsernamePasswordPage.html} |   0
 .../{SignInPage.java => UsernamePasswordPage.java} |  15 +-
 ...InPage_de.html => UsernamePasswordPage_de.html} |   0
 ...InPage_fr.html => UsernamePasswordPage_fr.html} |   0
 ...InPage_hu.html => UsernamePasswordPage_hu.html} |   0
 ...InPage_pl.html => UsernamePasswordPage_pl.html} |   0
 ...InPage_ru.html => UsernamePasswordPage_ru.html} |   0
 .../authentication/panel/SignInPanel.java          | 322 ---------------------
 ...SignInPanel.html => UsernamePasswordPanel.html} |   1 -
 .../panel/UsernamePasswordPanel.java               | 193 ++++++++++++
 ...Panel_de.html => UsernamePasswordPanel_de.html} |   1 -
 ...perties => UsernamePasswordPanel_de.properties} |   0
 ...Panel_fr.html => UsernamePasswordPanel_fr.html} |   1 -
 ...xml => UsernamePasswordPanel_fr.properties.xml} |   0
 ...Panel_hu.html => UsernamePasswordPanel_hu.html} |   1 -
 ...perties => UsernamePasswordPanel_hu.properties} |   0
 ...Panel_ja.html => UsernamePasswordPanel_ja.html} |   1 -
 ...Panel_ko.html => UsernamePasswordPanel_ko.html} |   1 -
 ...Panel_nl.html => UsernamePasswordPanel_nl.html} |   1 -
 ...perties => UsernamePasswordPanel_nl.properties} |   0
 ...Panel_pl.html => UsernamePasswordPanel_pl.html} |   1 -
 ...perties => UsernamePasswordPanel_pl.properties} |   0
 ...Panel_ru.html => UsernamePasswordPanel_ru.html} |   1 -
 ...perties => UsernamePasswordPanel_ru.properties} |   0
 ...zh_CN.html => UsernamePasswordPanel_zh_CN.html} |   1 -
 ...nelTest.java => UsernamePasswordPanelTest.java} |  76 ++++-
 wicket-core/pom.xml                                |   2 -
 wicket-core/src/main/java/module-info.java         |   2 -
 .../authentication/IAuthenticationStrategy.java    |  59 ----
 .../strategy/DefaultAuthenticationStrategy.java    | 172 -----------
 .../strategy/NoOpAuthenticationStrategy.java       |  43 ---
 .../apache/wicket/protocol/http/WebSession.java    |  17 --
 .../apache/wicket/settings/SecuritySettings.java   |  44 ---
 .../wicket/examples/WicketExampleApplication.java  |   6 +-
 .../wicket/examples/authentication1/SignIn.java    |   3 +-
 .../wicket/examples/authentication2/SignIn2.java   |   8 +-
 .../examples/authentication3/MySignInPage.java     |   9 +-
 .../org/apache/wicket/examples/library/SignIn.java |   4 +-
 .../wicket/examples/signin2/Signin2Test.java       |  32 --
 .../src/main/resources/META-INF/rewrite/wicket.yml |  24 ++
 .../src/main/asciidoc/internals/pagestoring.adoc   |   2 +-
 .../main/asciidoc/modelsforms/modelsforms_4.adoc   |   1 -
 .../src/main/asciidoc/security/security_4.adoc     |   4 +-
 44 files changed, 314 insertions(+), 738 deletions(-)

diff --git a/SECURITY.md b/SECURITY.md
index 6a074fa4ec..eb46390476 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -298,8 +298,8 @@ confirm a guessed URL by encrypting it themselves. With the 
default
 single user; with an application-wide key it is not. Encrypted URLs are
 therefore an obfuscation and a per-session CSRF token, never a secret in their
 own right — which is the same reason they are not an authorization mechanism.
-Everything Wicket encrypts elsewhere (the page store, the "remember me" cookie)
-uses the randomized path and does not have this property.
+Everything Wicket encrypts elsewhere, such as the page store, uses the 
randomized
+path and does not have this property.
 
 ## Reporting Something That Is Not a Vulnerability
 
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage.java
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage.java
similarity index 78%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage.java
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage.java
index 44bf6a708e..e12801299f 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage.java
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage.java
@@ -16,24 +16,25 @@
  */
 package org.apache.wicket.authroles.authentication.pages;
 
-import org.apache.wicket.authroles.authentication.panel.SignInPanel;
+import org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 
 /**
- * A base class which provide standard functionality for sign in.
+ * A base class which provide standard functionality for sign in, by hosting a
+ * {@link UsernamePasswordPanel}.
  * 
  * @author Jonathan Locke
  */
-public class SignInPage extends WebPage
+public class UsernamePasswordPage extends WebPage
 {
        private static final long serialVersionUID = 1L;
 
        /**
         * Construct
         */
-       public SignInPage()
+       public UsernamePasswordPage()
        {
                this(null);
        }
@@ -44,8 +45,10 @@ public class SignInPage extends WebPage
         * @param parameters
         *            The page parameters
         */
-       public SignInPage(final PageParameters parameters)
+       public UsernamePasswordPage(final PageParameters parameters)
        {
-               add(new SignInPanel("signInPanel"));
+               super(parameters);
+
+               add(new UsernamePasswordPanel("signInPanel"));
        }
 }
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_de.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_de.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_de.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_de.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_fr.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_fr.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_fr.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_fr.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_hu.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_hu.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_hu.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_hu.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_pl.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_pl.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_pl.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_pl.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_ru.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_ru.html
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/SignInPage_ru.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/pages/UsernamePasswordPage_ru.html
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.java
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.java
deleted file mode 100644
index 8e106309c3..0000000000
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.java
+++ /dev/null
@@ -1,322 +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.wicket.authroles.authentication.panel;
-
-import org.apache.wicket.RestartResponseException;
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
-import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.form.CheckBox;
-import org.apache.wicket.markup.html.form.PasswordTextField;
-import org.apache.wicket.markup.html.form.StatelessForm;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.CompoundPropertyModel;
-
-/**
- * Reusable user sign in panel with username and password as well as support 
for persistence of the
- * both. When the SignInPanel's form is submitted, the method signIn(String, 
String) is called,
- * passing the username and password submitted. The signIn() method should 
authenticate the user's
- * session.
- * 
- * @see IAuthenticationStrategy
- * @see org.apache.wicket.settings.SecuritySettings#getAuthenticationStrategy()
- * @see DefaultAuthenticationStrategy
- *
- * @author Jonathan Locke
- * @author Juergen Donnerstag
- * @author Eelco Hillenius
- */
-public class SignInPanel extends Panel
-{
-       private static final long serialVersionUID = 1L;
-
-       private static final String SIGN_IN_FORM = "signInForm";
-
-       /** 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) */
-       private boolean rememberMe = true;
-
-       /** password. */
-       private String password;
-
-       /** user name. */
-       private String username;
-
-       /**
-        * @see org.apache.wicket.Component#Component(String)
-        */
-       public SignInPanel(final String id)
-       {
-               this(id, true);
-       }
-
-       /**
-        * @param id
-        *            See Component constructor
-        * @param includeRememberMe
-        *            True if form should include a remember-me checkbox
-        * @see org.apache.wicket.Component#Component(String)
-        */
-       public SignInPanel(final String id, final boolean includeRememberMe)
-       {
-               super(id);
-
-               this.includeRememberMe = includeRememberMe;
-
-               // Create feedback panel and add to page
-               add(new FeedbackPanel("feedback"));
-
-               // Add sign-in form to page, passing feedback panel as
-               // validation error handler
-               add(new SignInForm(SIGN_IN_FORM));
-       }
-
-       /**
-        * 
-        * @return signin form
-        */
-       protected SignInForm getForm()
-       {
-               return (SignInForm)get(SIGN_IN_FORM);
-       }
-
-       /**
-        * Try to sign-in with remembered credentials.
-        * 
-        * @see #setRememberMe(boolean)
-        */
-       @Override
-       protected void onConfigure()
-       {
-               // logged in already?
-               if (isSignedIn() == false)
-               {
-                       IAuthenticationStrategy authenticationStrategy = 
getApplication().getSecuritySettings()
-                               .getAuthenticationStrategy();
-                       // get username and password from persistence store
-                       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];
-
-                                       onSignInRemembered();
-                               }
-                               else
-                               {
-                                       // the loaded credentials are wrong. 
erase them.
-                                       authenticationStrategy.remove();
-                               }
-                       }
-               }
-
-               super.onConfigure();
-       }
-
-       /**
-        * Convenience method to access the password.
-        * 
-        * @return The password
-        */
-       public String getPassword()
-       {
-               return password;
-       }
-
-       /**
-        * Set the password
-        * 
-        * @param password
-        */
-       public void setPassword(final String password)
-       {
-               this.password = password;
-       }
-
-       /**
-        * Convenience method to access the username.
-        * 
-        * @return The user name
-        */
-       public String getUsername()
-       {
-               return username;
-       }
-
-       /**
-        * Set the username
-        * 
-        * @param username
-        */
-       public void setUsername(final String username)
-       {
-               this.username = username;
-       }
-
-       /**
-        * Get model object of the rememberMe checkbox
-        * 
-        * @return True if user should be remembered in the future
-        */
-       public boolean getRememberMe()
-       {
-               return rememberMe;
-       }
-
-       /**
-        * @param rememberMe
-        *            If true, rememberMe will be enabled (username and 
password will be persisted
-        *            somewhere)
-        */
-       public void setRememberMe(final boolean rememberMe)
-       {
-               this.rememberMe = rememberMe;
-       }
-
-       /**
-        * Sign in user if possible.
-        * 
-        * @param username
-        *            The username
-        * @param password
-        *            The password
-        * @return True if signin was successful
-        */
-       private boolean signIn(String username, String password)
-       {
-               return AuthenticatedWebSession.get().signIn(username, password);
-       }
-
-       /**
-        * @return true, if signed in
-        */
-       private boolean isSignedIn()
-       {
-               return AuthenticatedWebSession.get().isSignedIn();
-       }
-
-       /**
-        * Called when sign in failed
-        */
-       protected void onSignInFailed()
-       {
-               // Try the component based localizer first. If not found try the
-               // application localizer. Else use the default
-               error(getLocalizer().getString("signInFailed", this, "Sign in 
failed"));
-       }
-
-       /**
-        * Called when sign in was successful
-        */
-       protected void onSignInSucceeded()
-       {
-               // 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()
-       {
-               // logon successful. Continue to the original destination
-               continueToOriginalDestination();
-
-               // Ups, no original destination. Go to the home page
-               throw new 
RestartResponseException(getApplication().getHomePage());
-       }
-
-       /**
-        * Sign in form.
-        */
-       public final class SignInForm extends StatelessForm<SignInPanel>
-       {
-               private static final long serialVersionUID = 1L;
-
-               /**
-                * Constructor.
-                * 
-                * @param id
-                *            id of the form component
-                */
-               public SignInForm(final String id)
-               {
-                       super(id);
-
-                       setModel(new CompoundPropertyModel<>(SignInPanel.this));
-
-                       // Attach textfields for username and password
-                       add(new TextField<>("username").setRequired(true));
-                       add(new PasswordTextField("password"));
-
-                       // container for remember me checkbox
-                       WebMarkupContainer rememberMeContainer = new 
WebMarkupContainer("rememberMeContainer");
-                       add(rememberMeContainer);
-
-                       // Add rememberMe checkbox
-                       rememberMeContainer.add(new CheckBox("rememberMe"));
-
-                       // Show remember me checkbox?
-                       rememberMeContainer.setVisible(includeRememberMe);
-               }
-
-               @Override
-               public void onSubmit()
-               {
-                       IAuthenticationStrategy strategy = 
getApplication().getSecuritySettings()
-                               .getAuthenticationStrategy();
-
-                       if (signIn(getUsername(), getPassword()))
-                       {
-                               if (rememberMe == true)
-                               {
-                                       strategy.save(username, password);
-                               }
-                               else
-                               {
-                                       strategy.remove();
-                               }
-
-                               onSignInSucceeded();
-                       }
-                       else
-                       {
-                               onSignInFailed();
-                               strategy.remove();
-                       }
-               }
-       }
-}
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.html
index 5f562f543c..e65528a111 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Password:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Remember Me </dd>
                        <dd>
                                <input type="submit" name="submit" value="Sign 
In"/>
                                <input type="reset" value="Reset"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.java
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.java
new file mode 100644
index 0000000000..a17e898e13
--- /dev/null
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel.java
@@ -0,0 +1,193 @@
+/*
+ * 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.wicket.authroles.authentication.panel;
+
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
+import org.apache.wicket.markup.html.form.PasswordTextField;
+import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.CompoundPropertyModel;
+
+/**
+ * Reusable sign in panel with a username and a password field. When the 
panel's form is submitted,
+ * the submitted values are passed to {@link 
AuthenticatedWebSession#signIn(String, String)}, which
+ * authenticates the user's session.
+ * <p>
+ * The credentials live no longer than the session: nothing is written to the 
client, so a user signs
+ * in again once the session has ended. Wicket offers no supported way to 
persist credentials on the
+ * client and get an automatic sign in on a later visit &mdash; anything 
stored there authenticates
+ * the user by itself, and the framework cannot make that safe. An application 
that needs a
+ * persistent login has to implement one, and should do so with a random, 
revocable, per-device token
+ * rather than with the password; {@link 
AuthenticatedWebSession#signIn(boolean)} exists so that such
+ * a token can sign a session in without being passed to
+ * {@link AuthenticatedWebSession#authenticate(String, String)}.
+ * 
+ * @author Jonathan Locke
+ * @author Juergen Donnerstag
+ * @author Eelco Hillenius
+ */
+public class UsernamePasswordPanel extends Panel
+{
+       private static final long serialVersionUID = 1L;
+
+       private static final String SIGN_IN_FORM = "signInForm";
+
+       /** password. */
+       private String password;
+
+       /** user name. */
+       private String username;
+
+       /**
+        * @see org.apache.wicket.Component#Component(String)
+        */
+       public UsernamePasswordPanel(final String id)
+       {
+               super(id);
+
+               // Create feedback panel and add to page
+               add(new FeedbackPanel("feedback"));
+
+               // Add sign-in form to page, passing feedback panel as
+               // validation error handler
+               add(new SignInForm(SIGN_IN_FORM));
+       }
+
+       /**
+        * 
+        * @return signin form
+        */
+       protected SignInForm getForm()
+       {
+               return (SignInForm)get(SIGN_IN_FORM);
+       }
+
+       /**
+        * Convenience method to access the password.
+        * 
+        * @return The password
+        */
+       public String getPassword()
+       {
+               return password;
+       }
+
+       /**
+        * Set the password
+        * 
+        * @param password
+        */
+       public void setPassword(final String password)
+       {
+               this.password = password;
+       }
+
+       /**
+        * Convenience method to access the username.
+        * 
+        * @return The user name
+        */
+       public String getUsername()
+       {
+               return username;
+       }
+
+       /**
+        * Set the username
+        * 
+        * @param username
+        */
+       public void setUsername(final String username)
+       {
+               this.username = username;
+       }
+
+       /**
+        * Sign in user if possible.
+        * 
+        * @param username
+        *            The username
+        * @param password
+        *            The password
+        * @return True if signin was successful
+        */
+       private boolean signIn(String username, String password)
+       {
+               return AuthenticatedWebSession.get().signIn(username, password);
+       }
+
+       /**
+        * Called when sign in failed
+        */
+       protected void onSignInFailed()
+       {
+               // Try the component based localizer first. If not found try the
+               // application localizer. Else use the default
+               error(getLocalizer().getString("signInFailed", this, "Sign in 
failed"));
+       }
+
+       /**
+        * Called when sign in was successful
+        */
+       protected void onSignInSucceeded()
+       {
+               // 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());
+       }
+
+       /**
+        * Sign in form.
+        */
+       public final class SignInForm extends 
StatelessForm<UsernamePasswordPanel>
+       {
+               private static final long serialVersionUID = 1L;
+
+               /**
+                * Constructor.
+                * 
+                * @param id
+                *            id of the form component
+                */
+               public SignInForm(final String id)
+               {
+                       super(id);
+
+                       setModel(new 
CompoundPropertyModel<>(UsernamePasswordPanel.this));
+
+                       // Attach textfields for username and password
+                       add(new TextField<>("username").setRequired(true));
+                       add(new PasswordTextField("password"));
+               }
+
+               @Override
+               public void onSubmit()
+               {
+                       if (signIn(getUsername(), getPassword()))
+                       {
+                               onSignInSucceeded();
+                       }
+                       else
+                       {
+                               onSignInFailed();
+                       }
+               }
+       }
+}
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_de.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_de.html
similarity index 93%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_de.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_de.html
index 5405ca28db..4e677ad936 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_de.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_de.html
@@ -30,7 +30,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Passwort:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> erinnern </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="Anmelden"/>
                                <input type="reset" value="Reset"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_de.properties
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_de.properties
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_de.properties
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_de.properties
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_fr.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_fr.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_fr.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_fr.html
index d1842e970a..97b9cb0bcd 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_fr.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_fr.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Mot de passe:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Se rappeler de moi </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="S'identifier"/>
                                <input type="reset" value="Annuler"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_fr.properties.xml
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_fr.properties.xml
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_fr.properties.xml
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_fr.properties.xml
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_hu.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_hu.html
similarity index 91%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_hu.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_hu.html
index 088e1e3160..c7c2244553 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_hu.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_hu.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Jelszó:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Emlékezzen rám </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="Bejelentkezés"/>
                                <input type="reset" value="Alaphelyzet"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_hu.properties
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_hu.properties
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_hu.properties
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_hu.properties
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ja.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ja.html
similarity index 91%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ja.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ja.html
index 663aabf81a..037bf77751 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ja.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ja.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>パスワード:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> ユーザー名を記憶する </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="サインイン"/>
                                <input type="reset" value="リセット"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ko.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ko.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ko.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ko.html
index a7b3883fe0..b4e8729c7d 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ko.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ko.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>비밀번호:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> ID 저장 </dd>
                        <dd>
                                <input type="submit" name="submit" value="로그인"/>
                                <input type="reset" value="취소"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_nl.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_nl.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_nl.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_nl.html
index 23a5969984..c3fef8a2e3 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_nl.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_nl.html
@@ -30,7 +30,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Wachtwoord:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Onthouden </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="Aanmelden"/>
                                <input type="reset" value="Reset"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_nl.properties
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_nl.properties
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_nl.properties
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_nl.properties
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_pl.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_pl.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_pl.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_pl.html
index 570aec9fb5..5c54dc2139 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_pl.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_pl.html
@@ -30,7 +30,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Has&#x0142;o:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Pami&#x0119;taj mnie </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="Wchodz&#x0119;"/>
                                <input type="reset" value="Rezygnuj&#x0119;"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_pl.properties
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_pl.properties
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_pl.properties
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_pl.properties
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ru.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ru.html
similarity index 91%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ru.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ru.html
index 3e4a2cc980..abf835faa9 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ru.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ru.html
@@ -26,7 +26,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>Пароль:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> Запомнить меня </dd>
                        <dd>
                                <input type="submit" name="submit" 
value="Вход"/>
                                <input type="reset" value="Сброс"/>
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ru.properties
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ru.properties
similarity index 100%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_ru.properties
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_ru.properties
diff --git 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_zh_CN.html
 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_zh_CN.html
similarity index 92%
rename from 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_zh_CN.html
rename to 
wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_zh_CN.html
index 001c11b86a..75acb5f023 100644
--- 
a/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/SignInPanel_zh_CN.html
+++ 
b/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanel_zh_CN.html
@@ -30,7 +30,6 @@
                        <dd><input wicket:id="username" type="text" 
size="30"/></dd>
                        <dt>密码:</dt>
                        <dd><input wicket:id="password" type="password" 
size="30"/></dd>
-                       <dd wicket:id="rememberMeContainer"><input 
wicket:id="rememberMe" type="checkbox" /> 记住我 </dd>
                        <dd>
                                <input type="submit" name="submit" value="到"/>
                                <input type="reset" value="重新设置"/>
diff --git 
a/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/SignInPanelTest.java
 
b/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanelTest.java
similarity index 56%
rename from 
wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/SignInPanelTest.java
rename to 
wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanelTest.java
index e4208c5b7c..5512c236b4 100644
--- 
a/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/SignInPanelTest.java
+++ 
b/wicket-auth-roles/src/test/java/org/apache/wicket/authroles/authentication/panel/UsernamePasswordPanelTest.java
@@ -17,11 +17,14 @@
 package org.apache.wicket.authroles.authentication.panel;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.Locale;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import jakarta.servlet.http.Cookie;
+
 import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.Session;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.authroles.authorization.strategies.role.Roles;
@@ -30,14 +33,20 @@ import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.util.resource.IResourceStream;
 import org.apache.wicket.util.resource.StringResourceStream;
+import org.apache.wicket.util.tester.FormTester;
 import org.apache.wicket.util.tester.WicketTester;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 /**
- * Tests for {@link SignInPanel}
+ * Tests for {@link UsernamePasswordPanel}
  */
-public class SignInPanelTest
+public class UsernamePasswordPanelTest
 {
+       private static final String USERNAME = "user";
+
+       private static final String PASSWORD = "secret";
 
        /**
         * https://issues.apache.org/jira/browse/WICKET-3980
@@ -60,14 +69,67 @@ public class SignInPanelTest
                assertEquals(1, constructorsCalls.get());
        }
 
-       private static class TestPage extends WebPage implements 
IMarkupResourceStreamProvider
+       /**
+        * The panel ships localized markup; every variant has to resolve and 
render, which is what
+        * catches a missing component or a stray {@code wicket:id} in one of 
them.
+        * 
+        * @param languageTag
+        *            the locale to render in
+        */
+       @ParameterizedTest
+       @ValueSource(strings = { "de", "fr", "hu", "ja", "ko", "nl", "pl", 
"ru", "zh-CN" })
+       public void rendersInEveryLocale(String languageTag)
+       {
+               WicketTester tester = new WicketTester(new TestApplication());
+               
tester.getSession().setLocale(Locale.forLanguageTag(languageTag));
+
+               tester.startPage(new TestPage(new AtomicInteger(0)));
+
+               tester.assertRenderedPage(TestPage.class);
+               tester.assertComponent("signInPanel:signInForm:username",
+                       org.apache.wicket.markup.html.form.TextField.class);
+       }
+
+       /**
+        * This panel keeps nothing on the client: a successful sign in must 
leave no cookie behind, and
+        * in particular not the one the removed authentication strategy used.
+        */
+       @Test
+       public void signInPersistsNothingOnTheClient()
+       {
+               WicketTester tester = new WicketTester(new TestApplication());
+               tester.startPage(new TestPage(new AtomicInteger(0)));
+
+               FormTester form = 
tester.newFormTester("signInPanel:signInForm");
+               form.setValue("username", USERNAME);
+               form.setValue("password", PASSWORD);
+               form.submit();
+
+               assertTrue(AuthenticatedWebSession.get().isSignedIn(), "should 
be signed in");
+               
assertTrue(tester.getLastResponse().getCookies().stream().map(Cookie::getName)
+                       .noneMatch("LoggedIn"::equals), "no credentials may be 
persisted on the client");
+       }
+
+       /**
+        * The page hosting the panel. It doubles as the home page, so it needs 
a default constructor for
+        * the redirect after a successful sign in.
+        */
+       public static class TestPage extends WebPage implements 
IMarkupResourceStreamProvider
        {
+               /**
+                * Construct.
+                */
+               public TestPage()
+               {
+                       this(new AtomicInteger(0));
+               }
+
                private TestPage(AtomicInteger constructorCalls)
                {
                        super();
                        constructorCalls.incrementAndGet();
 
-                       add(new SignInPanel("signInPanel"));
+                       add(new UsernamePasswordPanel("signInPanel"));
                }
 
                @Override
@@ -80,7 +142,7 @@ public class SignInPanelTest
        }
 
        /**
-        * A {@link Session session} for the test
+        * A {@link org.apache.wicket.Session session} for the test
         */
        public static class TestSession extends AuthenticatedWebSession
        {
@@ -104,7 +166,7 @@ public class SignInPanelTest
                @Override
                public boolean authenticate(String username, String password)
                {
-                       return false;
+                       return USERNAME.equals(username) && 
PASSWORD.equals(password);
                }
        }
 
diff --git a/wicket-core/pom.xml b/wicket-core/pom.xml
index 01ef60a5ea..ed6a06cce7 100644
--- a/wicket-core/pom.xml
+++ b/wicket-core/pom.xml
@@ -46,8 +46,6 @@ org.apache.wicket.ajax.markup.html;-noimport:=true,
 org.apache.wicket.ajax.markup.html.form;-noimport:=true,
 org.apache.wicket.ajax.markup.html.navigation.paging;-noimport:=true,
 org.apache.wicket.application;-noimport:=true,
-org.apache.wicket.authentication;-noimport:=true,
-org.apache.wicket.authentication.strategy;-noimport:=true,
 org.apache.wicket.authorization;-noimport:=true,
 org.apache.wicket.authorization.strategies;-noimport:=true,
 org.apache.wicket.authorization.strategies.action;-noimport:=true,
diff --git a/wicket-core/src/main/java/module-info.java 
b/wicket-core/src/main/java/module-info.java
index 25561600ed..d54cfe8dc7 100644
--- a/wicket-core/src/main/java/module-info.java
+++ b/wicket-core/src/main/java/module-info.java
@@ -45,8 +45,6 @@ module org.apache.wicket.core {
     exports org.apache.wicket.ajax.markup.html.form;
     exports org.apache.wicket.ajax.markup.html.navigation.paging;
     exports org.apache.wicket.application;
-    exports org.apache.wicket.authentication;
-    exports org.apache.wicket.authentication.strategy;
     exports org.apache.wicket.authorization;
     exports org.apache.wicket.authorization.strategies;
     exports org.apache.wicket.authorization.strategies.action;
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/authentication/IAuthenticationStrategy.java
 
b/wicket-core/src/main/java/org/apache/wicket/authentication/IAuthenticationStrategy.java
deleted file mode 100644
index c75a25c69a..0000000000
--- 
a/wicket-core/src/main/java/org/apache/wicket/authentication/IAuthenticationStrategy.java
+++ /dev/null
@@ -1,59 +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.wicket.authentication;
-
-import org.apache.wicket.Application;
-
-/**
- * The interface of an authentication strategy which is accessible via
- * {@link Application#getSecuritySettings()}. Implementations determine how 
logon data (username and
- * password) are persisted (e.g. Cookie), retrieved and removed.
- * 
- * @author Juergen Donnerstag
- */
-public interface IAuthenticationStrategy
-{
-       /**
-        * If "rememberMe" is enabled, then load the saved credentials (e.g. 
username and password) from the persistence storage
-        * (e.g. Cookie) for automatic sign in. This is useful for applications 
which users typically
-        * have open the whole day but where the server invalidates the session 
after a timeout and you
-        * want to force the user to sign in again and again during the day.
-        * 
-        * @return The {@link #save(String, String...) saved} credentials
-        */
-       String[] load();
-
-       /**
-        * If "rememberMe" is enabled and login was successful, then store the 
given credentials in the
-        * persistence store (e.g. Cookie).
-        *
-        * <p>The implementation of this method should be symmetrical with the 
implementation of
-        * {@link #load()}.</p>
-        *
-        * @param credential
-        *          The credential to store. For example: a security token or 
username.
-        * @param extraCredentials
-        *          Optional extra credentials. For example: a password
-        */
-       void save(final String credential, final String... extraCredentials);
-
-       /**
-        * When the user logs out (session invalidation), then remove username 
and password from the
-        * persistence store
-        */
-       void remove();
-}
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/DefaultAuthenticationStrategy.java
 
b/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/DefaultAuthenticationStrategy.java
deleted file mode 100644
index 7aef039229..0000000000
--- 
a/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/DefaultAuthenticationStrategy.java
+++ /dev/null
@@ -1,172 +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.wicket.authentication.strategy;
-
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-import org.apache.wicket.core.util.crypt.ICrypt;
-import org.apache.wicket.util.cookies.CookieDefaults;
-import org.apache.wicket.util.cookies.CookieUtils;
-import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.string.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Wicket's default implementation of an authentication strategy. It'll 
concatenate username and
- * password, encrypt it and put it into one Cookie.
- * <p>
- * Note: To support automatic authentication across application restarts you 
have to use
- * the constructor {@link 
DefaultAuthenticationStrategy#DefaultAuthenticationStrategy(String, ICrypt)}.
- * 
- * @author Juergen Donnerstag
- */
-public class DefaultAuthenticationStrategy implements IAuthenticationStrategy
-{
-       private static final Logger logger = 
LoggerFactory.getLogger(DefaultAuthenticationStrategy.class);
-
-       /** The cookie name to store the username and password */
-       protected final String cookieKey;
-
-       /** The separator used to concatenate the username and password */
-       protected final String VALUE_SEPARATOR = "-sep-";
-
-       /** Cookie utils with default settings */
-       private CookieUtils cookieUtils;
-
-       /** Use to encrypt cookie values for username and password. */
-       private ICrypt crypt;
-
-       /**
-        * This is the recommended constructor to be used, which allows 
automatic authentication across
-        * application restarts.  
-        * 
-        * @param cookieKey
-        *            The name of the cookie
-        * @param crypt
-        *            the crypt
-        */
-       public DefaultAuthenticationStrategy(final String cookieKey, ICrypt 
crypt)
-       {
-               this.cookieKey = Args.notEmpty(cookieKey, "cookieKey");
-               this.crypt = Args.notNull(crypt, "crypt");
-       }
-
-       /**
-        * Make sure you always return a valid CookieUtils
-        * 
-        * @return CookieUtils
-        */
-       protected CookieUtils getCookieUtils()
-       {
-               if (cookieUtils == null)
-               {
-                       CookieDefaults settings = new CookieDefaults();
-                       settings.setHttpOnly(true);
-                       cookieUtils = new CookieUtils(settings);
-               }
-               return cookieUtils;
-       }
-
-       /**
-        * @return The crypt engine to be used
-        */
-       protected ICrypt getCrypt()
-       {
-               return crypt;
-       }
-
-       @Override
-       public String[] load()
-       {
-               String value = getCookieUtils().load(cookieKey);
-               if (Strings.isEmpty(value) == false)
-               {
-                       value = getCrypt().decryptUrlSafe(value);
-                       if (value == null)
-                       {
-                               logger.info(
-                                       "Could not decrypt login cookie: {}. 
The cookie will be deleted. A possible cause is that the encryption key changed 
(e.g. the application was restarted with a session-relative or per-boot key), 
so a cookie created earlier can no longer be decrypted",
-                                       cookieKey);
-                               getCookieUtils().remove(cookieKey);
-                       }
-                       return decode(value);
-               }
-
-               return null;
-       }
-
-       /**
-        * This method will decode decrypted cookie value based on application 
needs
-        *
-        * @param value decrypted cookie value
-        * @return decomposed values array, or null in case cookie value was 
empty.
-        */
-       protected String[] decode(String value) {
-               if (Strings.isEmpty(value) == false)
-               {
-                       String username = null;
-                       String password = null;
-
-                       String[] values = value.split(VALUE_SEPARATOR);
-                       if ((values.length > 0) && (Strings.isEmpty(values[0]) 
== false))
-                       {
-                               username = values[0];
-                       }
-                       if ((values.length > 1) && (Strings.isEmpty(values[1]) 
== false))
-                       {
-                               password = values[1];
-                       }
-
-                       return new String[] { username, password };
-               }
-               return null;
-       }
-
-       @Override
-       public void save(final String credential, final String... 
extraCredentials)
-       {
-               String encryptedValue = 
getCrypt().encryptUrlSafe(encode(credential, extraCredentials));
-
-               getCookieUtils().save(cookieKey, encryptedValue);
-       }
-
-       /**
-        * This method can be overridden to provide different encoding mechanism
-        *
-        * @param credential
-        * @param extraCredentials
-        * @return String representation of the parameters given
-        */
-       protected String encode(final String credential, final String... 
extraCredentials)
-       {
-               StringBuilder value = new StringBuilder(credential);
-               if (extraCredentials != null)
-               {
-                       for (String extraCredential : extraCredentials)
-                       {
-                               
value.append(VALUE_SEPARATOR).append(extraCredential);
-                       }
-               }
-               return value.toString();
-       }
-
-       @Override
-       public void remove()
-       {
-               getCookieUtils().remove(cookieKey);
-       }
-}
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/NoOpAuthenticationStrategy.java
 
b/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/NoOpAuthenticationStrategy.java
deleted file mode 100644
index 21460638cd..0000000000
--- 
a/wicket-core/src/main/java/org/apache/wicket/authentication/strategy/NoOpAuthenticationStrategy.java
+++ /dev/null
@@ -1,43 +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.wicket.authentication.strategy;
-
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-
-/**
- * A no-op implementation. No username or password will be persisted or 
retrieved.
- * 
- * @author Juergen Donnerstag
- */
-public class NoOpAuthenticationStrategy implements IAuthenticationStrategy
-{
-       @Override
-       public String[] load()
-       {
-               return null;
-       }
-
-       @Override
-       public void save(final String credential, final String... 
extraCredentials)
-       {
-       }
-
-       @Override
-       public void remove()
-       {
-       }
-}
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebSession.java 
b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebSession.java
index 3a303fbf86..cfdd708f40 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebSession.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebSession.java
@@ -52,23 +52,6 @@ public class WebSession extends Session
                super(request);
        }
 
-       /**
-        * Call signOut() and remove the logon data from whereever they have 
been persisted (e.g.
-        * Cookies)
-        * 
-        * @see org.apache.wicket.Session#invalidate()
-        */
-       @Override
-       public void invalidate()
-       {
-               if (isSessionInvalidated() == false)
-               {
-                       
getApplication().getSecuritySettings().getAuthenticationStrategy().remove();
-
-                       super.invalidate();
-               }
-       }
-
        /**
         * {@inheritDoc}
         * 
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java 
b/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
index cde0f5c8bf..429efbe151 100644
--- a/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
+++ b/wicket-core/src/main/java/org/apache/wicket/settings/SecuritySettings.java
@@ -18,8 +18,6 @@ package org.apache.wicket.settings;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.Component;
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
 import org.apache.wicket.authorization.IAuthorizationStrategy;
 import 
org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener;
 import org.apache.wicket.authorization.IUnauthorizedResourceRequestListener;
@@ -28,20 +26,15 @@ import 
org.apache.wicket.coep.CrossOriginEmbedderPolicyConfiguration;
 import org.apache.wicket.coep.CrossOriginEmbedderPolicyConfiguration.CoepMode;
 import org.apache.wicket.coop.CrossOriginOpenerPolicyConfiguration;
 import org.apache.wicket.coop.CrossOriginOpenerPolicyConfiguration.CoopMode;
-import java.security.SecureRandom;
 import java.util.Collection;
 import java.util.List;
 
-import javax.crypto.SecretKey;
-
 import org.apache.wicket.core.random.DefaultSecureRandomSupplier;
 import org.apache.wicket.core.random.ISecureRandomSupplier;
 import org.apache.wicket.core.util.crypt.AesGcmCryptScheme;
-import org.apache.wicket.core.util.crypt.ICrypt;
 import org.apache.wicket.core.util.crypt.ICryptFactory;
 import org.apache.wicket.core.util.crypt.ICryptScheme;
 import org.apache.wicket.core.util.crypt.KeyInSessionCryptFactory;
-import org.apache.wicket.core.util.crypt.SchemeCrypt;
 import org.apache.wicket.util.lang.Args;
 
 /**
@@ -61,9 +54,6 @@ public class SecuritySettings
        /** The authorization strategy. */
        private IAuthorizationStrategy authorizationStrategy = 
IAuthorizationStrategy.ALLOW_ALL;
 
-       /** The authentication strategy. */
-       private IAuthenticationStrategy authenticationStrategy;
-
        /** factory for creating crypt objects */
        private ICryptFactory cryptFactory;
 
@@ -345,40 +335,6 @@ public class SecuritySettings
                return this;
        }
 
-       /**
-        * Gets the authentication strategy.
-        *
-        * @return Returns the authentication strategy.
-        */
-       public IAuthenticationStrategy getAuthenticationStrategy()
-       {
-               if (authenticationStrategy == null)
-               {
-                       // a "remember me" cookie must be decryptable across 
sessions, so it uses an
-                       // application-wide key. The key is random per boot; 
supply a custom strategy with a
-                       // stable key to keep cookies valid across application 
restarts.
-                       SecureRandom random = getRandomSupplier().getRandom();
-                       SecretKey key = getCryptScheme().generateKey(random);
-                       ICrypt crypt = new SchemeCrypt(key, random, 
getCryptScheme(),
-                               getWhitelistedCryptSchemes());
-                       authenticationStrategy = new 
DefaultAuthenticationStrategy("LoggedIn", crypt);
-               }
-               return authenticationStrategy;
-       }
-
-       /**
-        * Sets the authentication strategy.
-        *
-        * @param strategy
-        *            new authentication strategy
-        * @return {@code this} object for chaining
-        */
-       public SecuritySettings setAuthenticationStrategy(final 
IAuthenticationStrategy strategy)
-       {
-               authenticationStrategy = strategy;
-               return this;
-       }
-
        public CrossOriginOpenerPolicyConfiguration 
getCrossOriginOpenerPolicyConfiguration()
        {
                return crossOriginOpenerPolicyConfiguration;
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java
index d80c622dbb..f38b9d9767 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java
@@ -47,9 +47,9 @@ public abstract class WicketExampleApplication extends 
WebApplication
        {
                super.init();
                
-               // WARNING: DO NOT do this on a real world application unless
-               // you really want your app's passwords all passed around and
-               // stored in unencrypted browser cookies (BAD IDEA!)!!!
+               // WARNING: DO NOT do this on a real world application. NoCrypt 
encrypts nothing, so
+               // everything that goes through the crypt factory -- the URLs 
CryptoMapper produces and
+               // the file upload tokens -- is readable and forgeable by 
anyone (BAD IDEA!)!!!
 
                // The NoCrypt class is being used here because not everyone
                // has the java security classes required by Crypt installed
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication1/SignIn.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication1/SignIn.java
index 9d8f207502..eae836b224 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication1/SignIn.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication1/SignIn.java
@@ -27,8 +27,7 @@ import org.apache.wicket.util.value.ValueMap;
 
 /**
  * Simple example of a sign in page. Even simpler, as shown in the 
authentication-2 example, is
- * using the SignInPanel from the auth-role package. Beside that this simple 
example does not
- * support "rememberMe".
+ * using the UsernamePasswordPanel from the auth-role package.
  * 
  * @author Jonathan Locke
  */
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication2/SignIn2.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication2/SignIn2.java
index ab8a17b286..87b6612cc1 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication2/SignIn2.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication2/SignIn2.java
@@ -16,14 +16,14 @@
  */
 package org.apache.wicket.examples.authentication2;
 
-import org.apache.wicket.authroles.authentication.panel.SignInPanel;
+import org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel;
 import org.apache.wicket.examples.WicketExamplePage;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 
 /**
- * Simple example of a sign in page. It is based on auth-role's SignInPanel 
which already provides
- * all what is necessary.
+ * Simple example of a sign in page. It is based on auth-role's 
UsernamePasswordPanel which
+ * already provides all what is necessary.
  * 
  * @author Jonathan Locke
  */
@@ -41,6 +41,6 @@ public final class SignIn2 extends WicketExamplePage
 
                // Take our standard Logon Panel from the auth-role module and 
add it to the Page. That is
                // all what is necessary.
-               add(new SignInPanel("signInPanel", false));
+               add(new UsernamePasswordPanel("signInPanel"));
        }
 }
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MySignInPage.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MySignInPage.java
index 3f9e126097..c031c71a86 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MySignInPage.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MySignInPage.java
@@ -16,7 +16,7 @@
  */
 package org.apache.wicket.examples.authentication3;
 
-import org.apache.wicket.authroles.authentication.panel.SignInPanel;
+import org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel;
 import org.apache.wicket.examples.WicketExamplePage;
 
 
@@ -32,9 +32,8 @@ public final class MySignInPage extends WicketExamplePage
         */
        public MySignInPage()
        {
-               // That is all you need to add a logon panel to your 
application with rememberMe
-               // functionality based on Cookies. Meaning username and 
password are persisted in a Cookie.
-               // Please see ISecuritySettings#getAuthenticationStrategy() for 
details.
-               add(new SignInPanel("signInPanel"));
+               // That is all you need to add a logon panel to your 
application. The panel signs the user
+               // in for the duration of the session and persists nothing on 
the client.
+               add(new UsernamePasswordPanel("signInPanel"));
        }
 }
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/library/SignIn.java 
b/wicket-examples/src/main/java/org/apache/wicket/examples/library/SignIn.java
index 7a3543186a..5c763a9e6c 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/library/SignIn.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/library/SignIn.java
@@ -16,7 +16,7 @@
  */
 package org.apache.wicket.examples.library;
 
-import org.apache.wicket.authroles.authentication.panel.SignInPanel;
+import org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel;
 import org.apache.wicket.examples.WicketExamplePage;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
@@ -45,6 +45,6 @@ public final class SignIn extends WicketExamplePage
        public SignIn(final PageParameters parameters)
        {
                super(parameters);
-               add(new SignInPanel("signInPanel", false));
+               add(new UsernamePasswordPanel("signInPanel"));
        }
 }
diff --git 
a/wicket-examples/src/test/java/org/apache/wicket/examples/signin2/Signin2Test.java
 
b/wicket-examples/src/test/java/org/apache/wicket/examples/signin2/Signin2Test.java
index 80718883d9..94d3157cde 100644
--- 
a/wicket-examples/src/test/java/org/apache/wicket/examples/signin2/Signin2Test.java
+++ 
b/wicket-examples/src/test/java/org/apache/wicket/examples/signin2/Signin2Test.java
@@ -16,12 +16,6 @@
  */
 package org.apache.wicket.examples.signin2;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.Collection;
-
-import jakarta.servlet.http.Cookie;
-
 import org.apache.wicket.examples.authentication2.Home;
 import org.apache.wicket.examples.authentication2.SignIn2;
 import org.apache.wicket.examples.authentication2.SignIn2Application;
@@ -51,35 +45,9 @@ public class Signin2Test
                        FormTester formTester = 
tester.newFormTester("signInPanel:signInForm");
                        formTester.setValue("username", "wicket");
                        formTester.setValue("password", "wicket");
-                       formTester.setValue("rememberMeContainer:rememberMe", 
"true");
                        formTester.submit();
                        tester.assertRenderedPage(Home.class);
 
-                       // a) With wicket submitting a form will result in a 
temporary redirect,
-                       // with the redirect setting the Cookie.
-                       // b) jWebUnits Cookie test methods are all using the 
http response
-                       // object only
-                       // c) Like a browser, jwebunit will automatically 
handle the redirect
-                       // request
-                       // Hence dumpCookie will not print an Cookie and 
assertCookiePresent
-                       // will
-                       // fail.
-                       // The only mean available is to indirectly test the 
cookies. Indirectly
-                       // because
-                       // the screen flow depends on the cookies.
-                       // this.dumpCookies(System.err);
-                       // 
this.assertCookiePresent("signInPanel.signInForm.username");
-                       // 
this.assertCookiePresent("signInPanel.signInForm.password");
-
-                       Collection<Cookie> cookies = 
tester.getLastResponse().getCookies();
-                       for (Cookie cookie : cookies)
-                       {
-                               if 
("signInPanel.signInForm.username".equals(cookie.getName()))
-                               {
-                                       assertEquals("wicket", 
cookie.getValue());
-                               }
-                       }
-
                        tester.startPage(SignOut.class);
                        tester.assertRenderedPage(SignOut.class);
 
diff --git a/wicket-migration/src/main/resources/META-INF/rewrite/wicket.yml 
b/wicket-migration/src/main/resources/META-INF/rewrite/wicket.yml
index 3c193e5dba..90b1b3a735 100644
--- a/wicket-migration/src/main/resources/META-INF/rewrite/wicket.yml
+++ b/wicket-migration/src/main/resources/META-INF/rewrite/wicket.yml
@@ -65,6 +65,22 @@ recipeList:
 # up in the page and how much of it was read. Applications composing pages 
with it should use
 # Panels, Borders and markup inheritance instead; there is no replacement for 
including remote
 # content. It is deprecated in 8.19.0, 9.24.0 and 10.11.0.
+#
+# org.apache.wicket.authentication.IAuthenticationStrategy, its two 
implementations and the
+# SecuritySettings#getAuthenticationStrategy()/#setAuthenticationStrategy() 
accessors were removed
+# with no replacement. The interface persisted sign-in credentials on the 
client so that a later
+# visit could replay them, which cannot be made safe: whatever it persists is 
what signs the user
+# in, so the stored value is the password itself. An application that needs a 
persistent login has
+# to implement one, with a random, revocable, per-device token rather than 
with the password.
+# With the interface gone, org.apache.wicket.protocol.http.WebSession no 
longer overrides
+# invalidate(), and nothing clears a "LoggedIn" cookie left over from a Wicket 
10 deployment --
+# those expire on their own within thirty days.
+#
+# The "remember me" support went with it, so SignInPanel and SignInPage in 
wicket-auth-roles are
+# replaced by UsernamePasswordPanel and UsernamePasswordPage, which are the 
same types without it.
+# The ChangeType entries below handle the common case; getRememberMe(), 
setRememberMe(),
+# onSignInRemembered() and the two-argument SignInPanel constructor have no 
equivalent and need
+# hand-editing. Both are deprecated in 8.19.0, 9.24.0 and 10.11.0.
 type: specs.openrewrite.org/v1beta/recipe
 name: org.apache.wicket.MigrateToWicket11
 displayName: Migrate to Wicket 11.x
@@ -87,6 +103,14 @@ recipeList:
       oldFullyQualifiedTypeName: org.apache.wicket.util.crypt.NoCryptFactory
       newFullyQualifiedTypeName: 
org.apache.wicket.core.util.crypt.NoCryptFactory
       ignoreDefinition: "True"
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.wicket.authroles.authentication.panel.SignInPanel
+      newFullyQualifiedTypeName: 
org.apache.wicket.authroles.authentication.panel.UsernamePasswordPanel
+      ignoreDefinition: "True"
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.wicket.authroles.authentication.pages.SignInPage
+      newFullyQualifiedTypeName: 
org.apache.wicket.authroles.authentication.pages.UsernamePasswordPage
+      ignoreDefinition: "True"
   - org.openrewrite.maven.UpgradeDependencyVersion:
       groupId: org.apache.wicket
       artifactId: "*"
diff --git a/wicket-user-guide/src/main/asciidoc/internals/pagestoring.adoc 
b/wicket-user-guide/src/main/asciidoc/internals/pagestoring.adoc
index 96005ff1dd..b78872285c 100644
--- a/wicket-user-guide/src/main/asciidoc/internals/pagestoring.adoc
+++ b/wicket-user-guide/src/main/asciidoc/internals/pagestoring.adoc
@@ -40,7 +40,7 @@ i.e. this is the serialized page instance (data) plus 
additional information nee
 
 * *CryptingPageStore:* page instances might contain sensible information, 
therefore it's important to have the chance to encrypt their content before 
persist them on disk. _CryptingPageStore_ encrypts _SerializedPage_'s with an 
authenticated cipher (by default JDK-native AES-256-GCM) before passing them to 
the underling _DiskPageStore_, using a random 256 bit key per session. Because 
the encryption is authenticated, tampering is detected on decryption (a 
modified page is treated as if it [...]
 +
-The cipher (the "scheme") is configured application-wide via 
_org.apache.wicket.settings.SecuritySettings.setCryptScheme_ and defaults to 
_org.apache.wicket.core.util.crypt.AesGcmCryptScheme_. An 
_AesGcmSivCryptScheme_ (AES-256-GCM-SIV, nonce-misuse resistant) is also 
available but requires Bouncy Castle on the classpath. Each ciphertext starts 
with a one-byte marker identifying its scheme; on decryption the marker must 
match one of the schemes accepted by _SecuritySettings.setWhiteliste [...]
+The cipher (the "scheme") is configured application-wide via 
_org.apache.wicket.settings.SecuritySettings.setCryptScheme_ and defaults to 
_org.apache.wicket.core.util.crypt.AesGcmCryptScheme_. An 
_AesGcmSivCryptScheme_ (AES-256-GCM-SIV, nonce-misuse resistant) is also 
available but requires Bouncy Castle on the classpath. Each ciphertext starts 
with a one-byte marker identifying its scheme; on decryption the marker must 
match one of the schemes accepted by _SecuritySettings.setWhiteliste [...]
 +
 Note that the key lives in the user's HTTP session, so the encryption protects 
the stored pages against parties who can read or write the underlying store - 
it does not protect them against someone who already controls the session. 
Wicket deserializes whatever it reads back from the store, so the store itself 
should still be treated as trusted, private storage.
 
diff --git a/wicket-user-guide/src/main/asciidoc/modelsforms/modelsforms_4.adoc 
b/wicket-user-guide/src/main/asciidoc/modelsforms/modelsforms_4.adoc
index b87e0fb3eb..10b7482797 100644
--- a/wicket-user-guide/src/main/asciidoc/modelsforms/modelsforms_4.adoc
+++ b/wicket-user-guide/src/main/asciidoc/modelsforms/modelsforms_4.adoc
@@ -42,7 +42,6 @@ The purpose of FormComponent is to store the corresponding 
user input into its m
 As first example of interaction between the form and its models, we will build 
a classic login form which asks for username and password (project LoginForm).
 
 WARNING: The topic of security will be discussed later in chapter 22. The 
following form is for example purposes only and is not suited for a real 
application.
-If you need to use a login form you should consider to use component 
_org.apache.wicket.authroles.authentication.panel.SignInPanel_ shipped with 
Wicket.
 
 This form needs two text fields, one of which must be a password field. We 
should also use a label to display the result of login process. For the sake of 
simplicity, the login logic is all inside onSubmit and is quite trivial.
 
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_4.adoc 
b/wicket-user-guide/src/main/asciidoc/security/security_4.adoc
index 2e616bdd42..b69d49aed2 100644
--- a/wicket-user-guide/src/main/asciidoc/security/security_4.adoc
+++ b/wicket-user-guide/src/main/asciidoc/security/security_4.adoc
@@ -23,9 +23,9 @@ public interface ICrypt
 }
 ----
 
-_ICrypt_ works on raw bytes and provides a URL-safe Base64 _String_ layer on 
top. The same interface is used everywhere Wicket encrypts data: encrypted URLs 
(_CryptoMapper_), the page store (see <<_page_storing,the chapter on page 
storing>>) and the "remember me" cookie. Decryption returns `null` on _any_ 
failure (unknown cipher, failed authentication, malformed input) instead of 
throwing, so undecryptable data is uniformly treated as absent.
+_ICrypt_ works on raw bytes and provides a URL-safe Base64 _String_ layer on 
top. The same interface is used everywhere Wicket encrypts data: encrypted URLs 
(_CryptoMapper_) and the page store (see <<_page_storing,the chapter on page 
storing>>). Decryption returns `null` on _any_ failure (unknown cipher, failed 
authentication, malformed input) instead of throwing, so undecryptable data is 
uniformly treated as absent.
 
-Encryption comes in two flavours. _encrypt_ is *randomized*: it draws a fresh 
nonce per call, so encrypting the same data twice gives two different results. 
This is what the page store and the "remember me" cookie use. 
_encryptDeterministic_ is *stable*: the same input always produces the same 
ciphertext for as long as the key lives. Both write the same format and are 
read back by the same _decrypt_.
+Encryption comes in two flavours. _encrypt_ is *randomized*: it draws a fresh 
nonce per call, so encrypting the same data twice gives two different results. 
This is what the page store uses. _encryptDeterministic_ is *stable*: the same 
input always produces the same ciphertext for as long as the key lives. Both 
write the same format and are read back by the same _decrypt_.
 
 _CryptoMapper_ uses the deterministic flavour, because two things depend on an 
encrypted URL being stable. A URL regenerated while a page renders must match 
the one the client requested, or Wicket's URL normalisation would redirect to 
the newly generated URL, which would again differ, and so on. And a resource 
URL (JavaScript, CSS, images) must be identical on every page view, or the 
browser cannot recognise the resource it already holds and re-downloads it 
every time, however long-lived [...]
 

Reply via email to