Web Application Security: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(19 intermediate revisions by the same user not shown)
Line 63: Line 63:
==<security-constraint>==
==<security-constraint>==


A <security-constraint> tag protects a <web-resource-collection> so that access is granted only for roles in the <auth-constraint>.  
A <security-constraint> tag protects a <web-resource-collection> so that access is granted only for roles in the <auth-constraint>.
 
===Accessing <security-constraint> Metadata from Tomcat===
 
{{Internal|Accessing web.xml Metadata from Tomcat#security-constraint|Accessing <security-constraint> Metadata from Tomcat}}


==<web-resource-collection>==
==<web-resource-collection>==
Line 73: Line 77:
<url-pattern> is relative to the context root.
<url-pattern> is relative to the context root.


For the example above, if we try to access http://localhost:8080/test-servlet/whatever, we are '''not''' challenged for user/password, and allowed access the resource. It is not secured. The container '''does not''' associate any security context with the thread.
For the example above, if we try to access http://localhost:8080/test-servlet/whatever, we are '''not''' challenged for user/password, and allowed access the resource. It is not secured. The container '''does not''' associate any security context with the thread. However, if we access http://localhost:8080/test-servlet/test-secure or http://localhost:8080/test-servlet/test-secure/whatever, we are challenged for credentials, and we are only allowed access if our user has the correct role ('test-role').
 
In JBoss 5.1, the decision on whether a request is authorized or not is taken in <tt>org.jboss.web.tomcat.security.JBossWebRealm</tt>. <font color=red>TODO update for EAP 6.</font>
 
==<http-method>==
 
If no HTTP methods are named in the collection it means that all are protected.
 
==<auth-constraint>==


However, if we access [http://localhost:8080/test-servlet/test-secure] or [http://localhost:8080/test-servlet/test-secure/whatever], we are challenged for credentials, and we are only allowed access if our user has the correct role ('test-role').
===Specifying multiple roles===


In JBoss 5.1, the decision on whether a request is authorized or not is taken in {{org.jboss.web.tomcat.security.JBossWebRealm}}.
If more than one role has to be specified (with the semantics of allowing one role '''or''' another), the syntax is:


!!&lt;http-method&gt;
<pre>
<web-app>
    <security-constraint>
        ...
        <auth-constraint>
            <role-name>RoleOne</role-name>
            <role-name>RoleTwo</role-name>
        </auth-constraint>
    </security-constraint>
</web-app>   
</pre>


If no HTTP methods are named in the collection it means that all are protected.
==<user-data-constraint>, <transport-guarantee>==


<user-data-constraint> specifies the requirements for the transport layer of the client to server connection (NONE | INTEGRAL | CONFIDENTIAL).


Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission.


!!&lt;auth-constraint&gt;
Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit.


!Specifying multiple roles
Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.


If more than one role has to be specified (with the semantics of allowing one role __or__ another), the syntax is:
In practice, Java EE servers treat the CONFIDENTIAL and INTEGRAL transport guarantee values identically, and both mean SSL.


{{{
A working example of a servlet that requests SSL/TSL transport layer security is available here: {{External|https://github.com/NovaOrdis/playground/tree/master/jee/servlet/ssl-servlet}}
      <web-app>
          <security-constraint>
              ...
              <auth-constraint>
                  <role-name>RoleOne</role-name>
                  <role-name>RoleTwo</role-name>
              </auth-constraint>
          </security-constraint>
      </web-app>   
}}}


==<login-config>==


{{External|Specifying an Authentication Mechanism, JEE tutorial http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbn}}
{{External|http://download.oracle.com/javaee/1.4/tutorial/doc/Security5.html}}


!!&lt;user-data-constraint&gt;, &lt;transport-guarantee&gt;
The <login-config> element is used to specify the user authentication method to be used for access to web content, the realm in which the user will be authenticated, and, in the case of form-based login, additional attributes. When specified, the user must be authenticated before access to any resource that is constrained by a security constraint will be granted. <auth-method> specifies the authentication method for the Web application: BASIC, DIGEST, FORM or CLIENT-CERT. The <tt>realm-name</tt> specifies the realm name to use in HTTP BASIC and DIGEST authorization.


{{<__user-data-constraint__>}} specifies the requirements for the transport layer of the client to server connection (NONE | INTEGRAL | CONFIDENTIAL).
===BASIC Authentication===


Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission.
A servlet protected with BASIC authentication: {{External|https://github.com/NovaOrdis/playground/tree/master/jee/servlet/basic-authentication}}


Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit.
=== FORM Authentication===


Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.
Servlets can also perform authentication without relying on HTTP authentication, by using HTTP forms instead:


In practice, Java EE servers treat the CONFIDENTIAL and INTEGRAL transport guarantee values identically, and both mean SSL.
<pre>
....
<login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
          <form-login-page>/loginpage.html</form-login-page>
          <form-error-page>/errorpage.html</form-error-page>
      </form-login-config>
</login-config>
</pre>


The login page must include a form with special values to ensure the proper data is submitted to the server. The form must be a POST to the URL <tt>j_security_check</tt> with a username sent as <tt>j_username</tt> and a password sent as <tt>j_password</tt>.


!!&lt;login-config&gt;
===Custom auth-method===


<font color=red>TODO:


|Specifying an Authentication Mechanism, JEE tutorial [http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbn]
Custom auth-method And Tomcat Authenticator Valve https://home.feodorov.com:9443/wiki/Wiki.jsp?page=CustomAuthMethodAndTomcatAuthenticatorValve
|[http://download.oracle.com/javaee/1.4/tutorial/doc/Security5.html]


The {{__&lt;login-config&gt;__}} element is used to specify the user authentication method to be used for access to web content, the realm in which the user will be authenticated, and, in the case of form-based login, additional attributes. When specified, the user must be authenticated before access to any resource that is constrained by a security constraint will be granted. {{<__auth-method__>}} specifies the authentication method for the Web application: BASIC, DIGEST, FORM or CLIENT-CERT. The {{realm-name}} specifies the realm name to use in HTTP BASIC and DIGEST authorization.
</font>


__Form-Based Authentication__. Servlets can also perform authentication without relying on HTTP authentication, by using HTTP forms instead:
===Accessing <login-config> Metadata from Tomcat===


{{{
{{Internal|Accessing web.xml Metadata from Tomcat#login-config|Accessing <login-config> Metadata from Tomcat}}
    ....
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/loginpage.html</form-login-page>
            <form-error-page>/errorpage.html</form-error-page>
        </form-login-config>
    </login-config>
}}}


The login page must include a form with special values to ensure the proper data is submitted to the server. The form must be a POST to the URL {{j_security_check}} with a username sent as {{j_username}} and a password sent as {{j_password}}.
=Application Server-Specific Configuration=


!Custom {{auth-method}}
<font color=red>TODO


|See [Custom auth-method And Tomcat Authenticator Valve|CustomAuthMethodAndTomcatAuthenticatorValve]
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=JbossWebXml
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=JbossWebXml


</font>


!!!Conversation between Browser and Server for Authenticated Content
=Conversation between Browser and Server for Authenticated Content=


!! Sequence of Calls for BASIC Authentication
==Sequence of Calls for BASIC Authentication==


* Unauthenticated request reaches {{BasicAuthenticator.invoke()}}.
* Unauthenticated request reaches <tt>BasicAuthenticator.invoke()</tt>.
* The valve looks up the {{Realm}} into the associated {{Context}} and gets a {{JBossWebRealm}} instance.
* The valve looks up the <tt>Realm</tt> into the associated <tt>Context</tt> and gets a <tt>JBossWebRealm</tt> instance.
* The valve gets the {{SecurityConstraint[[]}} from the {{JBossWebRealm}} instance.
* The valve gets the <tt>SecurityConstraint[[]</tt> from the <tt>JBossWebRealm</tt> instance.
* The valve makes sure that security constrained resources are not cached:
* The valve makes sure that security constrained resources are not cached:
{{{
<pre>
                 response.setHeader("Pragma", "No-cache");
                 response.setHeader("Pragma", "No-cache");
                 response.setHeader("Cache-Control", "no-cache");
                 response.setHeader("Cache-Control", "no-cache");
                 ...
                 ...
                 response.setHeader("Expires", DATE_ONE);
                 response.setHeader("Expires", DATE_ONE);
}}}
</pre>
* {{BasicAuthenticator.authenticate(...)}} gets invoked.
 
* <tt>BasicAuthenticator.authenticate(...)</tt> gets invoked.
* This one sends an "unauthorized" response (401) and an appropriate challenge ("WWW-Authenticate Basic realm="My Realm"").
* This one sends an "unauthorized" response (401) and an appropriate challenge ("WWW-Authenticate Basic realm="My Realm"").
* The browser challenges the user for username/password and inserts an "authorization" MIME header with the Base64 encoded "&lt;username&gt;:&lt;password&gt;" pair (value similar to "Basic YWxpY2U6YWxpY2UxMjM=")
* The browser challenges the user for username/password and inserts an "authorization" MIME header with the Base64 encoded "<username>:<password>" pair (value similar to "Basic YWxpY2U6YWxpY2UxMjM=")
* Request intercepted again by the BasicAuthenticator, which extracts the "authorization" MIME header and from it the user name and the password.
* Request intercepted again by the BasicAuthenticator, which extracts the "authorization" MIME header and from it the user name and the password.
* The valve calls the {{JBossWebRealm}}'s {{authenticate(username, password)}}.
* The valve calls the <tt>JBossWebRealm</tt>'s <tt>authenticate(username, password)</tt>.


For the theory behind this, see:
For the theory behind this, see:


|[HTTP Basic Authentication Protocol|HTTPBasicAuthentication#Protocol]
<font color=red>


!! Sequence of Calls for FORM Authentication
TODO:


HTTP Basic Authentication Protocol https://home.feodorov.com:9443/wiki/Wiki.jsp?page=HTTPBasicAuthentication#Protocol
</font>
==Sequence of Calls for FORM Authentication==


''Valid for EAP 6.3.0''.
''Valid for EAP 6.3.0''.


 
* Unauthenticated request reaches <tt>FormAuthenticator.invoke()</tt>.
* Unauthenticated request reaches {{FormAuthenticator.invoke()}}.


* If there are no security constraints for this request - let it go through.
* If there are no security constraints for this request - let it go through.
Line 182: Line 208:
* Determine whether authentication is required based on the security constraint identified for request.
* Determine whether authentication is required based on the security constraint identified for request.


* Perform {{FormAuthenticator.authenticate(...)}}.
* Perform <tt>FormAuthenticator.authenticate(...)</tt>.




* If we're already authenticated ({{request.getUserPrincipal()}} is not {{null}}), return true.  
* If we're already authenticated (<tt>request.getUserPrincipal()</tt> is not null, return true.  


* If the request is not a request for the login page (ends in /j_security_check), save the request and forward it to the login page {{FormAuthenticator.forwardToLoginPage()}}.
* If the request is not a request for the login page (ends in /j_security_check), save the request and forward it to the login page <tt>FormAuthenticator.forwardToLoginPage()</tt>.


* <font color=red>Continue here ... </font>
* <font color=red>Continue here ... </font>


=Example of Selectively Protecting Different Resources for Access By Different Roles=
<font color=red>
TODO
Example of Selectively Protecting Different Resources for Access By Different Roles    https://home.feodorov.com:9443/wiki/Wiki.jsp?page=web.xml-example1
</font>
<font color=red>


Process:




* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=HTTPAuthentication
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=HTTPBasicAuthentication
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=JBossSecurity
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=WebXml


!!!Example of Selectively Protecting Different Resources for Access By Different Roles
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=JBossWebSecurityImplementationDiagram
* https://home.feodorov.com:9443/wiki/Wiki.jsp?page=CustomAuthMethodAndTomcatAuthenticatorValve


|[Example of Selectively Protecting Different Resources for Access By Different Roles|web.xml-example1]




!!!Internal


|[HTTP Authentication]
</font>
|[JBoss Security]
|[web.xml|WebXml]
|[jboss-web.xml|JbossWebXml]
|[JBoss Web Security Implementation Diagram|JBossWebSecurityImplementationDiagram]
|[Custom auth-method And Tomcat Authenticator Valve|CustomAuthMethodAndTomcatAuthenticatorValve]

Latest revision as of 15:13, 16 March 2017

External

Internal

Overview

Security of a web application is based on the concept of role. For more on roles, see https://home.feodorov.com:9443/wiki/Wiki.jsp?page=J2EESecurity. Role-based access is defined relative to URL patterns. Protected content is declared using the web.xml <security-constraint> element.

The example below represents a typical declarative security configuration. Assuming that the servlet is mapped to "/*" relative to the context root - which by default is the name of the servlet WAR ("test-servlet") or the value of the context-root element from application.xml - and we want to secure all content that is mappend under "test-secure" and "test/secure/2" sub-paths, the configuration is:

<web-app>

    <servlet>
        ...
    </servlet>

    <servlet-mapping>
        <servlet-name>...</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secure Content</web-resource-name>
            <url-pattern>/test-secure/*</url-pattern>
            <url-pattern>/test/secure/2/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>test-role</role-name>
        </auth-constraint>
        <user-data-constraint>
            <!-- 
                  Values: NONE, INTEGRAL, CONFIDENTIAL 
            -->
            <transport-guarantee>NONE</transport-guarantee> 
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <!-- 
               Values: BASIC, DIGEST, FORM, CLIENT-CERT 
        -->
        <auth-method>BASIC</auth-method> 
        <realm-name>Test Authentication Realm</realm-name> <!-- optional, only useful for BASIC, DIGEST -->
    </login-config>

    <security-role>
        <role-name>test-role</role-name>
    </security-role>
</web-app>

Configuration Elements

<security-constraint>

A <security-constraint> tag protects a <web-resource-collection> so that access is granted only for roles in the <auth-constraint>.

Accessing <security-constraint> Metadata from Tomcat

Accessing <security-constraint> Metadata from Tomcat

<web-resource-collection>

Each <web-resource-collection> contains a name, any number of URL patterns specifying the URLs to protect, and any number of HTTP methods for which access should be restricted. For URL patterns you can use wildcards. If no <http-method> is specified, then all methods are protected.

<url-pattern>

<url-pattern> is relative to the context root.

For the example above, if we try to access http://localhost:8080/test-servlet/whatever, we are not challenged for user/password, and allowed access the resource. It is not secured. The container does not associate any security context with the thread. However, if we access http://localhost:8080/test-servlet/test-secure or http://localhost:8080/test-servlet/test-secure/whatever, we are challenged for credentials, and we are only allowed access if our user has the correct role ('test-role').

In JBoss 5.1, the decision on whether a request is authorized or not is taken in org.jboss.web.tomcat.security.JBossWebRealm. TODO update for EAP 6.

<http-method>

If no HTTP methods are named in the collection it means that all are protected.

<auth-constraint>

Specifying multiple roles

If more than one role has to be specified (with the semantics of allowing one role or another), the syntax is:

<web-app>
    <security-constraint>
        ...
        <auth-constraint>
            <role-name>RoleOne</role-name>
            <role-name>RoleTwo</role-name>
        </auth-constraint>
    </security-constraint>
</web-app>    

<user-data-constraint>, <transport-guarantee>

<user-data-constraint> specifies the requirements for the transport layer of the client to server connection (NONE | INTEGRAL | CONFIDENTIAL).

Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission.

Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit.

Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.

In practice, Java EE servers treat the CONFIDENTIAL and INTEGRAL transport guarantee values identically, and both mean SSL.

A working example of a servlet that requests SSL/TSL transport layer security is available here:

https://github.com/NovaOrdis/playground/tree/master/jee/servlet/ssl-servlet

<login-config>

Specifying an Authentication Mechanism, JEE tutorial http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbn
http://download.oracle.com/javaee/1.4/tutorial/doc/Security5.html

The <login-config> element is used to specify the user authentication method to be used for access to web content, the realm in which the user will be authenticated, and, in the case of form-based login, additional attributes. When specified, the user must be authenticated before access to any resource that is constrained by a security constraint will be granted. <auth-method> specifies the authentication method for the Web application: BASIC, DIGEST, FORM or CLIENT-CERT. The realm-name specifies the realm name to use in HTTP BASIC and DIGEST authorization.

BASIC Authentication

A servlet protected with BASIC authentication:

https://github.com/NovaOrdis/playground/tree/master/jee/servlet/basic-authentication

FORM Authentication

Servlets can also perform authentication without relying on HTTP authentication, by using HTTP forms instead:

....
<login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
          <form-login-page>/loginpage.html</form-login-page>
          <form-error-page>/errorpage.html</form-error-page>
      </form-login-config>
</login-config>

The login page must include a form with special values to ensure the proper data is submitted to the server. The form must be a POST to the URL j_security_check with a username sent as j_username and a password sent as j_password.

Custom auth-method

TODO:

Custom auth-method And Tomcat Authenticator Valve https://home.feodorov.com:9443/wiki/Wiki.jsp?page=CustomAuthMethodAndTomcatAuthenticatorValve

Accessing <login-config> Metadata from Tomcat

Accessing <login-config> Metadata from Tomcat

Application Server-Specific Configuration

TODO

Conversation between Browser and Server for Authenticated Content

Sequence of Calls for BASIC Authentication

  • Unauthenticated request reaches BasicAuthenticator.invoke().
  • The valve looks up the Realm into the associated Context and gets a JBossWebRealm instance.
  • The valve gets the SecurityConstraint[[] from the JBossWebRealm instance.
  • The valve makes sure that security constrained resources are not cached:
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "no-cache");
                ...
                response.setHeader("Expires", DATE_ONE);
  • BasicAuthenticator.authenticate(...) gets invoked.
  • This one sends an "unauthorized" response (401) and an appropriate challenge ("WWW-Authenticate Basic realm="My Realm"").
  • The browser challenges the user for username/password and inserts an "authorization" MIME header with the Base64 encoded "<username>:<password>" pair (value similar to "Basic YWxpY2U6YWxpY2UxMjM=")
  • Request intercepted again by the BasicAuthenticator, which extracts the "authorization" MIME header and from it the user name and the password.
  • The valve calls the JBossWebRealm's authenticate(username, password).

For the theory behind this, see:

TODO:


HTTP Basic Authentication Protocol https://home.feodorov.com:9443/wiki/Wiki.jsp?page=HTTPBasicAuthentication#Protocol

Sequence of Calls for FORM Authentication

Valid for EAP 6.3.0.

  • Unauthenticated request reaches FormAuthenticator.invoke().
  • If there are no security constraints for this request - let it go through.
  • Determine whether authentication is required based on the security constraint identified for request.
  • Perform FormAuthenticator.authenticate(...).


  • If we're already authenticated (request.getUserPrincipal() is not null, return true.
  • If the request is not a request for the login page (ends in /j_security_check), save the request and forward it to the login page FormAuthenticator.forwardToLoginPage().
  • Continue here ...

Example of Selectively Protecting Different Resources for Access By Different Roles

TODO

Example of Selectively Protecting Different Resources for Access By Different Roles https://home.feodorov.com:9443/wiki/Wiki.jsp?page=web.xml-example1


Process: