Securing a web application

duration 15 minutes

Prerequisites:

Learn how to secure a web application through authentication and authorization.

What you’ll learn

You’ll learn how to secure a web application by performing authentication and authorization using Jakarta EE Security. Authentication confirms the identity of the user by verifying a user’s credentials while authorization determines whether a user has access to restricted resources.

Jakarta EE Security provides capability to configure the basic authentication, form authentication, or custom form authentication mechanism by using annotations in servlets. It also provides the SecurityContext API for programmatic security checks in application code.

You’ll implement form authentication for a simple web front end. You’ll also learn to specify security constraints for a servlet and use the SecurityContext API to determine the role of a logged-in user.

Getting started

The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:

git clone https://github.com/openliberty/guide-security-intro.git
cd guide-security-intro

The start directory contains the starting project that you will build upon.

The finish directory contains the finished project that you will build.

Try what you’ll build

The finish directory in the root of this guide contains the finished application that is secured with form authentication. Give it a try before you proceed.

To try out the application, first go to the finish directory and run the following Maven goal to build the application and deploy it to Open Liberty:

mvn liberty:run

After you see the following message, your application server is ready.

The defaultServer server is ready to run a smarter planet.

Navigate your browser to this URL to access the application: http://localhost:9080

The application automatically switches from an HTTP connection to a secure HTTPS connection and forwards you to a login page. If the browser gives you a certificate warning, it’s because the Open Liberty server created a self-signed SSL certificate by default. You can follow your browser’s provided instructions to accept the certificate and continue.

Sign in to the application with one of the following user credentials from the user registry, which are provided to you:

UsernamePasswordRoleGroup

alice

alicepwd

user

Employee

bob

bobpwd

admin, user

Manager, Employee

carl

carlpwd

admin, user

TeamLead, Employee

dave

davepwd

N/A

PartTime

Notice that when you sign in as Bob or Carl, the browser redirects to the admin page and you can view their names and roles. When you sign in as Alice, you can only view Alice’s name. When you sign in as Dave, you are blocked and see an Error 403: Authorization failed message because Dave doesn’t have a role that is supported by the application.

After you are finished checking out the application, stop the Open Liberty server by pressing CTRL+C in the shell session where you ran the server. Alternatively, you can run the liberty:stop goal from the finish directory in another shell session:

mvn liberty:stop

Adding authentication and authorization

For this application, users are asked to log in with a form when they access the application. Users are authenticated and depending on their roles, they are redirected to the pages that they are authorized to access. If authentication or authorization fails, users are sent to an error page. The application supports two roles, admin and user.

Navigate to the start directory to begin.

Start Open Liberty in development mode, which starts the Open Liberty server and listens for file changes:

mvn liberty:dev

After you see the following message, your application server in development mode is ready.

Press the Enter key to run tests on demand.

The development mode holds your command prompt to listen for file changes. You need to open another command prompt to continue, or simply open the project in your editor.

Create the HomeServlet class.
src/main/java/io/openliberty/guides/ui/HomeServlet.java

HomeServlet.java

 1// tag::copyright[]
 2/*******************************************************************************
 3 * Copyright (c) 2018, 2019 IBM Corporation and others.
 4 * All rights reserved. This program and the accompanying materials
 5 * are made available under the terms of the Eclipse Public License v1.0
 6 * which accompanies this distribution, and is available at
 7 * http://www.eclipse.org/legal/epl-v10.html
 8 *
 9 * Contributors:
10 *     IBM Corporation - initial API and implementation
11 *******************************************************************************/
12// end::copyright[]
13package io.openliberty.guides.ui;
14
15import java.io.IOException;
16import javax.inject.Inject;
17import javax.security.enterprise.SecurityContext;
18import javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;
19import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
20import javax.servlet.ServletException;
21import javax.servlet.annotation.HttpConstraint;
22import javax.servlet.annotation.ServletSecurity;
23import javax.servlet.annotation.WebServlet;
24import javax.servlet.http.HttpServlet;
25import javax.servlet.http.HttpServletRequest;
26import javax.servlet.http.HttpServletResponse;
27
28@WebServlet(urlPatterns = "/home")
29// tag::AuthenticationMechanism[]
30@FormAuthenticationMechanismDefinition(
31    // tag::loginToContinue[]
32    // tag::errorPage[]
33    loginToContinue = @LoginToContinue(errorPage = "/error.html",
34    // end::errorPage[]
35                                        // tag::loginPage[]
36                                       loginPage = "/welcome.html"))
37                                        // end::loginPage[]
38    // end::loginToContinue[]
39// end::AuthenticationMechanism[]
40// tag::ServletSecurity[]
41// tag::HttpConstraint[]
42@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "user", "admin" },
43// end::HttpConstraint[]
44  // tag::TransportGuarantee[]
45  transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL))
46  // end::TransportGuarantee[]
47// end::ServletSecurity[]
48// tag::HomeServlet[]
49public class HomeServlet extends HttpServlet {
50
51    private static final long serialVersionUID = 1L;
52
53    @Inject
54    private SecurityContext securityContext;
55
56    // tag::javaDoc1[]
57    /**
58     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
59     *      response)
60     */
61    // end::javaDoc1[]
62    // tag::doGet[]
63    protected void doGet(HttpServletRequest request, HttpServletResponse response)
64        throws ServletException, IOException {
65        // tag::CallerInRole[]
66        if (securityContext.isCallerInRole(Utils.ADMIN)) {
67            response.sendRedirect("/admin.jsf");
68        // end::CallerInRole[]
69        } else if  (securityContext.isCallerInRole(Utils.USER)) {
70            response.sendRedirect("/user.jsf");
71        }
72    }
73    // end::doGet[]
74
75    // tag::javaDoc2[]
76    /**
77     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
78     *      response)
79     */
80    // end::javaDoc2[]
81    protected void doPost(HttpServletRequest request, HttpServletResponse response)
82        throws ServletException, IOException {
83        doGet(request, response);
84    }
85}
86// end::HomeServlet[]

The HomeServlet servlet is the entry point of the application. To enable form authentication for the HomeServlet class, define the @FormAuthenticationMechanismDefinition annotation and set its loginToContinue attribute with a @LoginToContinue annotation. This @FormAuthenticationMechanismDefinition annotation defines welcome.html as the login page and error.html as the error page.

The welcome.html page implements the login form, and the error.html page implements the error page. Both pages are provided for you under the src/main/webapp directory. The login form in the welcome.html page uses the j_security_check action, which is defined by Jakarta EE and available by default.

Authorization determines whether a user can access a resource. To restrict access to authenticated users with user and admin roles, define the @ServletSecurity annotation with the @HttpConstraint annotation and set the rolesAllowed attribute to these two roles.

The transportGuarantee attribute defines the constraint on the traffic between the client and the application. Set it to CONFIDENTIAL to enforce that all user data must be encrypted, which is why an HTTP connection from a browser switches to HTTPS.

The SecurityContext interface provides programmatic access to the Jakarta EE Security API. Inject a SecurityContext instance into the HomeServlet class. The doGet() method uses the isCallerInRole() method from the SecurityContext API to check a user’s role and then forwards the response to the appropriate page.

The src/main/webapp/WEB-INF/web.xml file contains the rest of the security declaration for the application.

web.xml

 1<?xml version="1.0" encoding="UTF-8"?>
 2<!-- tag::copyright[] -->
 3<!--
 4    Copyright (c) 2018, 2019 IBM Corp.
 5
 6    Licensed under the Apache License, Version 2.0 (the "License");
 7    you may not use this file except in compliance with the License.
 8    You may obtain a copy of the License at
 9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17-->
18<!-- end::copyright[]-->
19<!-- tag::webxml[] -->
20<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
21    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
23    version="3.1">
24    <display-name>Liberty Project</display-name>
25
26    <!-- WebAppJSF: Faces Servlet -->
27    <servlet>
28      <servlet-name>Faces Servlet</servlet-name>
29      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
30      <load-on-startup>1</load-on-startup>
31    </servlet>
32
33    <!-- WebAppJSF: Faces Servlet Mapping -->
34    <servlet-mapping>
35      <servlet-name>Faces Servlet</servlet-name>
36      <url-pattern>*.jsf</url-pattern>
37    </servlet-mapping>
38
39    <welcome-file-list>
40      <welcome-file>/index.html</welcome-file>
41    </welcome-file-list>
42
43    <!-- tag::webxmlsecurity[] -->
44    <!-- SECURITY ROLES -->
45    <!-- tag::security-role[] -->
46    <security-role>
47      <!-- tag::role-name-admin[] -->
48      <role-name>admin</role-name>
49      <!-- end::role-name-admin[] -->
50    </security-role>
51
52    <security-role>
53      <!-- tag::role-name-user[] -->
54      <role-name>user</role-name>
55      <!-- end::role-name-user[] -->
56    </security-role>
57    <!-- end::security-role[] -->
58
59    <!-- SECURITY CONSTRAINTS -->
60    <!-- tag::security-constraint[] -->
61    <security-constraint>
62      <web-resource-collection>
63        <web-resource-name>AdminViewProperties</web-resource-name>
64        <!-- tag::url-pattern-admin[] -->
65        <url-pattern>/admin.jsf</url-pattern>
66        <!-- end::url-pattern-admin[] -->
67        <http-method>GET</http-method>
68      </web-resource-collection>
69      <auth-constraint>
70        <role-name>admin</role-name>
71      </auth-constraint>
72    </security-constraint>
73
74    <security-constraint>
75      <web-resource-collection>
76        <web-resource-name>UserViewProperties</web-resource-name>
77        <!-- tag::url-pattern-user[] -->
78        <url-pattern>/user.jsf</url-pattern>
79        <!-- end::url-pattern-user[] -->
80        <http-method>GET</http-method>
81      </web-resource-collection>
82      <auth-constraint>
83        <role-name>user</role-name>
84      </auth-constraint>
85    </security-constraint>
86    <deny-uncovered-http-methods/>
87    <!-- end::security-constraint[] -->
88    <!-- end::webxmlsecurity[] -->
89
90    <!-- Handle 403 Error -->
91    <error-page>
92      <error-code>403</error-code>
93      <location>/error403.html</location>
94    </error-page>
95</web-app>
96<!-- end::webxml[] -->

The <security-role/> elements define the roles that are supported by the application, which are user and admin. The <security-constraint/> elements specify that JSF resources like the user.jsf and admin.jsf pages can be accessed only by users with user and admin roles.

Configuring the user registry

User registries store user account information, such as username and password, for use by applications to perform security-related operations. Typically, application servers would be configured to use an external registry like a Lightweight Directory Access Protocol (LDAP) registry. Applications would access information in the registry for authentication and authorization by using APIs like the Jakarta EE Security API.

Open Liberty provides an easy-to-use basic user registry for developers, which you will configure.

Create the userRegistry configuration file.
src/main/liberty/config/userRegistry.xml

userRegistry.xml

 1<server description="Sample Liberty server">
 2  <basicRegistry id="basic" realm="WebRealm">
 3    <!-- tag::user-bob[] -->
 4    <user name="bob"
 5      password="{xor}PTA9Lyg7" /> <!-- bobpwd -->
 6    <!-- end::user-bob[] -->
 7    <!-- tag::user-alice[] -->
 8    <user name="alice"
 9      password="{xor}PjM2PDovKDs=" />  <!-- alicepwd -->
10    <!-- end::user-alice[] -->
11    <!-- tag::user-carl[] -->
12    <user name="carl"
13      password="{xor}PD4tMy8oOw==" />  <!-- carlpwd -->
14    <!-- end::user-carl[] -->
15    <!-- tag::user-dave[] -->
16    <user name="dave"
17      password="{xor}Oz4pOi8oOw==" />  <!-- davepwd -->
18    <!-- end::user-dave[] -->
19
20    <!-- tag::group-name-Manager[] -->
21    <group name="Manager">
22      <member name="bob" />
23    </group>
24    <!-- end::group-name-Manager[] -->
25
26    <!-- tag::group-name-TeamLead[] -->
27    <group name="TeamLead">
28      <member name="carl" />
29    </group>
30    <!-- end::group-name-TeamLead[]-->
31
32    <!-- tag::group-name-Employee[] -->
33    <group name="Employee">
34      <member name="alice" />
35      <member name="bob" />
36      <member name="carl" />
37    </group>
38    <!-- end::group-name-Employee[] -->
39
40    <!-- tag::group-name-PartTime[] -->
41    <group name="PartTime">
42      <member name="dave" />
43    </group>
44    <!-- end::group-name-PartTime[] -->
45  </basicRegistry>
46</server>

The registry has four users, bob, alice, carl, and dave. It also has four groups: Manager, TeamLead, Employee, and PartTime. Each user belongs to one or more groups.

It is not recommended to store passwords in plain text. The passwords in the userRegistry.xml file are encoded by using the Liberty securityUtility command with XOR encoding.

server.xml

 1<!-- tag::serverxml[] -->
 2<server description="Sample Liberty server">
 3
 4  <featureManager>
 5    <feature>appSecurity-3.0</feature>
 6    <feature>jsf-2.3</feature>
 7    <feature>servlet-4.0</feature>
 8  </featureManager>
 9
10  <variable name="default.http.port" defaultValue="9080"/>
11  <variable name="default.https.port" defaultValue="9443"/>
12  <variable name="application.name" defaultValue="guide-security-intro.war"/>
13
14  <httpEndpoint id="defaultHttpEndpoint"
15    httpPort="${default.http.port}"
16    httpsPort="${default.https.port}" />
17
18  <!-- tag::location[] -->
19  <include location="userRegistry.xml"/>
20  <!-- end::location[]-->
21
22  <application location="${application.name}" type="war"
23               id="${application.name}"
24               name="${application.name}" context-root="/">
25    <!-- tag::application-bnd[] -->
26    <application-bnd>
27      <!-- tag::Security[] -->
28      <!-- tag::security-role-admin[] -->
29      <security-role name="admin">
30      <!-- end::security-role-admin[] -->
31        <!-- tag::Group[] -->
32        <!-- tag::group-name-Manager[] -->
33        <group name="Manager" />
34        <!-- end::group-name-Manager[] -->
35        <!-- tag::group-name-TeamLead[] -->
36        <group name="TeamLead" />
37        <!-- end::group-name-TeamLead[] -->
38        <!-- end::Group[] -->
39      </security-role>
40      <!-- tag::security-role-user[] -->
41      <security-role name="user">
42      <!-- end::security-role-user[] -->
43        <!-- tag::group-name-Employee[] -->
44        <group name="Employee" />
45        <!-- end::group-name-Employee[] -->
46      </security-role>
47      <!-- end::Security[] -->
48    </application-bnd>
49     <!-- end::application-bnd[] -->
50  </application>
51</server>
52<!-- end::serverxml[] -->

Use the <include/> element to add the basic user registry configuration to your server configuration. Open Liberty includes configuration information from the specified XML file in its server configuration.

The server.xml file contains the security configuration of the server under the <application-bnd/> element. Use the <security-role/> and <group/> elements to map the groups in the userRegistry.xml file to the appropriate user roles supported by the application for proper user authorization. The Manager and TeamLead groups are mapped to the admin role while the Employee group is mapped to the user role.

Running the application

The Open Liberty server was started in development mode at the beginning of the guide and all the changes were automatically picked up.

HomeServlet.java

 1// tag::copyright[]
 2/*******************************************************************************
 3 * Copyright (c) 2018, 2019 IBM Corporation and others.
 4 * All rights reserved. This program and the accompanying materials
 5 * are made available under the terms of the Eclipse Public License v1.0
 6 * which accompanies this distribution, and is available at
 7 * http://www.eclipse.org/legal/epl-v10.html
 8 *
 9 * Contributors:
10 *     IBM Corporation - initial API and implementation
11 *******************************************************************************/
12// end::copyright[]
13package io.openliberty.guides.ui;
14
15import java.io.IOException;
16import javax.inject.Inject;
17import javax.security.enterprise.SecurityContext;
18import javax.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;
19import javax.security.enterprise.authentication.mechanism.http.LoginToContinue;
20import javax.servlet.ServletException;
21import javax.servlet.annotation.HttpConstraint;
22import javax.servlet.annotation.ServletSecurity;
23import javax.servlet.annotation.WebServlet;
24import javax.servlet.http.HttpServlet;
25import javax.servlet.http.HttpServletRequest;
26import javax.servlet.http.HttpServletResponse;
27
28@WebServlet(urlPatterns = "/home")
29// tag::AuthenticationMechanism[]
30@FormAuthenticationMechanismDefinition(
31    // tag::loginToContinue[]
32    // tag::errorPage[]
33    loginToContinue = @LoginToContinue(errorPage = "/error.html",
34    // end::errorPage[]
35                                        // tag::loginPage[]
36                                       loginPage = "/welcome.html"))
37                                        // end::loginPage[]
38    // end::loginToContinue[]
39// end::AuthenticationMechanism[]
40// tag::ServletSecurity[]
41// tag::HttpConstraint[]
42@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "user", "admin" },
43// end::HttpConstraint[]
44  // tag::TransportGuarantee[]
45  transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL))
46  // end::TransportGuarantee[]
47// end::ServletSecurity[]
48// tag::HomeServlet[]
49public class HomeServlet extends HttpServlet {
50
51    private static final long serialVersionUID = 1L;
52
53    @Inject
54    private SecurityContext securityContext;
55
56    // tag::javaDoc1[]
57    /**
58     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
59     *      response)
60     */
61    // end::javaDoc1[]
62    // tag::doGet[]
63    protected void doGet(HttpServletRequest request, HttpServletResponse response)
64        throws ServletException, IOException {
65        // tag::CallerInRole[]
66        if (securityContext.isCallerInRole(Utils.ADMIN)) {
67            response.sendRedirect("/admin.jsf");
68        // end::CallerInRole[]
69        } else if  (securityContext.isCallerInRole(Utils.USER)) {
70            response.sendRedirect("/user.jsf");
71        }
72    }
73    // end::doGet[]
74
75    // tag::javaDoc2[]
76    /**
77     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
78     *      response)
79     */
80    // end::javaDoc2[]
81    protected void doPost(HttpServletRequest request, HttpServletResponse response)
82        throws ServletException, IOException {
83        doGet(request, response);
84    }
85}
86// end::HomeServlet[]

Point your browser to the http://localhost:9080 URL. As you can see, the browser gets automatically redirected from an HTTP connection to an HTTPS connection because the transport guarantee is defined in the HomeServlet class.

You will see a login form since form authentication is implemented and configured. Sign in to the application by using one of the credentials from the following table. The credentials are defined in the configured user registry.

UsernamePasswordRoleGroup

alice

alicepwd

user

Employee

bob

bobpwd

admin, user

Manager, Employee

carl

carlpwd

admin, user

TeamLead, Employee

dave

davepwd

N/A

PartTime

Notice that when you sign in as Bob or Carl, the browser redirects to the admin page and you can view their names and roles. When you sign in as Alice, you can only view Alice’s name. When you sign in as Dave, you are blocked and see an Error 403: Authorization failed message because Dave doesn’t have a role that is supported by the application.

Testing the application

Write the SecurityIT class to test the authentication and authorization of the application.

Create the SecurityIT class.
src/test/java/it/io/openliberty/guides/security/SecurityIT.java

SecurityIT.java

  1// tag::copyright[]
  2/*******************************************************************************
  3 * Copyright (c) 2018, 2019 IBM Corporation and others.
  4 * All rights reserved. This program and the accompanying materials
  5 * are made available under the terms of the Eclipse Public License v1.0
  6 * which accompanies this distribution, and is available at
  7 * http://www.eclipse.org/legal/epl-v10.html
  8 *
  9 * Contributors:
 10 *     IBM Corporation - Initial implementation
 11 *******************************************************************************/
 12// end::copyright[]
 13package it.io.openliberty.guides.security;
 14
 15import static org.junit.jupiter.api.Assertions.assertEquals;
 16import static org.junit.jupiter.api.Assertions.assertTrue;
 17
 18import java.net.URI;
 19import java.util.ArrayList;
 20import java.util.List;
 21
 22import javax.net.ssl.SSLContext;
 23import javax.servlet.http.HttpServletResponse;
 24
 25import org.apache.http.HttpResponse;
 26import org.apache.http.NameValuePair;
 27import org.apache.http.client.HttpClient;
 28import org.apache.http.client.config.CookieSpecs;
 29import org.apache.http.client.config.RequestConfig;
 30import org.apache.http.client.entity.UrlEncodedFormEntity;
 31import org.apache.http.client.methods.HttpGet;
 32import org.apache.http.client.methods.HttpPost;
 33import org.apache.http.impl.client.HttpClientBuilder;
 34import org.apache.http.message.BasicNameValuePair;
 35import org.apache.http.util.EntityUtils;
 36import org.junit.jupiter.api.BeforeEach;
 37import org.junit.jupiter.api.Test;
 38
 39public class SecurityIT {
 40
 41    private static String urlHttp;
 42    private static String urlHttps;
 43
 44    @BeforeEach
 45    public void setup() throws Exception {
 46        urlHttp = "http://localhost:" + System.getProperty("http.port");
 47        urlHttps = "https://localhost:" + System.getProperty("https.port");
 48        ITUtils.trustAll();
 49    }
 50
 51    @Test
 52    // tag::testAuthenticationFail[]
 53    public void testAuthenticationFail() throws Exception {
 54        executeURL("/", "bob", "wrongpassword", true, -1, "Don't care");
 55    }
 56    // end::testAuthenticationFail[]
 57
 58    @Test
 59    // tag::testAuthorizationForAdmin[]
 60    public void testAuthorizationForAdmin() throws Exception {
 61        executeURL("/", "bob", "bobpwd", false,
 62            HttpServletResponse.SC_OK, "admin, user");
 63    }
 64    // end::testAuthorizationForAdmin[]
 65
 66    @Test
 67    // tag::testAuthorizationForUser[]
 68    public void testAuthorizationForUser() throws Exception {
 69        executeURL("/", "alice", "alicepwd", false,
 70            HttpServletResponse.SC_OK, "<title>User</title>");
 71    }
 72    // end::testAuthorizationForUser[]
 73
 74    @Test
 75    // tag::testAuthorizationFail[]
 76    public void testAuthorizationFail() throws Exception {
 77        executeURL("/", "dave", "davepwd", false,
 78            HttpServletResponse.SC_FORBIDDEN, "Error 403: Authorization failed");
 79    }
 80    // end::testAuthorizationFail[]
 81
 82    private void executeURL(
 83        String testUrl, String userid, String password,
 84        boolean expectLoginFail, int expectedCode, String expectedContent)
 85        throws Exception {
 86
 87        // Use HttpClient to execute the testUrl by HTTP
 88        URI url = new URI(urlHttp + testUrl);
 89        HttpGet getMethod = new HttpGet(url);
 90        HttpClientBuilder clientBuilder = HttpClientBuilder.create();
 91        SSLContext sslContext = SSLContext.getDefault();
 92        clientBuilder.setSSLContext(sslContext);
 93        clientBuilder.setDefaultRequestConfig(
 94            RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build());
 95        HttpClient client = clientBuilder.build();
 96        HttpResponse response = client.execute(getMethod);
 97
 98        // Response should be login.html
 99        String loginBody = EntityUtils.toString(response.getEntity(), "UTF-8");
100        assertTrue(loginBody.contains("window.location.assign"),
101            "Not redirected to home.html");
102        String[] redirect = loginBody.split("'");
103
104        // Use j_security_check to login
105        HttpPost postMethod = new HttpPost(urlHttps + "/j_security_check");
106        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
107        nvps.add(new BasicNameValuePair("j_username", userid ));
108        nvps.add(new BasicNameValuePair("j_password", password));
109        postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
110        response = client.execute(postMethod);
111        assertEquals(HttpServletResponse.SC_FOUND,
112            response.getStatusLine().getStatusCode(),
113            "Expected " + HttpServletResponse.SC_FOUND + " status code for login");
114
115        // Return if login fails
116        if (expectLoginFail) {
117            String location = response.getFirstHeader("Location").getValue();
118            assertTrue(location.contains("error.html"),
119                "Error.html was not returned");
120            return;
121        }
122
123        // Use HttpClient to execute the redirected url
124        url = new URI(urlHttps + redirect[1]);
125        getMethod = new HttpGet(url);
126        response = client.execute(getMethod);
127        assertEquals(expectedCode, response.getStatusLine().getStatusCode(),
128            "Expected " + expectedCode + " status code for login");
129
130        // Return if not SC_OK
131        if (expectedCode != HttpServletResponse.SC_OK) {
132            return;
133        }
134
135        // Check the content of the response returned
136        String actual = EntityUtils.toString(response.getEntity(), "UTF-8");
137        assertTrue(actual.contains(userid),
138            "The actual content did not contain the userid \"" + userid +
139            "\". It was:\n" + actual);
140        assertTrue(actual.contains(expectedContent),
141            "The url " + testUrl + " did not return the expected content \""
142            + expectedContent + "\"" + "The actual content was:\n" + actual);
143    }
144
145}

The testAuthenticationFail() method tests an invalid user authentication while the testAuthorizationFail() method tests unauthorized access to the application.

The testAuthorizationForAdmin() and testAuthorizationForUser() methods verify that users with admin or user roles are properly authenticated and can access authorized resource.

Running the tests

Since you started Open Liberty in development mode at the start of the guide, press the enter/return key to run the tests.

You see the following output:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.security.SecurityIT
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.78 sec - in it.io.openliberty.guides.security.SecurityIT

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

When you are done checking out the service, exit development mode by pressing CTRL+C in the shell session where you ran the server, or by typing q and then pressing the enter/return key.

Great work! You’re done!

You learned how to use Jakarta EE Security in Open Liberty to authenticate and authorize users to secure your web application.

Next, you can try the related MicroProfile JWT guide. It demonstrates technologies to secure backend services.

Guide Attribution

Securing a web application by Open Liberty is licensed under CC BY-ND 4.0

Copied to clipboard
Copy code block
Copy file contents

Prerequisites:

Nice work! Where to next?

What did you think of this guide?

Extreme Dislike Dislike Like Extreme Like

What could make this guide better?

Raise an issue to share feedback

Create a pull request to contribute to this guide

Need help?

Ask a question on Stack Overflow

Like Open Liberty? Star our repo on GitHub.

Star