Note
|
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website. |
Learn how to secure a web application through authentication and authorization.
You’ll learn how to secure a web application by performing authentication and authorization using Java 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.
Java EE Security provides capability to configure the basic authentication, form authentication or custom form authentication mechanism by using annotations in servlets. It also provides SecurityContext API for programmatic security checks in application code.
You’ll implement form authentication for a simple web frontend. 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.
The finish
directory in the root of this guide contains the finished application secured with form authentication. Feel free to give it a try before you proceed.
To try out the application, first navigate to the finish
directory and then run the following Maven goals to build the application and run it inside Open Liberty:
mvn install liberty:start-server
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 Liberty server created a self-signed SSL certificate by default. You may follow your browser’s provided instructions to accept the certificate and continue.
Sign into the application with one of the following user credentials from the user registry, which have been provided to you:
Username | Password | Role | Group |
---|---|---|---|
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’ll be blocked and will see a Error 403: Authorization failed
message because Dave doesn’t have a role supported by the application.
Once you’re done checking out the application, log out and stop the Open Liberty server:
mvn liberty:stop-server
For this application, users will be asked to login with a form when they access the application. Users are authenticated and depending on their roles, they will be redirected to the pages that they are authorized to access. If authentication or authorization failed, users will be sent to an error page. The application supports two roles, admin
and user
.
Navigate to the start
directory to begin.
Create the HomeServlet
class in the src/main/java/io/openliberty/guides/ui/HomeServlet.java
file:
link:finish/src/main/java/io/openliberty/guides/ui/HomeServlet.java[role=include]
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 defining welcome.html
as the login page and error.html
as the error page.
The welcome.html
and error.html
pages that implement the login form and error page respectively 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 Java 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 only, 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 will be switched to an HTTPS one.
The SecurityContext interface provides programmatic access to Java EE Security API. Inject a SecurityContext instance into the HomeServlet
class. The doGet()
method uses the isCallerInRole()
method from SecurityContext API to check a user’s role and then forwards the response to the appropriate page.
Open the src/main/webapp/WEB-INF/web.xml
file and look at the rest of the security declaration for the application:
link:finish/src/main/webapp/WEB-INF/web.xml[role=include]
The <security-role>
elements define the roles supported by the application, which are user
and admin
. The <security-constraint>
elements further specify that JSF resources like the user.jsf
and admin.jsf
pages can only be accessed by users with user
and admin
role respectively.
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 and applications would access information in the registry for authentication and authorization using API like Java EE Security API.
Open Liberty provides an easy-to-use basic user registry for developers, which you will configure.
Create the src/main/liberty/config/userRegistry.xml
file:
link:finish/src/main/liberty/config/userRegistry.xml[role=include]
The registry has four users, bob
, alice
, carl
and dave
, and four groups, Employee
, TeamLead
, Manager
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 using the Liberty securityUtility
command with XOR encoding.
Open the server.xml
file to view the security configuration of the server.
link:finish/src/main/liberty/config/server.xml[role=include]
Use the <include>
element to add the basic user registry configuration to your server configuration. Open Liberty will include configuration information from the specified XML file in its server configuration.
Map the groups in the user registry 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 using the <security-role>
and <group>
elements under the <application-bnd>
configuration.
Point your browser to http://localhost:9080
. As you can see, the browser gets redirected from an HTTP connection to an HTTPS connection automatically, which is due to the transport guarantee defined in the HomeServlet
class.
You will see a login form since form authentication is implemented and configured. Sign into the application using one of the credentials from the following table, which is defined in the configured user registry.
Username | Password | Role | Group |
---|---|---|---|
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’ll be blocked and will see a Error 403: Authorization failed
message because Dave doesn’t have a role supported by the application.
Once you’re done checking out the application, log out and stop the Open Liberty server:
mvn liberty:stop-server
Write SecurityTest
class to test the authentication and authorization of the application.
Create the SecurityTest
class in the src/test/java/it/io/openliberty/guides/security/SecurityTest.java
file like the following:
link:finish/src/test/java/it/io/openliberty/guides/security/SecurityTest.java[role=include]
The testAuthenticationFail()
method tests an invalid user authentication while the testAuthorizationFail()
method tests unauthorized access to the application.
The testAuthorizationForAdmin()
and testAuthorizationForUser()
methods, respectively, verify that a user with admin
role and a user with user
role are properly authenticated and can access authorized resource.
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.security.SecurityTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.78 sec - in it.io.openliberty.guides.security.SecurityTest
Results :
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
You learned how to use Java EE Security 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.