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"

(New page: {{Jetty Tutorial | introduction = (required) | details = Using JAAS with jetty is very simply a matter of declaring a {{org.mortbay.jetty.plus.jaas.JAASUserRealm}}, creating a jaas login ...)
 
Line 1: Line 1:
{{Jetty Tutorial
+
Jetty Tutorial
 
| introduction = (required)
 
| introduction = (required)
 
| details =
 
| details =
  
Using JAAS with jetty is very simply a matter of declaring a {{org.mortbay.jetty.plus.jaas.JAASUserRealm}}, creating a jaas login module configuration file and specifying it on the jetty run line. Let's look at an example.
+
Using JAAS with jetty is very simply a matter of declaring a org.mortbay.jetty.plus.jaas.JAASUserRealm, creating a jaas login module configuration file and specifying it on the jetty run line. Let's look at an example.
  
*Step 1*
+
=== Step 1 ===
  
Configure a jetty6 {{org.mortbay.jetty.plus.jaas.JAASUserRealm}} to match the {{<realm-name>}} in your {{web.xml}} file. For example, if the {{web.xml}} contains a realm called {{"xyzrealm"}}:
+
Configure a Jetty org.mortbay.jetty.plus.jaas.JAASUserRealm to match the &lt;realm-name&gt; in your web.xml file. For example, if the web.xml contains a realm called "xyzrealm":
 
<source lang="xml">
 
<source lang="xml">
 
<login-config>
 
<login-config>
Line 19: Line 19:
 
</source>
 
</source>
  
Then the following {{JAASUserRealm}} would be declared in a jetty configuration file:
+
Then the following JAASUserRealm would be declared in a Jetty configuration file:
 
<source lang="xml">
 
<source lang="xml">
 
<Call name="addUserRealm">
 
<Call name="addUserRealm">
Line 30: Line 30:
 
</Call>
 
</Call>
 
</source>
 
</source>
{warning:title=Important!} It is imperative that the contents of the {{<realm-name>}} and the {{<Set name="name">}} of the JAASUserRealm instance are _exactly_ the same
+
warning| IMPORTANT: It is imperative that the contents of the &lt;realm-name&gt; and the &lt;Set name="name"&gt; of the JAASUserRealm instance are _exactly_ the same
{warning}{*}Step 2*
+
  
Set up your LoginModule in a configuration file, following the [syntax rules|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html]:
+
=== Step 2 ===
<source lang="text">xyz {
+
 
 +
Set up your LoginModule in a configuration file, following the [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html syntax rules]:
 +
<source lang="text">
 +
xyz {
 
       com.acme.SomeLoginModule required debug=true;
 
       com.acme.SomeLoginModule required debug=true;
 
     };
 
     };
 
</source>
 
</source>
{warning:title=Important!} It is imperative that the application name to the left of the \{ is _exactly_ the same as the {{<Set name="LoginModuleName">}}
+
warning|IMPORTANT: It is imperative that the application name to the left of the \{ is _exactly_ the same as the &lt;Set name="LoginModuleName"&lt;
{warning}{*}Step 3*
+
 
 +
 
 +
=== Step 3 ===
  
 
Invoke jetty with the jaas configuration file you created in step 2:
 
Invoke jetty with the jaas configuration file you created in step 2:
Line 45: Line 49:
 
> java -Djava.security.auth.login.config=mylogin.conf -jar start.jar etc/myjetty.xml
 
> java -Djava.security.auth.login.config=mylogin.conf -jar start.jar etc/myjetty.xml
 
</source>
 
</source>
h1. A Closer Look at the JAASUserRealm
 
  
To allow the greatest degree of flexibility in using JAAS with web applications, the {{JAASUserRealm}} supports a couple of configuration options. Note that you don't ordinarily need to set these explicitly, as jetty6 has defaults which will work in 99% of cases. However, should you need to, you can configure:
+
== A Closer Look at the JAASUserRealm ==
 +
 
 +
To allow the greatest degree of flexibility in using JAAS with web applications, the JAASUserRealm supports a couple of configuration options. Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases. However, should you need to, you can configure:
 +
 
 
* a policy for role-based authorization (Default: org.mortbay.jetty.plus.jaas.StrictRoleCheckPolicy)
 
* a policy for role-based authorization (Default: org.mortbay.jetty.plus.jaas.StrictRoleCheckPolicy)
* a [CallbackHandler|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/CallbackHandler.html] (Default: org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler)
+
* a [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/CallbackHandler.html CallbackHandler] (Default: org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler)
* a list of classnames for the [Principal|http://java.sun.com/j2se/1.4.2/docs/api/java/security/Principal.html] implementation that equate to a user role (Default: org.mortbay.jetty.plus.jaas.JAASRole)
+
* a list of classnames for the [http://java.sun.com/j2se/1.4.2/docs/api/java/security/Principal.html Principal] implementation that equate to a user role (Default: org.mortbay.jetty.plus.jaas.JAASRole)
  
 
Here's an example of setting each of these (to their default values):
 
Here's an example of setting each of these (to their default values):
<source lang="xml"><New class="org.mortbay.jetty.plus.jaas.JAASUserRealm">
+
<source lang="xml">
 +
<New class="org.mortbay.jetty.plus.jaas.JAASUserRealm">
 
   <Set name="Name">xyzrealm</Set>
 
   <Set name="Name">xyzrealm</Set>
 
   <Set name="LoginModuleName">xyz</Set>
 
   <Set name="LoginModuleName">xyz</Set>
Line 60: Line 67:
 
   </Set>
 
   </Set>
 
   <Set name="CallbackHandlerClass">
 
   <Set name="CallbackHandlerClass">
      org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler
+
    org.mortbay.jetty.plus.jaas.callback.DefaultCallbackHandler
 
   </Set>
 
   </Set>
 
   <Set name="roleClassNames">
 
   <Set name="roleClassNames">
Line 69: Line 76:
 
</New>
 
</New>
 
</source>
 
</source>
h2. RoleCheckPolicy
 
  
The {{RoleCheckPolicy}} must be an implementation of the {{org.mortbay.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.mortbay.jetty.plus.jaas.StrictRoleCheckPolicy}}, which will assess a user as having a particular role iff 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 amongst those configured for the user.
+
=== RoleCheckPolicy ===
  
Roles can be temporarily assigned to a user programmatically by using the {{pushRole(String rolename)}} method of the {{org.mortbay.jetty.plus.jaas.JAASUserPrincipal}} class.
+
The RoleCheckPolicy must be an implementation of the org.mortbay.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.mortbay.jetty.plus.jaas.StrictRoleCheckPolicy, which will assess a user as having a particular role iff 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 amongst those configured for the user.
  
For the majority of webapps, the default {{StrictRoleCheckPolicy}} will be quite adequate, however you may provide your own implementation and set it on your {{JAASUserRealm}} instance.
+
Roles can be temporarily assigned to a user programmatically by using the pushRole(String rolename) method of the org.mortbay.jetty.plus.jaas.JAASUserPrincipal class.
  
h2. CallbackHandler
+
For the majority of webapps, the default StrictRoleCheckPolicy will be quite adequate, however you may provide your own implementation and set it on your JAASUserRealm instance.
  
A [CallbackHandler|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/CallbackHandler.html] is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
+
=== CallbackHandler ===
  
Jetty ships with the {{org.mortbay.jetty.plus.jaas.DefaultCallbackHandler}} which interfaces the information contained in the [request|http://jetty.mortbay.org/apidocs/javax/servlet/http/HttpServletRequest.html] to the [Callbacks|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/Callback.html] that are requested by [LoginModules|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/spi/LoginModule.html]. You can replace this default with your own implementation if you have specific requirements not covered by the default.
+
A [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/CallbackHandler.html CallbackHandler] is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
  
h2. Role Principal Implementation Class
+
Jetty ships with the org.mortbay.jetty.plus.jaas.DefaultCallbackHandler which interfaces the information contained in the [http://jetty.mortbay.org/apidocs/javax/servlet/http/HttpServletRequest.html request] to the [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/Callback.html Callbacks] that are requested by [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/spi/LoginModule.html LoginModules]. You can replace this default with your own implementation if you have specific requirements not covered by the default.
  
When LoginModules authenticate a user, they usually also gather all of the roles that a user has and place them inside the JAAS [Subject|http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/Subject.html]. As LoginModules are free to use their own implementation of the JAAS [Principal|http://java.sun.com/j2se/1.4.2/docs/api/java/security/Principal.html] 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-constraint>s}}. 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.
+
=== Role Principal Implementation Class ===
  
h1. Sample Login Modules
+
When LoginModules authenticate a user, they usually also gather all of the roles that a user has and place them inside the JAAS [http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/Subject.html Subject]. As LoginModules are free to use their own implementation of the JAAS [http://java.sun.com/j2se/1.4.2/docs/api/java/security/Principal.html 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 &lt;security-constraint&gt;s. 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.
  
{anchor:egs}At the time of writing, jetty6 ships with 3 sample LoginModule implementations:
+
=== Sample Login Modules ===
* {{org.mortbay.jetty.plus.jaas.spi.JDBCLoginModule}}
+
* {{org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule}}
+
* {{org.mortbay.jetty.plus.jaas.spi.DataSourceLoginModule}}
+
* {{org.mortbay.jetty.plus.jaas.ldap.LdapLoginModule}}
+
  
We'll take a look at all of these, but first, a word about password handling in jetty6, as it applies to all LoginModules.
+
At the time of writing, Jetty provides four sample LoginModule implementations:
 +
* org.mortbay.jetty.plus.jaas.spi.JDBCLoginModule
 +
* org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule
 +
* org.mortbay.jetty.plus.jaas.spi.DataSourceLoginModule
 +
* org.mortbay.jetty.plus.jaas.ldap.LdapLoginModule
  
h2. Passwords/Credentials
+
We'll take a look at all of these, but first, a word about password handling in Jetty, as it applies to all LoginModules.
  
{anchor:pwd}Passwords can be stored in clear text, obfuscated or checksummed.  The class {{org.mortbay.util.Password}} should be used to generate all varieties of passwords,the output from which can be cut and pasted into property files or entered into database tables.
+
=== Passwords/Credentials ===
 +
 
 +
Passwords can be stored in clear text, obfuscated or checksummed.  The class org.eclipse.jetty.http.security.Password should be used to generate all varieties of passwords,the output from which can be cut and pasted into property files or entered into database tables.
 
<source lang="bash">
 
<source lang="bash">
> java -cp lib/jetty.jar org.mortbay.jetty.security.Password
+
> java -cp lib/jetty.jar org.eclipse.jetty.http.security.Password
 
Usage - java org.mortbay.util.Password [<user>] <password>
 
Usage - java org.mortbay.util.Password [<user>] <password>
> java -cp lib/jetty.jar org.mortbay.jetty.security.Password me you
+
> java -cp lib/jetty.jar org.eclipse.jetty.http.security.Password me you
 
you
 
you
 
OBF:20771x1b206z
 
OBF:20771x1b206z
Line 111: Line 119:
 
Read more on [Securing Passwords].
 
Read more on [Securing Passwords].
  
h2. JDBCLoginModule
+
=== JDBCLoginModule ===
  
 
The JDBCLoginModule stores user passwords and roles in a database that are 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.
 
The JDBCLoginModule stores user passwords and roles in a database that are 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:
 
Here is an example login module configuration file entry for it using an HSQLDB driver:
<source lang="text">jdbc {
+
<source lang="text">
 +
jdbc {
 
       org.mortbay.jetty.plus.jaas.spi.JDBCLoginModule required
 
       org.mortbay.jetty.plus.jaas.spi.JDBCLoginModule required
 
       debug="true"
 
       debug="true"
Line 129: Line 138:
 
       userRoleRoleField="myrole";
 
       userRoleRoleField="myrole";
 
       };
 
       };
</source>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:
+
</source>
 +
 
 +
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:
 
<source lang="text">select <credentialField> from <userTable> where <userField> =?
 
<source lang="text">select <credentialField> from <userTable> where <userField> =?
 
select <userRoleRoleField> from <userRoleTable> where <userRoleUserField> =?
 
select <userRoleRoleField> from <userRoleTable> where <userRoleUserField> =?
Line 136: Line 147:
 
Note that passwords can be stored in the database in plain text or encoded formats, using the [org.mortbay.jetty.security.Password|#pwd] class.
 
Note that passwords can be stored in the database in plain text or encoded formats, using the [org.mortbay.jetty.security.Password|#pwd] class.
  
h2. DataSourceLoginModule
+
=== 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\}}}
+
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 it:
 
Here is a sample login module configuration for it:
Line 154: Line 165:
 
</source>
 
</source>
  
h2. PropertyFileLoginModule
+
=== PropertyFileLoginModule ===
  
 
With this login module implementation, the authentication and role information is read from a property file.
 
With this login module implementation, the authentication and role information is read from a property file.
Line 162: Line 173:
 
         file="/somewhere/somefile.props";
 
         file="/somewhere/somefile.props";
 
       };
 
       };
</source>The {{file}} parameter is the location of a properties file of the same format as the {{etc/realm.properties}} example file. The format is:
+
</source>The file parameter is the location of a properties file of the same format as the etc/realm.properties example file. The format is:
 
<source lang="text"><username>: <password>[,<rolename> ...]
 
<source lang="text"><username>: <password>[,<rolename> ...]
 
</source>Here's an example:
 
</source>Here's an example:
Line 171: Line 182:
 
</source>The contents of the file are fully read in and cached in memory the first time a user requests authentication.
 
</source>The contents of the file are fully read in and cached in memory the first time a user requests authentication.
  
h2. LdapLoginModule
+
=== LdapLoginModule ===
  
 
Note that the LdapLoginModule ships in a separate jar, in $JETTY-HOME/lib/ext/jetty-ldap-jaas.jar. It requires JDK1.5 or above.
 
Note that the LdapLoginModule ships in a separate jar, in $JETTY-HOME/lib/ext/jetty-ldap-jaas.jar. It requires JDK1.5 or above.
Line 196: Line 207:
 
   };
 
   };
 
</source>
 
</source>
h2. Writing Your Own
+
 
 +
=== Writing Your Own ===
  
 
If you want to implement your own custom LoginModule, there are two classes to be familiar with:
 
If you want to implement your own custom LoginModule, there are two classes to be familiar with:
<source lang="java">AbstractLoginModule.java
+
<source lang="java">
 +
AbstractLoginModule.java
  
 
package org.mortbay.jetty.plus.jaas.spi;
 
package org.mortbay.jetty.plus.jaas.spi;
Line 209: Line 222:
 
}
 
}
 
</source>
 
</source>
<source lang="java">UserInfo.java
+
 
 +
<source lang="java">
 +
UserInfo.java
  
 
package org.mortbay.jetty.plus.jaas.spi;
 
package org.mortbay.jetty.plus.jaas.spi;
Line 236: Line 251:
 
   }
 
   }
 
}
 
}
</source>The {{org.mortbay.jetty.plus.jaas.spi.AbstractLoginModule}} implements all of the {{javax.security.auth.spi.LoginModule}} methods. All you need to do is to implement the {{getUserInfo}} method to return a {{org.mortbay.jetty.plus.jaas.UserInfo}} instance which encapsulates the username, password and role names (note: as {{java.lang.String}}s) for a user.
+
</source>The org.mortbay.jetty.plus.jaas.spi.AbstractLoginModule implements all of the javax.security.auth.spi.LoginModule methods. All you need to do is to implement the getUserInfo method to return a org.mortbay.jetty.plus.jaas.UserInfo instance which encapsulates the username, password and role names (note: as java.lang.Strings) for a user.
  
The {{AbstractLoginModule}} does not support any caching, so if you want to cache {{UserInfo}} (eg as does the {{org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule}}) then you must provide this yourself.
+
The AbstractLoginModule does not support any caching, so if you want to cache UserInfo (eg as does the org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule) then you must provide this yourself.
  
h1. Example JAAS WebApp
+
=== Example JAAS WebApp ===
  
There is an example of authentication and web authorization in the jetty distribution in {{examples/test-jaas-webapp}}. It uses the [PropertyFileLoginModule|#pflm] to perform authentication based on a simple properties file.  To use it with the [jetty maven plugin|http://jetty.mortbay.org/maven-plugin/index.html]:
+
There is an example of authentication and web authorization in the jetty distribution in examples/test-jaas-webapp. It uses the [PropertyFileLoginModule|#pflm] to perform authentication based on a simple properties file.  To use it with the [jetty maven plugin|http://jetty.mortbay.org/maven-plugin/index.html]:
 
<source lang="bash">cd examples/test-jaas-webapp
 
<source lang="bash">cd examples/test-jaas-webapp
 
mvn jetty:run
 
mvn jetty:run
Line 252: Line 267:
 
</source>Then surf to [http://localhost:8080/test-jaas/index.html]
 
</source>Then surf to [http://localhost:8080/test-jaas/index.html]
  
h1. Other Goodies
+
== Other Goodies ==
 
+
  
h2. RequestParameterCallback
+
=== RequestParameterCallback ===
  
As all servlet containers intercept and process a form submission with action {{j_security_check}}, it is usually not possible to insert any extra input fields onto a login form with which to perform authentication: you may only pass {{j_username}} and {{j_password}}. For those rare occasions when this is not good enough, and you require more information from the user in order to authenticate them, you can use the JAAS callback handler {{org.mortbay.jetty.plus.jaas.callback.RequestParameterCallback}}. This callback handler gives you access to all parameters that were passed in the form submission. To use it, in the {{login()}} method of your custom login module, add the {{RequestParameterCallback}} to the list of callback handlers the login module uses, tell it which params you are interested in, and then get the value of the parameter back. Here's an example:
+
As all servlet containers intercept and process a form submission with action j_security_check, it is usually not possible to insert any extra input fields onto a login form with which to perform authentication: you may only pass j_username and j_password. For those rare occasions when this is not good enough, and you require more information from the user in order to authenticate them, you can use the JAAS callback handler org.mortbay.jetty.plus.jaas.callback.RequestParameterCallback. This callback handler gives you access to all parameters that were passed in the form submission. To use it, in the login() method of your custom login module, add the RequestParameterCallback to the list of callback handlers the login module uses, tell it which params you are interested in, and then get the value of the parameter back. Here's an example:
<source lang="java">FooLoginModule.java
+
<source lang="java">
 +
FooLoginModule.java
  
 
public class FooLoginModule extends AbstractLoginModule
 
public class FooLoginModule extends AbstractLoginModule
Line 298: Line 313:
 
| category = (optional) - categor(ies) to use for this page. If blank, will use the template name as a default category
 
| category = (optional) - categor(ies) to use for this page. If blank, will use the template name as a default category
 
Example: [[Category:Category 1]] [[Category:Category 2]]
 
Example: [[Category:Category 1]] [[Category:Category 2]]
}}
 

Revision as of 12:43, 31 December 2009

Jetty Tutorial | introduction = (required) | details =

Using JAAS with jetty is very simply a matter of declaring a org.mortbay.jetty.plus.jaas.JAASUserRealm, creating a jaas login module configuration file and specifying it on the jetty run line. Let's look at an example.

Step 1

Configure a Jetty org.mortbay.jetty.plus.jaas.JAASUserRealm 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>

Then the following JAASUserRealm would be declared in a Jetty configuration file:

<Call name="addUserRealm">
  <Arg>
    <New class="org.mortbay.jetty.plus.jaas.JAASUserRealm">
      <Set name="name">xyzrealm</Set>
      <Set name="LoginModuleName">xyz</Set>
    </New>
  </Arg>
</Call>

warning| IMPORTANT: It is imperative that the contents of the <realm-name> and the <Set name="name"> of the JAASUserRealm instance are _exactly_ the same

Step 2

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

xyz {
       com.acme.SomeLoginModule required debug=true;
    };

warning|IMPORTANT: It is imperative that the application name to the left of the \{ is _exactly_ the same as the <Set name="LoginModuleName"<


Step 3

Invoke jetty with the jaas configuration file you created in step 2:

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

A Closer Look at the JAASUserRealm

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

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

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

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

RoleCheckPolicy

The RoleCheckPolicy must be an implementation of the org.mortbay.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.mortbay.jetty.plus.jaas.StrictRoleCheckPolicy, which will assess a user as having a particular role iff 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 amongst those configured for the user.

Roles can be temporarily assigned to a user programmatically by using the pushRole(String rolename) method of the org.mortbay.jetty.plus.jaas.JAASUserPrincipal class.

For the majority of webapps, the default StrictRoleCheckPolicy will be quite adequate, however you may provide your own implementation and set it on your JAASUserRealm instance.

CallbackHandler

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

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

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-constraint>s. 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.

Sample Login Modules

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

  • org.mortbay.jetty.plus.jaas.spi.JDBCLoginModule
  • org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule
  • org.mortbay.jetty.plus.jaas.spi.DataSourceLoginModule
  • org.mortbay.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.

Passwords/Credentials

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

> java -cp lib/jetty.jar org.eclipse.jetty.http.security.Password
Usage - java org.mortbay.util.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 are 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.mortbay.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. Note that 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 that passwords can be stored in the database in plain text or encoded formats, using the [org.mortbay.jetty.security.Password|#pwd] class.

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 it:

ds {
     org.mortbay.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.mortbay.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

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

ldaploginmodule {
   org.mortbay.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";
   };

Writing Your Own

If you want to implement your own custom LoginModule, there are two classes to be familiar with:

AbstractLoginModule.java
 
package org.mortbay.jetty.plus.jaas.spi;
 
public abstract class AbstractLoginModule implements LoginModule
{
  ...
  public abstract UserInfo getUserInfo (String username) throws Exception;
}
UserInfo.java
 
package org.mortbay.jetty.plus.jaas.spi;
 
public class UserInfo
{
 
  public UserInfo (String userName, Credential credential, List roleNames)
  {
    ...
  }
 
  public String getUserName()
  {
    ...
  }
 
  public List getRoleNames ()
  {
    ...
  }
 
  public boolean checkCredential (Object suppliedCredential)
  {
     ...
  }
}
The org.mortbay.jetty.plus.jaas.spi.AbstractLoginModule implements all of the javax.security.auth.spi.LoginModule methods. All you need to do is to implement the getUserInfo method to return a org.mortbay.jetty.plus.jaas.UserInfo instance which encapsulates the username, password and role names (note: as java.lang.Strings) for a user.

The AbstractLoginModule does not support any caching, so if you want to cache UserInfo (eg as does the org.mortbay.jetty.plus.jaas.spi.PropertyFileLoginModule) then you must provide this yourself.

Example JAAS WebApp

There is an example of authentication and web authorization in the jetty distribution in examples/test-jaas-webapp. It uses the [PropertyFileLoginModule|#pflm] to perform authentication based on a simple properties file. To use it with the [jetty maven plugin|http://jetty.mortbay.org/maven-plugin/index.html]:

cd examples/test-jaas-webapp
mvn jetty:run
Alternatively, to use it instead with jetty standalone:
cd examples/test-jaas-webapp
mvn clean install
cd ../../
java -jar start.jar etc/jetty.xml etc/jetty-jaas.xml
Then surf to [1]

Other Goodies

RequestParameterCallback

As all servlet containers intercept and process a form submission with action j_security_check, it is usually not possible to insert any extra input fields onto a login form with which to perform authentication: you may only pass j_username and j_password. For those rare occasions when this is not good enough, and you require more information from the user in order to authenticate them, you can use the JAAS callback handler org.mortbay.jetty.plus.jaas.callback.RequestParameterCallback. This callback handler gives you access to all parameters that were passed in the form submission. To use it, in the login() method of your custom login module, add the RequestParameterCallback to the list of callback handlers the login module uses, tell it which params you are interested in, and then get the value of the parameter back. Here's an example:

FooLoginModule.java
 
public class FooLoginModule extends AbstractLoginModule
{
        .
        .
        .
 
     public boolean login()
        throws LoginException
     {
        .
        .
        .
        Callback[] callbacks = new Callback[3];
        callbacks[0] = new NameCallback();
        callbacks[1] = new ObjectCallback();
 
        //as an example, look for a param named "extrainfo" in the request
        //use one RequestParameterCallback() instance for each param you want to access
        callbacks[2] = new RequestParameterCallback ();
        ((RequestParameterCallback)callbacks[2]).setParameterName ("extrainfo");
        .
        .
        .
        callbackHandler.handle(callbacks);
        String userName = ((NameCallback)callbacks[0]).getName();
        Object pwd = ((ObjectCallback)callbacks[1]).getObject();
        List paramValues = ((RequestParameterCallback)callbacks[2]).getParameterValues();
 
        //use the userName, pwd and the value(s) of the parameter named "extrainfo" to
        //authenticate the user
        .
        .
        .
     }

| more = (optional) - links, additional references | category = (optional) - categor(ies) to use for this page. If blank, will use the template name as a default category Example:

Back to the top