Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples

Java vs. .NET Security, Part 4
User Authentication and Authorization

by Denis Piliptchouk




User Authentication: General



Related Reading

Programming .NET Security
By Adam Freeman, Allen Jones







User Authentication: Identities



WindowsPrincipal principal = 
WindowsIdentity identity = 




public final class Subject {
    public Set getPublicCredentials(); //not security-checked
    public Set getPrivateCredentials(); // security-checked
    public Set getPrincipals();


ASP.NET applications have several options for storing user credentials:




<sessionState timeout="20"/>





User Authentication: Web Mechanisms

There is a standard set of web-based authentication methods that may reasonably be expected by application developers on a particular platform. Generally supported authentication mechanisms include HTTP authentication (basic and digest), forms/cookies authentication, and certificate authentication. The latter is usually coupled with mutual SSL/TLS authentication -- this is the standard way of implementing it.

Forms authentication is normally performed with the help of a cookies mechanism. Two types of cookies are in use: temporary and persistent. The former last only during the current browser session, and the latter are stored at the client's computer. Both types have an expiration time, to prevent identity theft, but persistent cookies are typically stored on the client's computer and remain valid for many days, so they pose a greater security threat.

Certificate authentication is significantly more secure, as it allows mutual authentication, so the client can be assured that it connects to the proper server. Configuring it, however, is more problematic, because it requires installing an X509 certificate on the client side.

ASP.NET heavily relies on IIS for its authentication needs. In fact, it uses ISS to implement all of the above authentication modes, except for forms, and merely consumes the results of the authentication process performed by IIS. Therefore, forms authentication is the only one that is going to be further discussed here for ASP.NET.

Authentication is handled by FormsAuthenticationModule, which handles all traffic received from IIS via the extensions mechanism, as shown in Figure 1. It passes all authenticated requests through, while forwarding all unauthenticated ones to the specified logon page. The authentication, once performed, is sustained via the cookie mechanism, which can be made to expire after a timeout to prevent user identity theft. Alternatively, another form-authentication scheme can be developed; for example, using hidden fields to store credentials in the form, and taking full control of authentication process by providing a FormsAuthentication_OnAuthenticate handler event in the Global.asax file. It is possible (although not trivial) to create a completely cookieless authentication schema using this method.

Figure 1
Figure 1. ASP.NET Forms Authentication

ASP.NET provides a helper class, FormsAuthentication, to help with common authentication tasks: authenticating username and password; issuing, encrypting, and decrypting tickets; redirecting a user request to the originally requested page after successful authentication; and signing out. An authenticated user is identified by the presence of an authentication cookie (either temporary or persistent), which is usually implemented by the FormsAuthenticationTicket class. However, a custom cookie may be set in the code -- this allows better control over its expiration property, as well as over the cookie's content.

string data = "Application data";

HttpCookie cookie = new HttpCookie(

    FormsAuthentication.FormsCookieName, data);

//expires in 10 minutes

cookie.Expires = DateTime.Now + new TimeSpan(0,0,10,0);


Custom content in a cookie may be protected by encrypting, via the FormsAuthentication.Encrypt call, with a user-provided or auto-generated 3DES key, which is then stored at the server's Local Security Authority (LSA). HMAC validation with a specified algorithm may also be requested.

<machineKey validationKey="AutoGenerate" 



The associated authentication cookie's name and expiration timeout may be configured in the top-level application's web.config file. Cookies are renewed upon the next request after half of their expiration time has passed, thus keeping them from expiring. However, as was explained earlier, the server-side session associated with the user's identity expires after a certain period of inactivity, as determined by the timeout setting in the sessionState element. So, even if a request has a valid cookie, if the corresponding session has expired, the user will still be prompted to re-authenticate. Calling FormsAuthentication.SignOut will terminate any session association of the current user and remove cookies from the browser's cache.

<authentication mode="Forms">
  <forms forms="DemoApp" 
         protection="All" Timeout="30" Path="/">

The authentication sequence works in the following way: after a request comes in, it is forwarded to the OnAuthenticate handler, if present. Here, any additional information may be extracted from the custom cookie or URL, and additional roles assigned. If a user identity is associated with the request after the finishing handler's execution, no further actions are taken. Otherwise, the request is checked by name for the presence of authentication cookie. If such a cookie is found, it is used to construct the appropriate Principal and associate it with the current request; otherwise, the request is forwarded to the logon page.

The Java servlet specification requires support for the basic HTTP authorization mechanism, and encourages (but does not require!) support for digest authentication, because it is a fairly rare mechanism. Additionally, two other forms of authentication are required for J2EE compatibility: form-based and mutual certificate (HTTPS client). Basic, digest, and certificate authentication are carried out transparently, between the web server and the connecting client, and do not require writing additional code.


The form-based authentication schema is probably the most common option in use today. The specifications require the presence of the following names on the logon form: a j_security_check action, and the fields j_username and j_password. These indicate to the servlet engine that this is the logon information to process.


A container creates a persistent or temporary cookie named JSESSIONID for the user request, sets its expiration policy via a call to Cookie.setMaxAge before adding the cookie to the current session, and then keeps sending it back to the client with each response. The client returns it with each request, which allows mapping the connectionless requests to the user's session. Alternatively, a container may use a technique called URL Rewriting to support those clients that do not accept cookies:


Note that using a GET operation in form-based login is a bad idea -- it puts the entire request, with all of its fields, into the URL, thus making it available when browsing the server log. For instance:


Using the POST operation, the URL will be as shown below, so the user information will not show up in the server's log:


When a request comes for one of the protected resources, the engine checks the user's authentication, and if he is has not been authenticated yet, forwards him to the login page associated with the resource. The servlet engine is then responsible for redirecting the user back to the originally requested resource (or error page, in case of a failure).


Certificate authentication is configured declaratively on the server side, but support for mutual HTTPS communication is required on both sides. The client's request should contain a certificate that can be mapped to a server's defined principal, which is going to be associated with this and further requests. Note that HTTPS, as opposed to HTTP, is a stateful protocol, and cookies are not needed to maintain session association.


From inside of a servlet, client certificate information can be retrieved by accessing the getAttribute method of the javax.servlet.http.HttpServletRequest class, requesting the following attribute:

X509Certificate cert = 

In the case of a HTTPS connection, the servlet engine sets this attribute, as required by the servlet specifications, before invoking the target servlet. Using attributes of the returned X509Certificate object, the servlet can perform any additional programmatic authentication of the caller.

Note: .NET delegates all types of user authentication (except for forms) to IIS, and barely consumes the results. J2EE requires support for all standard authentication mechanisms from the compliant servers.

User Authentication: Other Mechanisms

Besides the standard web-based mechanisms, both platforms provide other means for authentication.

In .NET, Windows and Passport authentication are incorporated as separate entities via the corresponding modules. They both are used together with IIS, and require very little configuration in the application's configuration file.

WindowsAuthenticationModule relies on IIS to authenticate the caller, as shown in Figure 2, and attaches WindowsPrincipal object to the application context. This is the default provider for ASP.NET, and the easiest to use in pure Microsoft network environment, as it requires no additional application code.

<authentication mode="Windows">

Figure 2
Figure 2. ASP.NET Windows Authentication

PassportAuthenticationModule is a wrapper around the Passport SDK that creates a PassportIdentity object using Passport service and profile, as shown in Figure 3. This identity object provides access to the Passport profile and allows the encrypting/decrypting of authentication tickets. Most of the authentication details are handled by the ASP.NET framework; the developer can control the process by overloading the OnAuthentication handler.

<authentication mode="Passport">


Figure 3
Figure 3. ASP.NET Passport Authentication

In Java, JAAS serves as a general abstraction for providing authentication services to applications. JAAS relies on Pluggable Authentication Modules (PAM) in its operation to provide a flexible authentication framework. Administrators can add various implementations to the environment and modify its behavior and authentication method. The default PAM is username/password based; however, it is possible to use alternative schemas. In JDK 1.4, Sun provides implementations for the following login schemas via its LoginModule implementations: UnixLoginModule, NTLoginModule, JNDILoginModule, KeyStoreLoginModule, and Krb5LoginModule. Additionally, there exist implementations of SmartCard login modules by independent vendors; for instance, GemPlus.

A sample Java application, which demonstrates some of the discussed JAAS authentication techniques, can be found here.

In this section, only the authentication part of JAAS will be reviewed. Its operation is controlled by the LoginContext, which uses the Configuration class to retrieve the specified LoginModules. Those modules retrieve credentials with the help of provided Callbacks, although it is possible to use other means as well. There might be several LoginModules configured, and during the login process all of them are queried in turn, which is shown in Figure 4.

Figure 4
Figure 4. JAAS Login

The relationship among LoginModules is determined by the strategy configuration settings, which tells the system how to treat login failures in individual modules:

JAAS introduces a couple of new permissions, javax.security.auth.PrivateCredentialPermission and javax.security.auth.AuthPermission, to guard access to the Subject, LoginContext, and Configuration classes. The code that works with JAAS classes will need to have them (especially AuthPermission) granted in java.policy. See the online Javadoc for details about their usage.

The following classes are used as part of JAAS authentication process:

Different user identities and roles are represented via Principals, added to the resulting Subject by the configured LoginModules during the commit phase, and removed during logout. Their credentials may also be added to that object, as well as any additional identification information.

public abstract class DemoLoginModule implements LoginModule {
  protected Subject m_subject;
  protected ArrayList m_principals = null;
  public boolean commit() throws LoginException {
    // Login succeeded, 
    // add demo Principals to the Subject.
    if (!(m_subject.getPrincipals().containsAll(
                                m_principals))) {
    return ret;
  public boolean logout() throws LoginException {
    // Need to remove our 
    // principals from the Subject.
    if (null != m_principals) {
      m_principals = null;
    return true;

The interaction of the various JAAS classes during initialization process is shown in Figure 5 below.

Figure 5
Figure 5. JAAS Initialization

Note: JAAS provides a flexible and versatile mechanism for adding authentication to any type of Java application.

User Authentication: Impersonation



Sample ASP.NET configurations are listed below.


// Impersonating a logged-in Windows user
WindowsIdentity id = 
        new WindowsIdentity(userTokenHandle);
WindowsImpersonationContext ctxt = 




public final class Subject { 
  // associate the subject with the current 
  // AccessControlContext and 
  // execute the Privileged action 
  public static Object doAs(Subject s,
       java.security.PrivilegedAction action);


//class representing a protected operation
class ProtectedOperation 
                 implements PrivilegedAction {
  //do something veeeery sensitive here...
  public Object run();

public class ImpersonationExample {
  public static void main(String args[]) {
    //carry out the authentication process
    Subject subject = loginContext.getSubject();
    //run as the impersonated user
                 new ProtectedOperation());



Figure 6
Figure 6. GSS/JAAS Authentication


// client JAAS configuration for GSS-API
com.sun.security.jgss.initiate {

// server JAAS configuration for GSS-API
com.sun.security.jgss.accept {
                  useKeyTab=true storeKey=true 

// default configuration for GSS-API 
// if the above is not present
other {


User Access Security: Basic



WindowsPrincipal principal = 
  (WindowsPrincipal) Thread.CurrentPrincipal;
WindowsIdentity identity = 




GenericIdentity id = new GenericIdentity("user");
GenericPrincipal pr = new GenericPrincipal(
Thread.CurrentPrincipal = pr;


    SecurityAction.Demand, Role = "PowerUser")]


PrincipalPermission perm1 = 
   new PrincipalPermission("John","Admin");
PrincipalPermission perm2 = 
   new PrincipalPermission("PowerUser");


Principal principal = Thread.CurrentPrincipal;
if (principal.IsInRole("Admin"))
  //do something for Admin
} else if (principal.Identity.Name == "John")
  //do something for John




grant Signedby "MyPublisher" {
	permission java.io.FilePermission "c:\","read";

//an example of grant by username
grant Principal com.comp.PrincipalClass "user" {
	permission java.io.FilePermission "c:\","write";


This application demonstrates the effects of dynamic policy evaluation in JAAS.


// an example of role-based entry
grant Principal com.MySite.AppRole "PowerUser" {
  permission java.io.FilePermission "c:\","read";

// this class is used for building role hierarchy
public class AppRole implements 
                      PrincipalComparator {
  // the role this object represents
  public AppRole(String role) {...}

  //this method checks the Subject 
  //for being in the role
  public boolean implies(Subject currSubject) {


AccessControlContext ctxt = 
Subject subj = Subject.getContext(ctxt);
if (subj == null) {
  //no authenticated user
} else {
  Set principalsSet = subj.getPrincipals();
  Iterator iter = principalsSet.iterator();
  while(iter.hasNext()) {
    MyPrincipalClass princ = 
      // have an authenticated user


User Access Security: Extended

In addition to the basic facilities for user access checks, extension packages on both platforms define their own mechanisms.

ASP.NET provides security checks, which work on the top of regular CLR security facilities:

Java servlets and JSPs use role-based access control checks, which can be specified programmatically or declaratively, similar to ASP.NET. The mapping between authenticated users and security roles is not specified; it happens in a vendor-specific way. However, the servlet specification does standardize ACL declarations by security roles in the web.xml deployment descriptor, which can protect web resources defined as HTTP methods applied to URL-patterns. Also, the transport-guarantee element is considered during requests evaluation. A side effect of this approach is that the resulting declarative access control mechanism is rather coarse, on the file/operation level:

    <web-resource-name>Restricted Servlets
    <http-method>POST</http-method >
    <http-method>GET</http-method >

Violation of the auth constraint will result in either the HTTP 401 (if unauthenticated) or HTTP 403 (if authenticated, but ACL-rejected) status code being returned to the caller. For cases of anonymous web users, the web application's deployment descriptor may contain a <run-as> element, which will specify the identity that will be used to process the request. If it is specified, the servlet container is required to propagate this security identity in calls to the EJB layer, whether in the same or in a different J2EE application, as was explained in the Identities section.

Principal checks may be performed imperatively, using one of the methods exposed by HttpServletRequest: getUserPrincipal, getRemoteUser, or isUserInRole. They can be used to provide finer-grained checks than declarative security allows for:

public void doGet(HttpServletRequest request, 
         HttpServletResponse response) {
  java.security.Principal principal = 
  String user = request.getRemoteUser();
  if (user != null) {
    //have an authenticated user, check his name

  if (request.isUserInRole("owner")) {
    //owner of the account

EJB role-based security is similar to that of servlets, and can be declarative or programmatic. However, the declarative variant is finer-grained, as it allows access control up to the methods level. Mapping of principals to roles is vendor-specific, but the EJB specification dictates role-based ACL format in the bean deployment descriptor, with * as a wildcard for all permissions:

    <description>Role description</description>


Using the <unchecked> element in the bean's descriptor will bypass any authorization, even if the <role-name> element is also specified.

Some methods may even be excluded from being called at deployment time by specifying an exclude list. This list provides a directive from the application assembler to the deployer that these methods should be configured to deny any access:


Alternatively, the principal's attributes can be accessed from the bean's code, using methods exposed by the EJBContext class. Note that those methods may be invoked only in the EJB business methods with security context present -- otherwise, a java.land.IllegalStateException will be thrown. Also, both the getCallerPrincipal and isCallerInRole methods from EJBContext always operate on the caller identity, even if the <run-as> attribute was specified.

public class UserAccessBean 
                 implements SessionBean {
  EJBContext beanContext;

  public void getUserInfo() {
    java.security.Principal principal = 
    if (beanContext.isCallerInRole("UserRole")) {
      //authenticated user 

Note: For extended access checks, both systems provide an adequate level of declarative support.


This article addressed the user authentication and authorization features of the Java and .NET platforms. .NET suffers from tight integration with IIS, without which it is not really capable of performing authentication. In terms of access control, it does provide a convenient mechanism that meshes nicely with its CAS features. Java, in addition to the standard authentication types, offers the powerful JAAS mechanism as its primary vehicle for adding authentication and Principal-based authorization to Java applications, which adds a lot of flexibility to the design choices.

Overall, .NET and Java both earned pretty high marks on the security comparison, which should not be too surprising, considering the long history of Java in the enterprise and the amount of effort that Microsoft is putting into making .NET a premier Windows development platform. Traditionally (and .NET is not an exception), Microsoft products have done best in the closed, homogeneous environment of all-Windows networks, while enterprise Java performs quite well in heterogeneous environments. If we consider an all-Microsoft network, it allows system integration and utilization of .NET's security features to their fullest potential. In case of a mixed environment, Java's platform-independent security features may be more useful than those of .NET. Also, when issues like communication security and authentication across networks start coming into play, Java seems to be a good choice.

Demo Applications



Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.