IBM Support

Form-based login in Liberty

Education


Abstract

This article offers an introduction to form-based login, it then goes on to explain which parts of the form login flow come from the JEE specification and which are specific to WAS/Liberty and finally explains what steps are needed to implement form login with Liberty.

Content

One of the login challenges defined in the J2EE Specification is form-based login.  It enables the application developer to customize the login process and present an application-specific form by making use of the Form Login Authentication Method.

Form login works in the following manner:

image-20190924162432-1

1. An unauthenticated user requests a resource protected by a JEE Security Constraint, for example https://localhost:port/snoop

2. The application server redirects the request to the Login Form defined in the Web deployment descriptor: https://localhost:port/login.html

WAS creates a cookie called WASReqURL which contains the path to the requested protected resource in the format http[s]://[:port]/snoop

3. On the HTML login form, the user enters the user ID and password and submits the form.

The action triggered by the form submission runs a special Java EE standard servlet j_security_check.

4. If the servlet authenticates the user successfully, WAS reads the WASReqURL cookie and redirects the user to the originally requested resource https://localhost:port/snoop

If the credentials are invalid, WAS redirects the user to an error page, for example https://localhost:port/error.html

NB: It is possible to edit the WASReqURL cookie to change the redirect path after a successful login.  Whilst you can change the contents of the WASReqURL you should not be able to set any redirect location i.e. to another domain.

Form-based login and Liberty:

While everything in the deployment descriptor (web.xml file under the Web project, e.g. snoop.ear\DefaultWebApplication.war\WEB-INF\), the name of the j_security_check servlet, and the general flow of how j_security_check is used are the parts of the form login flow that come from the JEE specification, the WASReqURL and security role to user/group mapping using the ibm-application-bnd.xm* and server.xml files are specific to WAS/Liberty:

image-20191002151258-1

More specifically, the below high-level steps are needed to implement form login with Liberty:
1. Security constraint, login configuration and security role in the web.xml file
2. Login page with form that points to j_security_check
3. Application security enabled on the Liberty server and a user registry configured
4. Security role mapping to an application user in the ibm-application-bnd.xm*, web.xml or server.xml files

Please note that single sign-on (SSO) must be enabled for form-based login to succeed as this will generate the LTPA token that is required for form based login, see Why do I need to enable SSO when using form-based login in my WebSphere Application Server application?

Below is a complete copy of the web.xml file that is discussed in this article.  The individual sections will be discussed below:

  <?xml version="1.0" encoding="UTF-8"?>
  <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"      version="4.0">      <display-name>FormLoginTest</display-name>        <security-constraint>          <web-resource-collection>              <web-resource-name>DefaultDeny</web-resource-name>              <url-pattern>/*</url-pattern>          </web-resource-collection>          <auth-constraint>              <role-name>DefaultDeny</role-name>          </auth-constraint>      </security-constraint>        <security-constraint>          <web-resource-collection>              <web-resource-name>GeneralResources</web-resource-name>              <url-pattern>/login.html</url-pattern>              <url-pattern>/images/*</url-pattern>              <url-pattern>/css/*</url-pattern>              <http-method>GET</http-method>          </web-resource-collection>          <auth-constraint>              <role-name>AllUsers</role-name>          </auth-constraint>      </security-constraint>        <security-constraint>          <web-resource-collection>              <web-resource-name>TestLogin</web-resource-name>              <url-pattern>/TestLogin</url-pattern>              <http-method>GET</http-method>              <http-method>POST</http-method>          </web-resource-collection>          <auth-constraint>              <role-name>TestAuth</role-name>          </auth-constraint>            <user-data-constraint>              <transport-guarantee>CONFIDENTIAL</transport-guarantee>          </user-data-constraint>        </security-constraint>        <security-role>          <role-name>AllUsers</role-name>      </security-role>        <security-role>          <role-name>TestAuth</role-name>      </security-role>        <login-config>          <auth-method>FORM</auth-method>          <form-login-config>              <form-login-page>/login.html</form-login-page>              <form-error-page>/error.html</form-error-page>          </form-login-config>      </login-config>    </web-app>

For 1) Security constraint, login configuration and security role in the web.xml file,

<security-constraint> This tag is used to define the access privileges to a collection of resources using their URL mapping.

If the <transport-guarantee> is set to CONFIDENTIAL or INTEGRAL, it generally means that the use of SSL is required, and that type of security constraint applies to all requests that match the URL patterns in the web resource collection and not just to the login dialog box.  The strength of the required protection is defined by the value of the transport guarantee:

You can configure an application to redirect from HTTP to HTTPS using CONFIDENTIAL.  For further details, see Specifying a Secure Connection.

<login-config> This tag is used to specify an authentication mechanism (authentication method, realm name and form login configuration).  The <realm-name> subelement indicates the realm name to use when the basic authentication scheme is chosen for the web application.  The <form-login-config> subelement specifies the login and error pages that should be used when form-based login is specified.

<security-role> This tag defines the security role.  This role matches to the roles defined in the ibm-application-bnd.xm* and server.xml files.

In the JEE security constraint the * and ** security roles are special when configured in the auth-constraint e.g.

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>GeneralResources</web-resource-name>
            <url-pattern>/images/*</url-pattern>
            <url-pattern>/css/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
    </security-constraint>

The special role name * is a shorthand for all role names defined in the deployment descriptor.  The special role name ** is a shorthand for any authenticated user independent of role.

Security best practices suggest that you Carefully verify that every servlet alias is secure:

The following approach can be taken within every web.xml to ensure that permissions are restrictive:

1. Define an initial security constraint such as that shown below.  This says all URLs (unless overridden with more specific patterns) are restricted to the DefaultDeny role.  The DefaultDeny role name can be pre-bound to the None special role.
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>DefaultDeny</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>DefaultDeny</role-name>
        </auth-constraint>
    </security-constraint>
2. In case of using a Form-based login, define the permissive constraint to allow the web container to display the Login page (and necessary graphics, and so on) to any user, even those who are not authenticated.  The AllUsers role name can be pre-bound to the Everyone special role.
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>GeneralResources</web-resource-name>
            <url-pattern>/login.html</url-pattern>
            <url-pattern>/images/*</url-pattern>
            <url-pattern>/css/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AllUsers</role-name>
        </auth-constraint>
    </security-constraint>
3. After the above two “default” constraints are added, add the “real” security constraint element for each servlet added to the application that is appropriate for that URI.  The advantage of this approach is that new end-points added to the web application are unreachable by default.  If a new servlet is added, you will have to add a security constraint for the new URL in order for anyone to use it.  Such a “default-to-deny” design is a cornerstone of developing secure applications.
<security-constraint>
        <web-resource-collection>
            <web-resource-name>TestLogin</web-resource-name>
            <url-pattern>/TestLogin</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>TestAuth</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <security-role>
        <role-name>TestAuth</role-name>
    </security-role>
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>
4. Save and close the Web deployment descriptor file.

For 2) Login page with form that points to j_security_check,

Simple form-based login does not require any extra code development on the server side.  The j_security_check servlet used by WebSphere Application Server enforces only the name of the input fields that the developer should put in the custom login form.  These fields are as follows:

  • j_username should be the input field in which a user will type the user ID.
  • j_password should be the input field into which the user will type the password.

The action required for the HTTP POST method is j_security_check.  A simple HTML code for the custom login form is given in the following example (login.html also located in the WEB-INF folder):

<html>
<head><title> Security FVT Login Page </title></head>
<body>
<h2>Form Login</h2>
<FORM METHOD=POST ACTION="j_security_check">
<p>
<font size="2"> <strong> Enter user ID and password: </strong></font>
<BR>
<strong> User ID</strong> <input type="text" size="20" name="j_username">
<strong> Password </strong> <input type="password" size="20" name="j_password" autocomplete="off">
<BR>
<BR>
<font size="2"> <strong> And then click this button: </strong></font>
<input type="submit" name="login" value="Login">
</p>
</form>
</body>
</html>

NB: If you are using JSP files as login and error pages, make sure that you set session=”false” to prevent denial of service attacks:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1" session="false"%>

For 3) Application security enabled on the Liberty server and a user registry configured,

a) Enable the <appSecurity-3.0> Liberty feature in the server.xml file

b) Add a user registry, for example

    <basicRegistry>
        <user password="Bob" name="Bob"></user>
    </basicRegistry>

For 4) Security role mapping to an application user in the ibm-application-bnd.xm*, web.xml or server.xml files,

J2EE security relies on roles and mappings to users and groups in a registry.  Annotations and the web.xml are used to define the roles and the ibm-application-bnd.xm* and the server.xml files are used to bind the roles to the users or groups.  While it is possible to add the authorization configuration definition to the ibm-application-bnd.xml or ibm-application-bnd.xmi file, it is recommended that you add the authorization table definitions to the server.xml file under the respective application element because this does not require any updates to the application artefact.

If there is a conflict in the role mapping for a servlet between an application’s web.xml file and annotations, the Servlet specification dictates that the configuration in the web.xml takes precedence.  If there is a conflict between the ibm-application-bnd.xm* and server.xml files, then the configuration in the server.xml file takes precedence.


image-20191002154733-1

When the role mapping binding information for a protected application is not provided, the default authorization engine takes the role name that is protecting the resource as the group name associated with that role.  For example, if the role name is “LibertyUsers”, then a user who belongs to a “LibertyUsers” group has access to that resource.  This applies only when no application bind information is specified for the application in the server.xml or the application binding files.  For further information, see Configuring authorization for applications in Liberty.

Example of a user security role mapping in the server.xml file:

    <webApplication id="FormLoginTest"
        location="FormLoginTest.war" name="FormLoginTest">
        <application-bnd>
            <security-role name="TestAuth">
                <user name="Bob"/>
            </security-role>
            <security-role name="AllUsers">
                <special-subject type="EVERYONE"/>
            </security-role>
        </application-bnd>
    </webApplication>

[{"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Product":{"code":"SSD28V","label":"WebSphere Application Server Liberty Core"},"Component":"","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF016","label":"Linux"},{"code":"PF033","label":"Windows"}],"Version":"All Versions","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Document Information

Modified date:
18 October 2019

UID

ibm11074664