How do I create a secure login page using Java?
To be precise, I assume you are looking for design strategies and best practices for building a secure login page that allows you to perform user authentication in a Java enterprise application. In a Java EE (J2EE) environment, creating a login page directly relates to choosing a supported authentication mechanism and then representing the authentication callbacks via a preferred user interface in the presentation tier. In J2EE development, the login page can be implemented using any presentation tier APIs such as JSP, Servlets or Java Server Faces (JSF) and also using model-view-controller (MVC) frameworks such as Struts. The login page typically encapsulates the underlying authentication mechanism provided by the J2EE container environment.
The J2EE specification mandates the J2EE Web container provide support for four types of authentication mechanisms, which include the following:
- HTTP Basic Authentication: The Web container component authenticates a user (or client caller) using a username and password dialogue from the Web client.
- Form-Based Authentication: Most commonly used for Web authentication, it is quite similar to Basic Authentication. But the login dialogue page is customized as a form page to pass the username and password to the Web container.
- Client/Server Mutual Authentication: Both the client and server use X.509 certificates to establish their identities. This authentication usually occurs over a secure communication channel using SSL/TLS protocols.
- HTTP Digest Authentication: With HTTP digest authentication, the client authenticates to the server using a message digest containing the client password and sends it with the HTTP request message.
In a typical J2EE-based Web application, the servlet adopts any one of those authentication mechanisms from the J2EE container services and then uses declarative security mechanisms to map the user principal to a security role defined in its Web deployment descriptor (web.xml) for performing authorization. These J2EE-supported authentication types can also be performed in the J2EE Business/Enterprise JavaBean (EJB) tier, which involves a Web component that receives a user request and then invokes an EJB component on the EJB tier. In a Web component-to-EJB interaction scenario, the application uses a Web component in front of the EJB component to provide authentication.
While integrating with back-end enterprise applications such as Enterprise Information Systems (EIS) and databases, the J2EE environment provides a container-managed resource manager sign-on authentication. This allows engaging authentication with the client caller, including Web and Business tier components. To support additional third-party authentication mechanisms, J2EE recommends the use of JAAS, which facilitates using a pluggable login module and ensures that applications remain independent of their authentication mechanisms. JAAS also supports enforcing authentication and access controls based on user identity in both Web and EJB container environments.
Now the odd scenarios. Using standalone Java clients, how do you create a login page that doesn't run in a J2EE container environment? In this case, the Java client can make use of a programmatic approach to perform authentication, where the Java client application collects the user credentials and verifies the identity against the J2EE security realm by issuing a HTTP authentication request (using FrontController/AuthenticationEnforcer pattern) on the target J2EE environment.
Additionally, most J2EE application server vendors and Web containers provide authentication support via agents from proprietary security infrastructure providers. The use of these security infrastructures allows enforcement of authentication and access control policies regardless of whether the caller application client is a browser, device, or Java/non-Java application.
With agent-based authentication, the application no longer needs to use its own J2EE container-based mechanisms to perform authentication. This also adds value to the application by making it independent of the type of authentication mechanism used. That means the authentication mechanism can be changed without affecting the Web application. As a standards initiative, the Java community process is currently working on a JSR 196 specification, which defines a standard service provider interface that allows authentication mechanisms from proprietary security providers to be integrated with the J2EE application environment.
To support implementing a secure login page, I strongly recommend using appropriate design strategies prescribed in the AuthenticationEnforcer pattern from the Core Security patterns catalog. In terms of best practices, I often recommend the following to ensure a secure login process:
- For security-sensitive Web application authentication, make sure the login page sessions -- including the data exchanged between the server and client -- remain confidential and tamper-proof during transit using SSL/TLS based communication. Using SSL communication with digital certificates offers confidentiality and integrity of data transmitted between the Web applications and client authentication.
- After switching to SSL communication, make sure the application no longer accepts non-SSL requests until logging out from the SSL session. In the event that the client is sending a non-SSL request, the application must enforce re-authentication of that user over a new SSL session and then stop listening to non-SSL requests. Verifying SSL requests can be implemented using various connection filter mechanisms.
- Log and monitor all fake SSL and non-SSL requests using filters. For all such unsolicited requests, redirect the user to an authentication page to provide valid login credentials.
- Verify and validate all login requests and responses and its both inbound and outbound data exchanged with the application. Apply constraints and verify the input data so that the data does not cause any undesirable side effects on the application.
- Use HTTP POST rather than HTTP GET and avoid using HTTP GET requests while generating HTML forms. HTTP GET requests reveal URL-appended information, allowing sensitive information to be revealed in the URL string.
- Identify the originating user and the host destination making the application request in the session ID. Verify that all subsequent requests are received from that same user's host origin until the user logs out. This protects application sessions from hijacking and spoofing.
- Use HTTP session timeouts for all user sessions after a period of inactivity. Redirect the user back to the login page for re-authentication to enable the stored HTTP session state.
- Make sure that your Web application resides on a server accessed via reverse-proxies or Network Address Translation (NAT)-based IP addresses. Then rewrite the URLs of the target Web applications. This protects your Web application from direct access from unsolicited users.