Securing Web Applications
Start course
Difficulty
Intermediate
Duration
1h 6m
Students
9
Description

In this course, we will learn the concepts of Java EE 7 with a focus on Secure Java EE 7 Applications with Security Mechanism, Web Application Security, and Programmatic Security.

Learning Objectives

  • Secure Java EE 7 Applications

Intended Audience

  • Anyone looking to earn Oracle Java Certification
  • Those who want to improve their Java EE 7 knowledge
  • Java developers

Prerequisites

  • Have at least 2 years of Java development experience 
Transcript

Hello there. In this lesson, we'll talk about securing web applications. So, let's start. Let's start by looking at our basic deployment scenario. Someone using a browser or a rich client application with access to a web component that is hosted on a web server. The starting point for all interactions with web components on the Java EE web container is an HTTP request. This is true whether the web component is a servlet, JAX-RS resource, or WebSocket. Even in the case of WebSocket, the client may not establish a WebSocket session until the opening HTTP handshake interaction has completed. In this figure, the user is initiating an HTTP request from a browser or rich client for a web component that is protected by a security model on the server. Before the request can be fulfilled, the server security model must consider the following three questions. Who is asking for the resource? If the user has not previous logged into the web server and if the HTTP request is not carrying some indication of that state, the request is anonymous. It may be that the security model allows anonymous access to the web component, or it may be that the server must know the identity of the user requesting the resource, in order to answer the next question. May this person have it. If the web server does not allow anonymous access to the web component, then it has the information necessary to determine whether this particular user is allowed to access the resource or not. Once the server has made this determination, the server needs to consider the next question. How private is its data? The server may have decided that the data the web component yields in response to the request must be delivered back to the client, in such a way that guarantees that the information has not been altered en route. Or the server may wish to ensure with some level of certainty that anyone intercepting the data it sends from the web component to the client cannot read it. The process of determining the answers to these questions are more commonly known as authentication establishing the identity of a user making a request. Authorization: granting or denying access to a web component by a user. Establishing data privacy: determining the privacy level of the communication channel used to transmit data between the web component and the client. Java EE Web Container Security. The Java EE Web container supports a declarative security model, where the container serves as the gatekeeper for all web components that choose to be protected by it. It does this by intercepting all HTTP requests to the application and determining whether they can continue and if so, over what channel. A web application that chooses to use the Java EE Web containers declarative security model does so by adding security declarations to its deployment descriptor, in combination with certain annotations in certain cases.

This kind of static configuration generally allows the security model for an application to be configured and defined separately from the application logic itself. The second security model that a web application may choose to use is the programmatic one. In this model, the application itself is responsible for determining whether an HTTP request issued by a user to one or more of its web components is allowed to execute the application logic of the web component. In this case, the application developer is essentially responsible for programming the web application security in the application itself. There are a number of runtime APIs concerned with different aspects of security in a web application that are useful to developers, whether they choose to use a declarative model or a programmatic one. Of course, every good security model has many more features in addition to the core three we have just described; including auditing, nonrepudiation, and interoperability. Every implementation of the Java EE platform will have some level of support for these features, but the level of support is likely to differ from implementation to implementation. We'll focus on the three core features of authentication, authorization, and establishing data privacy.

Since they are supported in a standard way by the Java EE web container, and because they cover the security needs of a majority of Java EE web applications. The Declarative Security Model:  The declarative security model is declared in the web.xml deployment descriptor of the web application. We'll see many examples of relevant syntax, but let's start with the models that allow you to ensure that only known or authenticated users are allowed to access the web components in a Java EE web application. Authentication: We'll look at the three standard types of authentication for Java EE web applications in this section, starting with the simplest. Basic Authentication: This is the simplest HTTP-based authentication scheme. Basic authentication is initiated when the client sends its credentials in the form of a username and password pair encoded in an HTTP header. The client may either send this pre-emptively or in a reaction to a challenge from the server if the client sends an unauthenticated request. Because the credentials in the HTTP basic scheme are encoded only with base 64 encoding, they are vulnerable to being intercepted and decoded.

This is a good scheme to use in a web application where you need to sign in and need to know which user is accessing the application, but you do not necessarily have a strong concern about the privacy of the data in the application. In other words, basic authentication is useful in applications where you wish to tailor the content to the users because you already know something about them. But you do not necessarily need a strong security scheme to protect the data that you are sending or receiving. Other web applications that wish to protect the credentials in the application data may choose to use basic authentication, but only when the communication occurs over an encrypted or private connection. Browsers typically use a basic model username password dialog to retrieve the user credentials, so the user experience from a browser is simple, but it's also not easy to customize. Form-Based

Authentication: Form-based authentication is a mechanism that allows the user credentials to be gathered by a highly customizable HTML form in a login page created by the developer. The mechanism defines the pair of HTTP request parameters that signify the username and password that are encoded in a form element in the web page. Like basic authentication, the credentials are vulnerable to interception. The main difference between form authentication and basic authentication is that the look and placement of the login form is customizable, and thus suits applications that are more conscious of the user experience.

Again, applications that are doing more than a casual personalization based on the user identity and that are concerned about maintaining the integrity of credentials supplied by the user will choose to use only form-based authentication over an encrypted or private connection. Client Certificate Authentication: Client certificate authentication is a process by which the server and optionally the client authenticate one another using a digital certificate which acts as a kind of encrypted passport that verifies the agent's identity. The process is more secure than either basic or form-based authentication, because the credentials are always transferred using HTTP over SSL, and because the client is able to verify the server identity. Once you have decided which scheme you wish to use, configuring it is relatively easy. You specify it in the web.xml deployment descriptor of the war file in which your web components are packaged. The key element to include in the deployment descriptor is the login-config element. Here are some excerpts of web.xml files that specify each of the three types of authentication that you can use for web applications. For basic authentication, including this snippet of XML under the top-level web-app element of the web.xml, configures an application to receive an HTTP basic authentication challenge when attempting to access a protected web component.

The server verifies the credentials that the client sends in response with the matching user credentials in the server's file authentication realm. To specify your application, use form authentication if you include the following XML under the web-app element of the web.xml. Then the server redirects any unauthenticated requests to protected resources within the web application to the login.html page located at the root of the web application's URI namespace. The login.html page needs to include a form of the shape show next. And so, the form submission posts, requests, parameters named "j_username" and "j_password" containing the values of the username and password that the user enters to. Especially reserved name j_security_check on the server that processes the authentication request. If the authentication succeeds, the user is redirected to the protected resource he requested in the first place. If the authentication fails, the user is redirected to the error.html page that was specified in the form login config element and that is located at the root of the web applications URI space. Finally, here's the login config snippet you need to include in your web application if you would like the server to initiate a client certificate challenge when an unauthenticated user of the web application attempts to access a protected resource. Being able to specify an authentication scheme for the web component isn't any use unless you know how to protect those server-side endpoints in the first place. Thus, we turn to the language of authentication in Java EE web applications. Authorization. Authorization is the process by which the Java EE web container decides whether a particular user is permitted access to a particular endpoint. The Java EE platform uses a level of indirection in defining users by using the idea of a user role or simply a role. A role is a kind of abstraction of a user that allows authorization rules to be set up in the application without actually having to put real usernames in the application configuration. When an authenticated HTTP request for a web component arrives at the web container, the web container must decide three things in order to determine whether it will grant access to the web component the request is for. First, the web container must determine to which role or roles the authenticated user belongs. How users are associated with roles is not a standard part of the Java EE platform and therefore will vary from Java EE implementation to Java EE implementation. In the GlassFish 4.0 application server, you can make the association between the user and the roles to which he belongs in a GlassFish specific deployment descriptor called the glassfish.xml file that you co-package with the war file containing your endpoints. Other application servers however, use different schemes. Next, the web container looks at the web applications deployment descriptor with the web.xml file co-packaged in the war file. The definition of which roles are allowed to access to which URI in the URI space of a web application is expressed in a number of XML elements called security constraints which have been written by the developer. Once the web container has examined the deployment descriptor, it knows which roles are allowed to access to the URI that the original HTTP request is for. Finally, since the web container knows the association between the requested URI and the web component, whether it be static file, Java servlet, JSP, Java server faces page, JAX-RS resource or Java WebSocket, it can now determine whether the user has access to the web component. This figure shows the process of authorization. With these three pieces of information, the server can then decide for a given user an HTTP request URI whether the user is allowed access to the web component. Now the mapping of URIs to web components is handled by the individual component technologies. So, we already know one part of the three. The question of the role to which the user issuing the HTTP request belongs, as we already mentioned is defined in the Java EE implementation. To consider the question, are users in this role allowed to access this URI?

We need to look at the security constraint element from the web.xml as this is where that question will be answered for a web application. Security constraints. The security constraint element contains two pieces of information, a web resource collection in the web resource collection sub-element. This is composed of a list of URL patterns which define a portion of the URI space within the web application to which the containing security constraint applies. The second component is a list of HTTP methods that defines the HTTP operations on the URIs covered in the URL patterns to which you wish this security constraint to apply. An authorization constraints in the auth constraints sub-elements, this is composed of a list of the names of roles to which the security constraint will apply. The security constraint element also may contain a third sub-element user-data-constraint, which defines how data is transported between client and server for the web component operations defined in the containing security constraint. This table contains a description of each of the sub-elements. The URL pattern element contains a string that indicates a URI or signifies some matching set of URIs. There are three ways you can define a URI pattern value. Exact path. This is a path relative to the context root of the web application. For example, /airlines/booking.xhtml. This path matches one and only one web component in the web application. Wildcard. This is a path that defines a group of URLs relative to the context root of the web application. For example, /airlines/* indicates all URIs starting with airlines, including for example: /airlines/booking.xhtml. File name ending. This is a URL pattern that looks for a particular endpoint pattern in a URI. For example, if you decided to protect all the Java server faces pages ending in .xhtml in your application, you could use the file name extension URL pattern *.xhtmlin in the URL pattern element. The auth-constraint element is much simpler. It simply contains a list of the names of user roles that are allowed access under the limits of these security constraints. The values of the user roles in the role name element may be drawn from the list of security roles that has been previously defined for this web.xml. This list is held in a list of security role sub-elements of the root web app elements of the web.xml with the name of the role, the text value of the role name sub-element. Note that there is a special role name '*', which denotes any user. Using * in a security constraint allows any user to access the resources matched under the URL pattern provided they have authenticated. This is different from allowing open access to resources. In this latter case, the access is granted to anyone authenticated or not. This gives us the answer to our question, to which roles is a given HTTP request URI allowed access in my web application? How to ensure data privacy? User data constraints. The user-data-constraint of a security constraint defines the level of privacy the web application needs in order for users to access it. This is defined in the sub-element user-data-constraint of the security constraint. It takes a text value either, NONE, INTEGRAL or CONFIDENTIAL. A value of NONE allows the Java EE server to interpret this as allowing access over HTTP, which is the default mode if non-user data constraint is included. The risk to application data is that a third party can intercept the HTTP interactions and read potentially sensitive data. A value of INTEGRAL or CONFIDENTIAL is in practice interpreted by Java EE web containers as meaning the web components need an encrypted connection. A note on WebSockets. A final note on WebSockets. Java WebSockets use an underlying protocol that is not the same as HTTP. Java WebSockets are mapped by the Java WebSocket API to URIs within a web application and are in fact covered by the security constraints in a web application. How can this be possible? You'll recall that a WebSocket connection can be established only by the client initiating a specifically formatted HTTP request called a WebSocket opening handshake. It is this HTTP response interaction that is gated by the security model of the web application that contains it. If the opening handshake returns an HTTP 403 Forbidden response, the WebSocket connection is not established. This means that the authorization model of the Java EE web container applies to Java WebSockets just as it does to other HTTP components in the platform. How does a Java WebSocket authenticate the opening handshake request, so that the Java EE web container can check the caller identity and determine whether to authorize the interaction? Unfortunately, the WebSocket protocol does not include any standard mechanism for authentication. Fortunately, WebSocket connection in web applications are typically initiated by JavaScript code within a web page. So, when a WebSocket attempts the opening handshake with the Java EE web container, the Java EE web container knows the authorization state of the opening handshake HTTP request because it knows the authorization state of the web page in which the JavaScript code is executing. In this way, provided the web page in which the WebSocket connection is trying to be established and authenticated, so is the opening handshake. And the converse is also true. The upshot of this is that everything in the Java EE web container security model here is through for java WebSockets, except that in order to know that a WebSocket client in a web page is authenticated with the Java EE web container, you must ensure that the web page that contains it is authenticated. Security constraints in Java servlets. One type of web component does not need the web.xml deployment descriptor to define the security constraints under which it wishes to operate.

Java servlets. The original goal of the deployment descriptor in the WAR file was to be able to simultaneously standardize information about the web application needed by the web container in order to deploy it, while at the same time making sure that such deployment information was separate from the source code. Thus, the information could, in theory, be created after all the application code was written possibly by someone other than the developer of the application and someone more familiar with the setup of the web server. But editing the web.xml can be somewhat onerous in part because you are maintaining a global view of all the web components in the web application. This is why the Java Servlet API includes several security annotations that allow developers to annotate a Java servlet with the information needed to define the security model under which it operates. The annotations control the same security model we have already examined. So, they should be easy to pick up.

In order to apply a security constraint to a Java servlet, the starting point is to add an annotation of type @ServletSecurity from the package javax.servlet.annotation to the servlet class. The @ServeletSecurity annotation is the same as a security constraint with a single URL pattern matching the path of the Java servlet in question. The @ServletSecurity allows two attributes that are themselves annotations from the same package. First, @HttpConstraint annotation allows you to define the list of roles allowed to access all of the servlet's HTTP methods by listing the role names in its roles allowed attribute, or to grant access to all authenticated users using ServletSecurity.EmptyRolesSemantic in the value attribute. The attribute, transport guarantee allows you to specify in this annotation the level of data privacy this servlet needs.

Second, the @HttpMethodConstraint annotation has the value attribute, which is the name of one of the standard HTTP methods, GET, POST, and so forth together with the same attributes as the @HttpConstraint element. In this way, the @HttpMethodConstraint annotations allow you to define per HttpMethodConstraints, while the @HttpConstraintAnnotation enables you to define security constraints that apply to all of the HTTP methods of the Java servlet. We summarize the structure of the servlet security annotation in this figure. Programmatic security. When a web application has declared a security model that causes its users to be authenticated, web components can do several interesting things with this information. Within a particular request to web components, it's often useful to know programmatically who is calling, how they authenticated, and in which part of the application defined roles they belong.

Perhaps, you wish to use their identity to pull up and display private information particular to that user. Perhaps you wish to provide different output from your web component, depending on which roles they belong to. Anyone who has peered forward to the meal and entertainment service available to first-class passengers on a plane can probably relate to that idea. Second, it's useful to be able to manage the authentication model explicitly. Perhaps, being able to programmatically initiate an authentication interaction even if the user has not requested a protected resource, or to explicitly log a user out of an application. So, we'll take a look at the APIs available at runtime to web component developers to perform these functions. Understanding the caller. Java represents a user identity using the javax.security.principal class. The principal of the client calling a web component is available to all web components as shown in this table. This is useful information to have at runtime, allowing a range of possibilities for personalizing the output of a web component, based on knowing information about the user and his or her previous interactions. As we have seen, however, web applications often partition their users into roles. This allows applications a simplified view of their users, being able to divide a large number of users into a small set of known roles that can be used to control access as we have already seen. Exposing the knowledge concerning the current user's role allows applications to offer different functionality to different user groups. The source of the defined list of roles for a web application, as we have seen, is defined in the list of security role elements in the web.xml deployment descriptor. The function occurs in a number of places in the Java EE web APIs and is the means by which you can tell whether a caller is in a given role. The following table shows you the locations for each of the web component types. The role name you pass into this method is checked by the Java EE web container against role names that appear in the web.xml.

If you wish to decouple the hard-coded role names from code calling, isUserInRole from the role names that appear in the web.xml, you can take advantage of the security-role-ref syntax in the web.xml to map role references in code to role names in the web.xml deployment descriptor. If the current request is not authenticated ie, there is no user identity associated with the request, then the method returns false. It's often useful to know whether or not the current connection of the current underlying HTTP request or the WebSocket connection that is invoking the web component is encrypted. The method is available to make this determination and the following table summarizes the locations of the API call on the various Java EE web APIs.

Finally, you can determine the authentication scheme used for the HTTP components by means of the string, getAuthenticationSchemeCalls. As you might imagine, it's available on the HttpServletRequest, JSP and JSP request implicit objects, and the JAX-RS security context. HTTP sessions login and log out. Many Java EE web containers use the HttpSession mechanism not only to track a sequence of interactions from the same browser, but also to track authenticated state. Unfortunately, as a Java EE developer, you cannot rely on all containers taking this approach. For example, some web containers may expire the authenticated state of a user while allowing the HttpSession to continue unexpired. Equally, explicitly invalidating an HttpSession using the HttpSession.invalidate call may not log out the user, even if on many Java EE implementations it does. The Java servlet API does allow you to control HttpSession state and authenticated state separately.

However, and most importantly, provides a means to reliably log a user out of an application no matter what the underlying mechanism a web container is using to track the authenticated state. The HttpServletRequest provides three useful methods to explicitly control authenticated state. First and foremost, however, if a user has authenticated calling, it causes that user to be logged out. That is, all authenticated state associated with that user is removed. If the same client calls the web application again and the web component requested is protected, a new authenticated challenge will be issued. Second, some applications that have decided on using a username/password scheme of authentication may wish to further customize the login process more than is allowed by the form login mechanism. Such applications can manage their own authentication process from the gathering of the credentials from the user to the call to a web component, and call the HttpServletRequest API, passing in the user name and password that it gathered from the client. The method returns without exception if the authentication succeeds. Otherwise, the exception is raised. To complete the trio of controls on the authentication mechanism. In the Java EE web container, the method can be called from application code to explicitly cause the Java EE web container to attempt to authenticate the caller based on the mechanism defined in the web application deployment descriptor. This method returns true if and only the authentication succeeds. This can be a useful method to know about if you wish to make decisions on your web component based on the caller's identity. But you do not necessarily want to have to use security constraints to protect the web component just to do so. So, that's it. Hope to see you in our next lesson. Have a nice day.

 

About the Author
Students
1936
Courses
64
Learning Paths
4

OAK Academy is made up of tech experts who have been in the sector for years and years and are deeply rooted in the tech world. They specialize in critical areas like cybersecurity, coding, IT, game development, app monetization, and mobile development.

Covered Topics