Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Jetty/Tutorial/JAAS"

m
m
Line 396: Line 396:
 
     }
 
     }
 
</source>
 
</source>
| category = [[Category:Jetty Tutorial]]
+
 
}}
+
 
  
  
Line 403: Line 403:
  
 
<references />
 
<references />
 +
| category = [[Category:Jetty Tutorial]]
 +
}}

Revision as of 15:08, 23 March 2011

{{Jetty Tutorial | introduction =

Using JAAS with Jetty is a matter of completing the following tasks:

#Configuring a JAASLoginService

#Declaring an org.eclipse.jetty.plus.jaas.JAASLoginService

#Creating a JAAS login module configuration file

#Specifying the JAAS login module configuration file on the Jetty run line


| details = The following sections explain how to configure Jetty with JAAS:

Configuring a JAASLoginService

Configure a Jetty org.eclipse.jetty.plus.jaas.JAASLoginService to match the realm-name in your web.xml file. For example, if the web.xml contains a realm called "xyzrealm":

<login-config>
  <auth-method>FORM</auth-method>
  <realm-name>xyzrealm</realm-name>
  <form-login-config>
    <form-login-page>/login/login</form-login-page>
    <form-error-page>/login/error</form-error-page>
  </form-login-config>
</login-config>

Declaring an org.eclipse.jetty.plus.jaas.JAASLoginService

Next declare the following JAASLoginService in a Jetty configuration file:

    <Call name="addBean">
      <Arg>
          <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
           <Set name="Name">Test JAAS Realm</Set>
           <Set name="LoginModuleName">xyz</Set>
          </New>
      </Arg>
    </Call>

Alternatively, of course, you can set this up in a context XML file that configures a web app:

  <Set name="securityHandler">
    <New class="org.eclipse.jetty.security.ConstraintSecurityHandler">
     <Set name="loginService">
       <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
         <Set name="name">Test JAAS Realm</Set>
         <Set name="loginModuleName">xyz</Set>
       </New>
     </Set>
    </New>
  </Set>
Warning2.png
It is imperative that the realm-name element in web.xml file is exactly the same as the value of the name property of the JAASLoginService instance.


Creating a JAAS login module configuration file

Set up your LoginModule in a configuration file, following the syntax rules:

xyz {
       com.acme.SomeLoginModule required debug=true;
    };
Warning2.png
It is imperative that the application name to the left of the opening brace is exactly the same as the value of the LoginModuleName property specified above.


Specifying the JAAS login module configuration file on the Jetty run line

Invoke Jetty with the JAAS configuration file you created above:

> java -Djava.security.auth.login.config=mylogin.conf -jar start.jar etc/myjetty.xml

Fine Tuning the JAASLoginService

To allow the greatest degree of flexibility in using JAAS with web applications, the JAASLoginService supports additional configuration options. You don't ordinarily need to set these explicitly, as Jetty has defaults which work in 99% of cases. However, should you need to, you can configure:

  • A policy for role-based authorization (Default: org.eclipse.jetty.plus.jaas.StrictRoleCheckPolicy).
  • A CallbackHandler (Default: org.eclipse.jetty.plus.jaas.callback.DefaultCallbackHandler).
  • A list of classnames for the Principal implementation that equate to a user role (Default: org.eclipse.jetty.plus.jaas.JAASRole).

Here's an example that sets each of these (to their default values):

<New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
  <Set name="Name">xyzrealm</Set>
  <Set name="LoginModuleName">xyz</Set>
  <Set name="RoleCheckPolicy">
    <New class="org.eclipse.jetty.plus.jaas.StrictRoleCheckPolicy"/>
  </Set>
  <Set name="CallbackHandlerClass">
    org.eclipse.jetty.plus.jaas.callback.DefaultCallbackHandler
  </Set>
  <Set name="roleClassNames">
    <Array type="java.lang.String">
      <Item>org.eclipse.jetty.plus.jaas.JAASRole</Item>
    </Array>
  </Set>
</New>

Understanding the RoleCheckPolicy

The RoleCheckPolicy must be an implementation of the org.eclipse.jetty.plus.jaas.RoleCheckPolicy interface, and its purpose is to help answer the question "is User X in Role Y?" for role-based authorization requests. The default implementation distributed with Jetty is the org.eclipse.jetty.plus.jaas.StrictRoleCheckPolicy, which assesses a user as having a particular role if that role is at the top of the stack of roles that have been temporarily pushed onto the user, or if the user has no temporarily assigned roles, the role is among those configured for the user.

You can temporarily assign roles to a user programmatically by using the pushRole(String rolename) method of the org.eclipse.jetty.plus.jaas.JAASUserPrincipal class.

For the majority of webapps, the default StrictRoleCheckPolicy is adequate, but you can provide your own implementation and set it on your tt>JAASLoginService</tt> instance.

Using the CallbackHandler

A CallbackHandler is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.

Jetty ships with the org.eclipse.jetty.plus.jaas.DefaultCallbackHandler which interfaces the information contained in the request to the Callbacks that LoginModules requests. You can replace this default with your own implementation if you have specific requirements not covered by the default.

Configuring a Role Principal Implementation Class

When LoginModules authenticate a user, they usually also gather all of the roles that a user has and place them inside the JAAS Subject. As LoginModules are free to use their own implementation of the JAAS Principal to put into the Subject, Jetty needs to know which Principals represent the user and which represent his/her roles when performing authorization checks on security-constraints. The example LoginModules that ship with jetty all use the org.mortbay.jetty.plus.jaas.JAASRole class. However, if you have plugged in some other LoginModules, you must configure the classnames of their role Principal implementations.

Examining Sample Login Modules

At the time of writing, Jetty provides four sample LoginModule implementations:

  • org.eclipse.jetty.plus.jaas.spi.JDBCLoginModule
  • org.eclipse.jetty.plus.jaas.spi.PropertyFileLoginModule
  • org.eclipse.jetty.plus.jaas.spi.DataSourceLoginModule
  • org.eclipse.jetty.plus.jaas.ldap.LdapLoginModule

We'll take a look at all of these, but first, a word about password handling in Jetty, as it applies to all LoginModules.

Understanding Passwords/Credentials

Passwords can be stored in clear text, obfuscated or checksummed. Use the class org.eclipse.jetty.http.security.Password to generate all varieties of passwords, the output from which you can cut and paste into property files or enter into database tables.

> java -cp lib/jetty.jar org.eclipse.jetty.http.security.Password
Usage - java org.eclipse.jetty.http.security.Password [<user>] <password>
> java -cp lib/jetty.jar org.eclipse.jetty.http.security.Password me you
you
OBF:20771x1b206z
MD5:639bae9ac6b3e1a84cebb7b403297b79
CRYPT:me/ks90E221EY

Read more on securing passwords.

JDBCLoginModule

The JDBCLoginModule stores user passwords and roles in a database that is accessed via JDBC calls. You can configure the JDBC connection information, as well as the names of the table and columns storing the username and credential, and the name of the table and columns storing the roles.

Here is an example login module configuration file entry for it using an HSQLDB driver:

jdbc {
         org.eclipse.jetty.plus.jaas.spi.JDBCLoginModule required
         debug="true"
         dbUrl="jdbc:hsqldb:."
         dbUserName="sa"
         dbDriver="org.hsqldb.jdbcDriver"
         userTable="myusers"
         userField="myuser"
         credentialField="mypassword"
         userRoleTable="myuserroles"
         userRoleUserField="myuser"
         userRoleRoleField="myrole";
     };

There is no particular schema required for the database tables storing the authentication and role information. The properties userTable, userField, credentialField, userRoleTable, userRoleUserField, userRoleRoleField configure the names of the tables and the columns within them that are used to format the following queries:

SELECT <credentialField> FROM <userTable> WHERE <userField> =?
SELECT <userRoleRoleField> FROM <userRoleTable> WHERE <userRoleUserField> =?

Credential and role information is lazily read from the database when a previously unauthenticated user requests authentication. This information is only cached for the length of the authenticated session. When the user logs out or the session expires, the information is flushed from memory.

Note.png
You can store passwords in the database in plain text or encoded formats, using the Jetty password utility.


DataSourceLoginModule

Similar to the JDBCLoginModule, but this LoginModule uses a DataSource to connect to the database instead of a JDBC driver. The DataSource is obtained by doing a JNDI lookup on java:comp/env/$\{dnJNDIName\}.

Here is a sample login module configuration for the DataSourceLoginModule:

ds {
       org.eclipse.jetty.plus.jaas.spi.DataSourceLoginModule required
       debug="true"
       dbJNDIName="ds"
       userTable="myusers"
       userField="myuser"
       credentialField="mypassword"
       userRoleTable="myuserroles"
       userRoleUserField="myuser"
       userRoleRoleField="myrole";
   };

PropertyFileLoginModule

With this login module implementation, the authentication and role information is read from a property file.

props {
          org.eclipse.jetty.plus.jaas.spi.PropertyFileLoginModule required
          debug="true"
          file="/somewhere/somefile.props";
      };

The file parameter is the location of a properties file of the same format as the etc/realm.properties example file. The format is:

<username>: <password>[,<rolename> ...]

Here's an example:

fred: OBF:1xmk1w261u9r1w1c1xmq,user,admin
harry: changeme,user,developer
tom: MD5:164c88b302622e17050af52c89945d44,user
dick: CRYPT:adpexzg3FUZAk,admin

The contents of the file are fully read in and cached in memory the first time a user requests authentication.

LdapLoginModule

The LdapLoginModule ships in a separate jar, in $JETTY-HOME/lib/ext/jetty-ldap-jaas.jar. It requires JDK1.5 or above.

ldaploginmodule {
   org.eclipse.jetty.plus.jaas.spi.LdapLoginModule required
   debug="true"
   contextFactory="com.sun.jndi.ldap.LdapCtxFactory"
   hostname="ldap.example.com"
   port="389"
   bindDn="cn=Directory Manager"
   bindPassword="directory"
   authenticationMethod="simple"
   forceBindingLogin="false"
   userBaseDn="ou=people,dc=alcatel"
   userRdnAttribute="uid"
   userIdAttribute="uid"
   userPasswordAttribute="userPassword"
   userObjectClass="inetOrgPerson"
   roleBaseDn="ou=groups,dc=example,dc=com"
   roleNameAttribute="cn"
   roleMemberAttribute="uniqueMember"
   roleObjectClass="groupOfUniqueNames";
   };

=== Configuring the Role Principal Implementation Class for the LDAPLoginModule[1]
Cite error: <ref> tags exist, but no <references/> tag was found

Back to the top