Added post-login forward capability (original patch posted to the sourceforge.net...
authorchris_schultz <chris_schultz>
Fri, 2 Nov 2007 16:31:24 +0000 (16:31 +0000)
committerchris_schultz <chris_schultz>
Fri, 2 Nov 2007 16:31:24 +0000 (16:31 +0000)
src/share/org/securityfilter/authenticator/FormAuthenticator.java
src/test/org/securityfilter/test/http/form/ForwardAfterLoginTest.java [new file with mode: 0644]
web/example/loginForm.jsp

index 4c8f473..55ad1a8 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/FormAuthenticator.java,v 1.11 2005/02/22 11:02:16 maxcooper Exp $
- * $Revision: 1.11 $
- * $Date: 2005/02/22 11:02:16 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/FormAuthenticator.java,v 1.12 2007/11/02 16:31:24 chris_schultz Exp $
+ * $Revision: 1.12 $
+ * $Date: 2007/11/02 16:31:24 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -66,16 +66,22 @@ import javax.servlet.http.*;
 import java.io.IOException;
 import java.security.Principal;
 
+import java.util.Enumeration;
+import java.net.URLEncoder;
+import java.io.UnsupportedEncodingException;
+
 /**
  * FormAuthenticator - authenticator implementation for the FORM auth method.
  *
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.11 $ $Date: 2005/02/22 11:02:16 $
+ * @author Chris Schultz (chris@christopherschultz.net)
+ * @version $Revision: 1.12 $ $Date: 2007/11/02 16:31:24 $
  */
 public class FormAuthenticator implements Authenticator {
 
    public static final String LOGIN_SUBMIT_PATTERN_KEY = "loginSubmitPattern";
    public static final String DEFAULT_LOGIN_SUBMIT_PATTERN = "/j_security_check";
+
    protected String loginSubmitPattern;
 
    protected static final String FORM_USERNAME = "j_username";
@@ -93,6 +99,79 @@ public class FormAuthenticator implements Authenticator {
 
    protected SecurityRealmInterface realm;
 
+
+    /**
+     * The key that will be used to look up the filter init parameter
+     * that specifies the "forward" parameter used for post-login forward
+     * requests.
+     *
+     * @see #forwardParameterName
+     */
+    public static final String FORWARD_PARAMETER_KEY = "forwardParameter";
+
+    /**
+     * The key that will be used to look up the filter init parameter
+     * that specifies the "forwardMode" parameter used for post-login forward
+     * requests.
+     *
+     * @see #forwardModeParameterName
+     */
+    public static final String FORWARD_MODE_PARAMETER_KEY = "forwardModeParameter";
+
+    /**
+     * The key that will be used to look up the filter init parameter
+     * that specifies the "forwardParameters" parameter used for post-login
+     * forward requests.
+     *
+     * @see #forwardParametersParameterName
+     */
+    public static final String FORWARD_PARAMETERS_PARAMETER_KEY = "forwardParametersParameter";
+
+    /**
+     * The default value for {@link #forwardParameterName}.
+     */
+    public static final String DEFAULT_FORWARD_PARAMETER_NAME = "forward";
+    /**
+     * The default value for {@link #forwardModeParameterName}.
+     */
+    public static final String DEFAULT_FORWARD_MODE_PARAMETER_NAME = "forward-mode";
+    /**
+     * The default value for {@link #forwardParametersParameterName}.
+     */
+    public static final String DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME = "forward-parameters";
+
+    /**
+     * The name of the request parameter that will be recognized as a
+     * post-login forward request.
+     *
+     * @see #forwardParameterName
+     * @see #DEFAULT_FORWARD_PARAMETER_NAME
+     */
+    protected String forwardParameterName;
+
+    /**
+     * The name of the request parameter that will be checked for
+     * either "forward" or "redirect" when processing a post-login forward
+     * request. The default is "redirect".
+     *
+     * @see #forwardModeParameterName
+     * @see #DEFAULT_FORWARD_MODE_PARAMETER_NAME
+     */
+    protected String forwardModeParameterName;
+
+    /**
+     * The name of the request parameter that will be checked to see
+     * whether the login request's request parameters should be forwarded
+     * to the destination URI when processing a post-login forward request.
+     * The options are "true" (to forward the request parameters) or "false"
+     * (to forward to the destination URI with no request parameter
+     * pass-through. The default is "false".
+     *
+     * @see #forwardParameterName
+     * @see #DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME
+     */
+    protected String forwardParametersParameterName;
+
    /**
     * Initilize this Authenticator.
     *
@@ -109,6 +188,21 @@ public class FormAuthenticator implements Authenticator {
          loginSubmitPattern = DEFAULT_LOGIN_SUBMIT_PATTERN;
       }
 
+      // "forward" parameter
+      forwardParameterName = filterConfig.getInitParameter(FORWARD_PARAMETER_KEY);
+      if(null == forwardParameterName)
+         forwardParameterName = DEFAULT_FORWARD_PARAMETER_NAME;
+
+      // "forward-mode" parameter name
+      forwardModeParameterName = filterConfig.getInitParameter(FORWARD_MODE_PARAMETER_KEY);
+      if(null == forwardModeParameterName)
+         forwardModeParameterName = DEFAULT_FORWARD_MODE_PARAMETER_NAME;
+
+      // "forward-parameters" parameter name
+      forwardParametersParameterName = filterConfig.getInitParameter(FORWARD_PARAMETERS_PARAMETER_KEY);
+      if(null == forwardParametersParameterName)
+         forwardParametersParameterName = DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME;
+
       // default page
       defaultPage = securityConfig.getDefaultPage();
 
@@ -174,44 +268,63 @@ public class FormAuthenticator implements Authenticator {
 
       // process login form submittal
       if (request.getMatchableURL().endsWith(loginSubmitPattern)) {
-         String username = request.getParameter(FORM_USERNAME);
-         String password = request.getParameter(FORM_PASSWORD);
-         Principal principal = realm instanceof FlexibleRealmInterface ?
-            ((FlexibleRealmInterface) realm).authenticate(request)
-            : realm.authenticate(username, password);
-         if (principal != null) {
-            // login successful
-
-            // invalidate old session if the user was already authenticated, and they logged in as a different user
-            if (request.getUserPrincipal() != null
-                && false == request.getUserPrincipal().equals(principal)) {
-               request.getSession().invalidate();
-            }
-
-            // manage persistent login info, if persistent login management is enabled
-            // and username/password are passed as part of logon
-            if (persistentLoginManager != null
-                && username != null && password != null) {
-               String rememberme = request.getParameter(FORM_REMEMBERME);
-               // did the user request that their login be persistent?
-               if (rememberme != null) {
-                  // remember login
-                  persistentLoginManager.rememberLogin(request, response, username, password);
-               } else {
-                  // forget login
-                  persistentLoginManager.forgetLogin(request, response);
-               }
-            }
-
-            request.setUserPrincipal(principal);
-            String continueToURL = getContinueToURL(request);
-            // This is the url that the user was initially accessing before being prompted for login.
-            response.sendRedirect(response.encodeRedirectURL(continueToURL));
-         } else {
-            // login failed - forward to error page
-            request.getRequestDispatcher(errorPage).forward(request, response);
-         }
-         return true;
+          String username = request.getParameter(FORM_USERNAME);
+          String password = request.getParameter(FORM_PASSWORD);
+          Principal principal = realm instanceof FlexibleRealmInterface ?
+              ((FlexibleRealmInterface) realm).authenticate(request)
+              : realm.authenticate(username, password);
+          if (principal != null) {
+              // login successful
+
+              // invalidate old session if the user was already authenticated, and they logged in as a different user
+              if (request.getUserPrincipal() != null
+                  && false == request.getUserPrincipal().equals(principal)) {
+                  request.getSession().invalidate();
+              }
+
+              // manage persistent login info, if persistent login management is enabled
+              // and username/password are passed as part of logon
+              if (persistentLoginManager != null
+                  && username != null && password != null) {
+                  String rememberme = request.getParameter(FORM_REMEMBERME);
+                  // did the user request that their login be persistent?
+                  if (rememberme != null) {
+                      // remember login
+                      persistentLoginManager.rememberLogin(request, response, username, password);
+                  } else {
+                      // forget login
+                      persistentLoginManager.forgetLogin(request, response);
+                  }
+              }
+
+              request.setUserPrincipal(principal);
+
+
+              Forward fwd = getForward(request);
+
+              if(fwd.redirect)
+              {
+                  String uri = response.encodeRedirectURL(fwd.uri);
+
+                  // Parameters only need to be explicitly forwarded
+                  // when we're doing a redirect.
+                  if(fwd.forwardParameters)
+                  {
+                      StringBuffer q = this.getFilteredQueryString(request);
+                      if(null != q)
+                          uri += q;
+                  }
+
+                  response.sendRedirect(uri);
+              }
+              else
+                  request.getRequestDispatcher(fwd.uri).
+                      forward(request, response);
+          } else {
+              // login failed - forward to error page
+              request.getRequestDispatcher(errorPage).forward(request, response);
+          }
+          return true;
       }
 
       return false;
@@ -324,6 +437,126 @@ public class FormAuthenticator implements Authenticator {
       }
       return uri;
    }
+
+    /**
+     * A class to represent information about the destination after login.
+     */
+    private static class Forward
+    {
+        /**
+         * The destination URI.
+         */
+        String uri;
+
+        /**
+         * <code>true</code> if this Forward should be redirected through the
+         * client.
+         */
+        boolean redirect;
+
+        /**
+         * <code>true</code> if the forward should include all the parameters
+         * from the current request.
+         */
+        boolean forwardParameters;
+
+        Forward(String uri, boolean redirect, boolean forwardParameters)
+        {
+            this.uri = uri;
+            this.redirect = redirect;
+            this.forwardParameters = forwardParameters;
+        }
+    }
+
+    /**
+     * Gets post-login destination information.
+     */
+    private Forward getForward(HttpServletRequest request)
+    {
+        String uri  = request.getParameter(forwardParameterName);
+        boolean redirect;
+        boolean forwardParameters;
+
+        // Was there a request to forward somewhere else after login?
+        if(null != uri && 0 < uri.trim().length())
+        {
+            // Default to redirect
+            redirect = !"forward".equalsIgnoreCase(request.getParameter(forwardModeParameterName));
+            // Default to do-not-forward-parameters
+            forwardParameters = "true".equalsIgnoreCase(request.getParameter(forwardParametersParameterName));
+        }
+        else
+        {
+            // No forward request: go to the "continue URL" which is either
+            // the user's original request or the default page to hit after login.
+            uri = getContinueToURL(request);
+            redirect = true;
+            forwardParameters = false;
+        }
+
+        return new Forward(uri, redirect, forwardParameters);
+    }
+
+    /**
+     * Gets the query string that will be used when a login request
+     * has included a "forward" directive. We don't want to include
+     * username and password information in the resulting URL, so we
+     * re-build the query string by stripping-out the sensitive
+     * parameters. We also strip-out the "forward" parameter information
+     * because it has served its purpose.
+     *
+     * @param request The request being processed.
+     *
+     * @return A StringBuffer containing the query string (starting with '?')
+     *         with all of the current request's parameters except for
+     *         the username, password, and forward-related parameters.
+     */
+    private StringBuffer getFilteredQueryString(HttpServletRequest request)
+        throws UnsupportedEncodingException
+    {
+        Enumeration e = request.getParameterNames();
+
+        StringBuffer queryString = null;
+
+        if(e.hasMoreElements())
+        {
+            boolean first = true;
+            queryString = new StringBuffer();
+
+            while(e.hasMoreElements())
+            {
+                String name = (String)e.nextElement();
+
+                // Filter-out login-related parameters
+                if(!(FORM_USERNAME.equals(name)
+                     || FORM_PASSWORD.equals(name)
+                     || forwardParameterName.equals(name)
+                     || forwardModeParameterName.equals(name)
+                     || forwardParametersParameterName.equals(name)))
+                {
+                    String[] values = request.getParameterValues(name);
+
+                    for(int i=0; i<values.length; ++i)
+                    {
+                        if(first)
+                        {
+                            queryString.append('?');
+                            first = false;
+                        }
+                        else
+                            queryString.append('&');
+
+                        queryString
+                            .append(URLEncoder.encode(name, "UTF-8"))
+                            .append('=')
+                            .append(URLEncoder.encode(values[i], "UTF-8"));
+                    }
+                }
+            }
+        }
+
+        return queryString;
+    }
 }
 
 // ------------------------------------------------------------------------
diff --git a/src/test/org/securityfilter/test/http/form/ForwardAfterLoginTest.java b/src/test/org/securityfilter/test/http/form/ForwardAfterLoginTest.java
new file mode 100644 (file)
index 0000000..39378fd
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/test/org/securityfilter/test/http/form/ForwardAfterLoginTest.java,v 1.1 2007/11/02 16:31:24 chris_schultz Exp $
+ * $Revision: 1.1 $
+ * $Date: 2007/11/02 16:31:24 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by
+ *        SecurityFilter.org (http://www.securityfilter.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ *    products derived from this software without prior written permission.
+ *    For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ *    nor may "SecurityFilter" appear in their name, without prior written
+ *    permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.test.http.form;
+
+import com.meterware.httpunit.*;
+import junit.framework.Assert;
+import org.securityfilter.example.Constants;
+import org.securityfilter.test.http.TestBase;
+import org.securityfilter.authenticator.FormAuthenticator;
+
+/**
+ * ForwardAfterLoginTest - test forward-afterlogin behavior.
+ *
+ * @author Chris Schultz (chris@christopherschultz.net)
+ * @version $Revision: 1.1 $ $Date: 2007/11/02 16:31:24 $
+ */
+public class ForwardAfterLoginTest extends TestBase {
+   /**
+    * Constructor
+    *
+    * @param name
+    */
+   public ForwardAfterLoginTest(String name) {
+      super(name);
+   }
+
+    public void testForwardAfterLogin()
+        throws Exception
+    {
+        // request the login page
+        WebConversation session = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(baseUrl + "/loginForm.jsp");
+        WebResponse response = session.getResponse(request);
+
+        // make sure the response leads us to login page
+        assertPageTitle(Constants.LOGIN_TITLE, response);
+
+        // submit valid login credentials
+        WebForm loginForm = response.getFormWithID(Constants.LOGIN_FORM_ID);
+        loginForm.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+        loginForm.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+
+        loginForm.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETER_NAME, "/securePage.jsp");
+        loginForm.setParameter(FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME, "forward");
+
+        // Disable automatic redirection so we can detect it ourselves.
+        session.getClientProperties().setAutoRedirect(false);
+
+        response = session.getResponse(loginForm.getRequest());
+
+        // make sure the response leads to the default page (Home page -- index.jsp)
+        assertPageTitle(Constants.SECURE_TITLE, response);
+    }
+
+    public void testRedirectAfterLogin()
+        throws Exception
+    {
+        String contextPath = baseUrl.substring(baseUrl.lastIndexOf('/'));
+
+        // request the login page
+        WebConversation session = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(baseUrl + "/loginForm.jsp");
+        WebResponse response = session.getResponse(request);
+
+        // make sure the response leads us to login page
+        assertPageTitle(Constants.LOGIN_TITLE, response);
+
+        // submit valid login credentials
+        WebForm loginForm = response.getFormWithID(Constants.LOGIN_FORM_ID);
+        loginForm.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+        loginForm.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+
+        loginForm.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETER_NAME, contextPath + "/securePage.jsp");
+        loginForm.setParameter(FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME, "redirect");
+
+        // Disable automatic redirection so we can detect it ourselves.
+        session.getClientProperties().setAutoRedirect(false);
+
+        response = session.getResponse(loginForm.getRequest());
+
+        String location = response.getHeaderField("Location");
+
+        // Remove any ";jsessionid" parameter.
+
+        if(0 <= location.indexOf(";jsessionid="))
+            location = location.replaceAll(";jsessionid=[a-fA-F0-9]+", "");
+
+        // Check for correct redirect (fully-qualified URL)
+        Assert.assertEquals(baseUrl + "/securePage.jsp",
+                            location);
+    }
+
+    public void testRedirectParametersAfterLogin()
+        throws Exception
+    {
+        String contextPath = baseUrl.substring(baseUrl.lastIndexOf('/'));
+
+        // request the login page
+        WebConversation session = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(baseUrl + FormAuthenticator.DEFAULT_LOGIN_SUBMIT_PATTERN);
+        WebResponse response;
+
+        request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+        request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETER_NAME, contextPath + "/securePage.jsp");
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME, "redirect");
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME, "true");
+        request.setParameter("extra", "data");
+
+        // Disable automatic redirection so we can detect it ourselves.
+        session.getClientProperties().setAutoRedirect(false);
+
+        response = session.getResponse(request);
+
+        String location = response.getHeaderField("Location");
+
+        // Remove any ";jsessionid" parameter.
+
+        if(0 <= location.indexOf(";jsessionid="))
+            location = location.replaceAll(";jsessionid=[a-fA-F0-9]+", "");
+
+        // Check for correct redirect (fully-qualified URL)
+        Assert.assertEquals(baseUrl + "/securePage.jsp?extra=data",
+                            location);
+    }
+
+    public void testRedirectNoParametersAfterLogin()
+        throws Exception
+    {
+        String contextPath = baseUrl.substring(baseUrl.lastIndexOf('/'));
+
+        // request the login page
+        WebConversation session = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(baseUrl + FormAuthenticator.DEFAULT_LOGIN_SUBMIT_PATTERN);
+        WebResponse response;
+
+        request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+        request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETER_NAME, contextPath + "/securePage.jsp");
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME, "redirect");
+        request.setParameter(FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME, "false");
+        request.setParameter("extra", "data");
+
+        // Disable automatic redirection so we can detect it ourselves.
+        session.getClientProperties().setAutoRedirect(false);
+
+        response = session.getResponse(request);
+
+        String location = response.getHeaderField("Location");
+
+        // Remove any ";jsessionid" parameter.
+
+        if(0 <= location.indexOf(";jsessionid="))
+            location = location.replaceAll(";jsessionid=[a-fA-F0-9]+", "");
+
+        // Check for correct redirect (fully-qualified URL)
+        Assert.assertEquals(baseUrl + "/securePage.jsp",
+                            location);
+    }
+}
index bdb92f0..d708261 100644 (file)
@@ -1,9 +1,10 @@
 <%@ page session="false" %>
 <%@ page import="org.securityfilter.example.Constants"%>
+<%@ page import="org.securityfilter.authenticator.FormAuthenticator"%>
 
 <html>
 <head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title><%=Constants.LOGIN_TITLE%></title>
 </head>
 <body>
@@ -29,8 +30,28 @@ Password:
    value="<%=Constants.VALID_PASSWORD%>"
 ><p>
 
+<p>
+You may set these post-login forward options if you'd like:<br />
+URL: <input type="text" name="forward" /><br />
+
+Method:
+<input id="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>-redirect" type="radio" name="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>" value="redirect" />
+<label for="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>-redirect">Redirect</label>
+
+<input id="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>-forward" type="radio" name="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>" value="forward" />
+<label for="<%= FormAuthenticator.DEFAULT_FORWARD_MODE_PARAMETER_NAME %>-forward">Forward</label>
+<br />
+
+Include parameters:
+<input id="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>-yes" type="radio" name="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>" value="true" />
+<label for="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>-yes">Yes</label>
+
+<input id="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>-no" type="radio" name="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>" value="false" />
+<label for="<%= FormAuthenticator.DEFAULT_FORWARD_PARAMETERS_PARAMETER_NAME %>-no">No</label>
+</p>
+
 <input type="Submit">
 
 </form>
 </body>
-</html>
\ No newline at end of file
+</html>