JAAS
JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework.
JAAS can be used for two purposes:
-
for authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet
-
for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed
JAAS authentication is performed in a pluggable fashion. This permits applications to remain independent from underlying authentication technologies. New or updated authentication technologies can be plugged under an application without requiring modifications to the application itself.
See Java Authentication and Authorization Service (JAAS) Reference Guide for more information about JAAS.
The Jetty JAAS support aims to dictate as little as possible whilst providing a sufficiently flexible infrastructure to allow users to drop either one of the JAAS Login Modules that ships with Jetty, or their own custom LoginModules.
Configuration
The jaas
module
Enable the jaas
module:
# DO NOT EDIT THIS FILE - See: https://eclipse.dev/jetty/documentation/ [description] Enables JAAS for deployed web applications. [depend] server [lib] lib/jetty-jaas-${jetty.version}.jar [xml] etc/jetty-jaas.xml [ini-template] ## The file location (relative to $jetty.base) for the ## JAAS "java.security.auth.login.config" system property # jetty.jaas.login.conf=etc/login.conf
The configurable items in the resulting $jetty.base/start.d/jaas.ini
file are:
- jetty.jaas.login.conf
-
This is the location of the file that will be referenced by the system property
java.security.auth.login.config
: Jetty sets this system property for you based on the value of this property. The value of this property is assumed to be relative to$JETTY_BASE
. The default value isetc/login.conf
, which resolves to$JETTY_BASE/etc/login.conf
. If you don’t want to put your login module configuration file here, you can change this property to point to where it is.
See more about the contents of this file in the Configuring JAAS section.
Configure the webapp for JAAS
The <realm-name>
in web.xml
will be used to identify the org.eclipse.jetty.jaas.JAASLoginService
declaration that integrates JAAS with Jetty.
For example, this web.xml
contains a realm called Test JAAS Realm
:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Test JAAS Realm</realm-name> (1)
<form-login-config>
<form-login-page>/login/login</form-login-page>
<form-error-page>/login/error</form-error-page>
</form-login-config>
</login-config>
1 | The name of the realm, which must be identical to the name of an org.eclipse.jetty.jaas.JAASLoginService declaration. |
We now need to declare an org.eclipse.jetty.jaas.JAASLoginService
that references the realm name of Test JAAS Realm
.
Here’s an example of a suitable XML snippet:
<New class="org.eclipse.jetty.jaas.JAASLoginService">
<Set name="Name">Test JAAS Realm</Set> (1)
<Set name="LoginModuleName">xyz</Set> (2)
</New>
1 | The name is the same as that declared in the <realm-name> in web.xml . |
2 | The name that identifies a set of javax.security.auth.spi.LoginModule configurations that comprise the JAAS config file identified in the jetty.jaas.login.conf property of the jaas module. |
The org.eclipse.jetty.jaas.JAASLoginService
can be declared in a couple of different places, pick whichever suits your purposes best:
-
If you have more than one webapp that you would like to use the same security infrastructure, then you can declare your
org.eclipse.jetty.jaas.JAASLoginService
as a bean that is added to theorg.eclipse.jetty.server.Server
. The file in which you declare this needs to be on Jetty’s execution path. The recommended procedure is to create a file in your$jetty.base/etc
directory and then ensure it is on the classpath either by adding it to the Jetty start command line, or more conveniently to a custom module.Here’s an example of this type of XML file:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd"> <Configure id="Server" class="org.eclipse.jetty.server.Server"> <Call name="addBean"> <Arg> <New class="org.eclipse.jetty.jaas.JAASLoginService"> <Set name="name">Test JAAS Realm</Set> <Set name="LoginModuleName">xyz</Set> </New> </Arg> </Call> </Configure>
-
Alternatively, if you want to use JAAS with a specific webapp only, you declare your
org.eclipse.jetty.jaas.JAASLoginService
in a context XLM file specific to that webapp:<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="securityHandler"> <New class="org.eclipse.jetty.security.ConstraintSecurityHandler"> <Set name="loginService"> <New class="org.eclipse.jetty.jaas.JAASLoginService"> <Set name="name">Test JAAS Realm</Set> <Set name="loginModuleName">xyz</Set> </New> </Set> </New> </Set> </Configure>
Configure JAAS
We now need to setup the contents of the file we specified as the jetty.jaas.login.conf
property when we configured the jaas
module.
Refer to the syntax rules of this file for a full description.
Remembering the example we set up previously, the contents of the $jetty.base/etc/login.conf
file could look as follows:
xyz { (1)
com.acme.SomeLoginModule required debug=true; (2)
com.other.OtherLoginModule optional; (3)
};
1 | The name of the configuration exactly as specified in your org.eclipse.jetty.jaas.JAASLoginService declaration. |
2 | The first LoginModule declaration, containing the classname of the LoginModule and its configuration properties. |
3 | A second LoginModule declaration.
You can provide as many LoginModule alternatives as you like, with a minimum of one.
Refer to the JAAS documentation for more information on the standard configuration properties, and how JAAS interprets this file. |
Provided LoginModules
Passwords can be stored in clear text, obfuscated or checksummed.
The class |
JDBCLoginModule
The org.eclipse.jetty.jaas.spi.JDBCLoginModule
stores user passwords and roles in a database 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 names of the table and columns storing the roles.
Here is an example login module configuration file entry for it using an HSQLDB driver:
jdbc { (1)
org.eclipse.jetty.jaas.spi.JDBCLoginModule required (2)(3)
dbUrl="jdbc:hsqldb:." (4)
dbUserName="sa" (5)
dbDriver="org.hsqldb.jdbcDriver" (6)
userTable="myusers" (7)
userField="myuser" (8)
credentialField="mypassword" (9)
userRoleTable="myuserroles" (10)
userRoleUserField="myuser" (11)
userRoleRoleField="myrole"; (12)
};
1 | The name of the configuration. |
2 | The name of the LoginModule class. |
3 | A standard JAAS flag making successful authentication via this LoginModule mandatory. |
4 | The JDBC url used to connect to the database. |
5 | The name of the JDBC user to use for the connection. |
6 | The name of the JDBC Driver class. |
7 | The name of the table holding the user authenication information. |
8 | The name of the column holding the user name. |
9 | The name of the column holding the user credential. |
10 | The name of the table holding the user authorization information. |
11 | The name of the column holding the user name. |
12 | The name of the column holding the user role. |
The properties 7-12 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 — see the note on "Passwords/Credentials" above.
DataSourceLoginModule
Similar to the org.eclipse.jetty.jaas.spi.JDBCLoginModule
, but using a javax.sql.DataSource
to connect to the database instead of a JDBC driver.
The javax.sql.DataSource
is obtained at runtime by performing a JNDI lookup on java:comp/env/${dnJNDIName}
.
A sample login module configuration for this LoginModule
:
ds { (1)
org.eclipse.jetty.jaas.spi.DataSourceLoginModule required (2)(3)
dbJNDIName="ds" (4)
userTable="myusers" (5)
userField="myuser" (6)
credentialField="mypassword" (7)
userRoleTable="myuserroles" (8)
userRoleUserField="myuser" (9)
userRoleRoleField="myrole"; (10)
};
1 | The name of the configuration. |
2 | The name of the LoginModule class. |
3 | A standard JAAS flag making successful authentication via this LoginModule mandatory. |
4 | The JNDI name, relative to java:comp/env/ to lookup to obtain the javax.sql.DataSource . |
5 | The name of the table holding the user authenication information. |
6 | The name of the column holding the user name. |
7 | The name of the column holding the user credential. |
8 | The name of the table holding the user authorization information. |
9 | The name of the column holding the user name. |
10 | The name of the column holding the user role. |
PropertyFileLoginModule
With this login module implementation, the authentication and role information is read from a property file.
props { (1)
org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required (2)(3)
file="/somewhere/somefile.props"; (4)
};
1 | The name of the configuration. |
2 | The name of the LoginModule class. |
3 | A standard JAAS flag making successful authentication via this LoginModule mandatory. |
4 | The location of a properties file containing the authentication and authorization information. |
The property file must be of the format:
<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 org.eclipse.jetty.jaas.spi.LdapLoginModule
uses LDAP to access authentication and authorization information stored in a directory.
The LDAP connection information and structure of the authentication/authorization data can be configured.
Here’s an example:
example { (1)
org.eclipse.jetty.jaas.spi.LdapLoginModule required (2)(3)
contextFactory="com.sun.jndi.ldap.LdapCtxFactory" (4)
hostname="ldap.example.com" (5)
port="389" (6)
bindDn="cn=Directory Manager" (7)
bindPassword="directory" (8)
authenticationMethod="simple" (9)
useLdaps="true" (10)
userBaseDn="ou=people,dc=alcatel" (11)
userRdnAttribute="uid" (12)
userIdAttribute="cn" (13)
userPasswordAttribute="userPassword" (14)
userObjectClass="inetOrgPerson" (15)
roleBaseDn="ou=groups,dc=example,dc=com" (16)
roleNameAttribute="cn" (17)
roleMemberAttribute="uniqueMember" (18)
roleObjectClass="groupOfUniqueNames"; (19)
forceBindingLogin="false" (20)
debug="false" (21)
};
1 | The name of the configuration. |
2 | The name of the LoginModule class. |
3 | A standard JAAS flag making successful authentication via this LoginModule mandatory. |
4 | The name of the context factory to use for the LDAP connection. |
5 | The hostname for the LDAP connection. Optional. |
6 | The port for the LDAP connection. Optional. |
7 | The caller security Principal. Optional. |
8 | The caller security credential. Optional. |
9 | The security level for the LDAP connection environment. Optional. |
10 | If true, use ldaps instead of ldap for the connection url. |
11 | The distinguished name of the directory to search for user information. |
12 | The name of the attribute for the user roles. |
13 | The name of the attribute for the user id. |
14 | The name of the attribute for the user password. |
15 | The ObjectClass for users. |
16 | The distinguished name of the directory to search for role information. |
17 | The name of the attribute for roles. |
18 | The name of the attribute storing the user for the roles ObjectClass . |
19 | The name of the ObjectClass for roles. |
20 | If true, the authentication proceeds on the basis of a successful LDAP binding using the username and credential provided by the user. If false, then authentication proceeds based on username and password information retrieved from LDAP. |
21 | If true, failed login attempts are logged on the server. |