Table of Contents
List of Figures
List of Examples
dwr.xml configuration examplejGuardPrincipalPermission.xmluk.ltd.getahead.dwr.AccessControlTable of Contents
jGuard provides EASY security (authentication and authorization) in web and standalone applications. It is built over the stable and mature JAAS framework, which is part of the JAVA J2SE apis.
jGuard is licensed under the GNU Lesser General Public Licence (formerly known as LGPL). you can obtain a copy of the LGPL licence on the gnu project web site.
Only requires java 1.4 and j2ee 1.3 or higher
Can be adapted to any webapp, on any application server
Permits a user to have more than one role simultaneously
Does not depend on a web framework, or an AOP framework
Built on top of the standard, very secure, and flexible JAAS
Authentication and authorization are handled by pluggable mechanisms
Authentication data stored in a database, an XML file, a JNDI datasource, an LDAP directory, Kerberos...
Changes take effects 'on the fly' (dynamic configuration)
Permissions, roles, and their associations can be created, updated, deleted on the fly through a webapp (an API is provided too)
Each webapp has its own authentication and authorization configuration
A taglib is provided to protect jsp fragments
Support security manager
jGuard is composed of 9 libraries :
jGuard-core: it contains the main jGuard features.
jGuard-ext : it handles specific authentication and authorization managers such as XML or JDBC based managers. It also embeds login modules like JDBC or jCaptcha.
jGuard-ext-java-5: a java 5 library which includes jGuard security features for JMX.
jGuard-jee : library is dedicated for web applications.
jGuard-jee-4: a jee 4 library
jGuard-jee-extras: library dedicated to add security features to some specific web thrid part libraries like DWR (ajax library).
jGuard-struts-example: webapp example to ilustrate jGuard use if you've chosen Struts as your web framework
jGuard-jsf-example: webapp example to ilustrate jGuard use if you've chosen JSF MyFaces as your web framework
Table of Contents
securing an application should be done with an Access Control Model. widely used access control models are described in a dedicated chapter.
To apply an access control model in a java application, you have these choices
use java security infrastructure (through jAAS)
use security implementation by the application server if you're in a jee context
reinvent the wheel
jGuard distinguish 3 types of "users" in a J2EE environment:
administrator
webapp developer
webapp user
since release 1.0.0 , jGuard
provides two Security scopes, on authentication and authorization.
these scopes affect jGuard
javax.security.auth.login.Configuration and
java.security.policy implementations.
this scope permits to have isolate security per classloader; i.e is mainly dedicated to jee applications.
'local' authentication provides a good security level. It allows protection of the webapp resources against webapp users. Each webapp user will be authenticated, and access control will be provided according to his roles. This authentication configuration will not protect webapp developers against webapp developers of others webapps, or administrators.
The authentication configuration is easier, because everything should be configured in the web.xml. There is no need to configure things on the JVM side. Security is present after the first webapp which uses jGuard is loaded by the application server. This security level is reliable for these use cases:
The webapp is used to test jGuard
There is only one webapp on the application server
There are multiple webapps on the same application servers, and there are 'friendly' each others
One 'friendly' webapp is loaded firstly
'advanced' configuration allows for a more secure environment, but is more difficult to configure: in jee environment, You must install two jars: one for the webapp, and one dedicated to the JVM-side.some bootclasspath tricks are needed too.
This configuration allows for protection of webapp resources against users like the 'usual' configuration; i.e to protect webapp developers against others webapps, and to protect administrator against any webapp developers. The administrator of the machine should also restrict the java rights to protect against the application sever administrator. This configuration is highly secure, and should be used by hosting companies.
This is a cascading security delegation
model:
webapp users are controlled by webapps
webapps are isolated from others webapps (others webapps cannot make damages)
webapps are controlled by the application server administrator which configure the JVM security
The application server administrator is controlled by the operating system administrator which assign restricted rights to java
the operating system administrator security relies on BIOS security, which relies on the physical machine security.
To have this very secured configuration, you must enable
the SecurityManager.
goals of this configuration file is to define:
resources where the user is dispatched depending on the Access Control check result
authentication schemes used with the specific technology anchor
specific parameters for the CallbackHandler implementation
Authentication schemes are defined as the mechanisms used to transmit credentials from the user (browser for webapps) to the server. These credentials are used on the server to authenticate the user in its backend. They can be configured in the authScheme markup.
to configure your authentication schemes, you DON'T have
to configure your application server to use them (especially,
you DON'T have to configure the
<login-config> markup in the
web.xml, and its related
<auth-method> and
<realm-name> markup). jGuard replace
the specific mechanisms used in your application server, to
grab credentials and compute them to authenticate the
user.
FORM authentication
since its inception, jGuard support the
FORM authentication scheme. Credentials
are sent from the browser to the application server through
an HTML form.
some special URIs are involved in this authentication scheme:
logonURI
this URI is used to access to the page which contains the form used to authenticate. This URI is granted to ALL users.
logonProcessURI
this URI is used to send to the server the credentials to authenticate. This URI is granted to ALL users.
loginField
HTML field in the HTML authentication form, used to store your login. This special field is trapped by the accessFilter to grab this credential.
passwordField
HTML field in the HTML authentication form, used to store your password. This special field is trapped by the accessFilter to grab this credential.
BASIC authentication
since the 0.70 release, jGuard support BASIC authentication. Some special URIs are involved in this authentication scheme:
logonProcessURI
this URI is used to send to the server the credentials to authenticate. This URI is granted to ALL users.
Digest Authentication
this authentication scheme is not yet supported.a feature request has been posted on the jGuard bug tracking system hosted on sourceforge.
CLIENT_CERT authentication
since the 0.70 release,
jGuard support CLIENT_CERT
authentication.
jGuard use its own mechanisms involved in
authentication schemes. But it uses the
SSL mechanism provided by the
application server, in the case of
CLIENT-CERT authentication. So, you
have to configure your web.xml file
with this markup:
<security-constraint>
<web-resource-collection>
<web-resource-name>all the webapp</web-resource-name>
<description></description>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<description>This part requires SSL</description>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>Example 2.4. jGuardFilter.xml example
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE configuration SYSTEM "jGuardFilter_1.1.0.dtd">
<configuration>
<!-- Index uri of your web application. -->
<authenticationSucceedURI>/index.jsp</authenticationSucceedURI>
<!-- Uri when the user authentication failed. -->
<authenticationFailedURI>/AuthenticationFailed.do</authenticationFailedURI>
<!-- Uri to access to the authentication form -->
<logonURI>/Logon.do</logonURI>
<!-- uri to be authenticated. The action property of the authentication form MUST NOT be set to j_security_check. -->
<logonProcessURI>/LogonProcess.do</logonProcessURI>
<registerURI>/Registration.do</registerURI>
<registerProcessURI>/RegistrationProcess.do</registerProcessURI>
<!-- uri to to be unauthenticated -->
<logoffURI>/Logoff.do</logoffURI>
<!-- uri when access to a ressource is denied -->
<accessDeniedURI>/AccessDenied.do</accessDeniedURI>
<authScheme>FORM</authScheme>
<loginField>login</loginField>
<!-- Parameter's name of the form's field which holds the password. All values are accepted except j_password. -->
<passwordField>password</passwordField>
<goToLastAccessDeniedUriOnSuccess>true</goToLastAccessDeniedUriOnSuccess>
</configuration>this configuration file specific to a web application is
used to define the URI used when to follow
jGuard Access control decisions. The location of this file is
specified in the web.xml, especially in the
AccessFilter declaration in a
configurationLocation parameter.
goals of this configuration file is to define:
the authentication scope
the AuthenticationManager implementation
the loginmodules involved in the authentication process with their options and JAAS keywords (required, optional, and so on...)
Table of Contents
Authentication part is composed of the Authentication process, which is involved when user is not authenticated, and AuthenticationManager, which manage users and roles.they both share the same Authentication store.
AuthenticationManager implementations aims to do Create, Read,
Update, Delete (CRUD) operations on users and roles
of the application. These Users and roles are present in the
datasource authentication. This datasource (database, XML and so
on..), is also the same one used for the authentication
process which involve LoginContext,
Configuration and
LoginModules.
Authentication configuration in jGuard, is done via the
jGuardAuthentication.xml file.
goals of this configuration file is to:
define the authentication scope
define the AuthenticationManager implementation
define the loginmodules involved in the
authentication process with their options and
JAAS keywords (required, optional, and so on...)
This AuthenticationManager implementation permits to persist in a XML file all the auithentication informations of your application.
debug
This optional parameter, when set to
true, activate the debug mode (provide more
logs to detect easily misconfiguration).
authenticationXmlFileLocation
a relative path from the webapp, of the
jGuardUsersPrincipals.xml file.
....
....
<authenticationManager>net.sf.jguard.authentication.XmlAuthenticationManager</authenticationManager>
<authenticationManagerOptions>
<option>
<name>authenticationXmlFileLocation</name>
<value>WEB-INF/conf/jGuard/jGuardUsersPrincipals.xml</value>
</option>
</authenticationManagerOptions>
....
....The JdbcAuthenticationManager has
been replaced by the
HibernateAuthenticationManager for a better
flexibility. A further
JPAAuthenticationManager,
ORM agnostic
AuthenticationManager implementation, can
be another suitable solution provided in a future release.
This AuthenticationManager
implementation permits to persist in a database all the
authentication informations of your
application.HIerbnaetAuthenticationManager needs to use a
SessionFactory instance; here are the ways supported to grab the
sessionFactory
hibernate.cfg.xml
Hibernate can build and use a sessionFactory by reading an Hibernate.cfg.xml config file present on the classPath.
authenticationXmlFileLocation
WEB-INF/conf/jGuard/jGuardUsersPrincipals.xml for example . This parameter permits to import some data when your database is empty
....
....
<authenticationManager>net.sf.jguard.ext.authentication.manager.HibernateAuthenticationManager</authenticationManager>
<authenticationManagerOptions>
<option>
<name>authenticationXmlFileLocation</name>
<value>WEB-INF/conf/jGuard/jGuardUsersPrincipals.xml</value>
</option>
</authenticationManagerOptions>
....
....you have to configure the associated HibernateLoginModule.
Authentication process is standardized into java through the
JAAS api. It involves the
LoginContext class, a callbackHandler
implementation, a Configuration instance, and
some loginModules. jGuard provides
This class is the main entry point to the Authentication Process. it defines :
which Subject (user) authenticate
through which way (CallbackHandler)
for which application
with which authentication technologies (LoginModules)
in which mechanism (Configuration)
This class provides multiple constructors which permits to
build a convenient LoginContext class. Authentication is done
during the login method, which return an
authenticated Subject, or a
LoginException. when the user quit the
application, the logout method should to
be called.
in webapps, jGuard provides some high-level classes to reduce your work, and simplify the use of JAAS like the AccessFilter servlet filter.
this class handle the way to grab informations contained into
information from a protocol, to fill callbacks (used by loginmodules)
to authenticate the user. So, LoginModules can use the same callbacks
but with different CallbackHandler depending on the situation. jGuard
provides different callbackHandler like
JMXCallbackHandler,
SwingCallbackHandler ,and
HttpServletCallbackHandler.
after the user transmits its credentials through the authentication scheme, jGuard should authenticate the user with them.to authenticate the user, jGuard use its credentials against some security challenges: LoginModules.
loginModules are stackable: you can configure multiple
loginModules (in the jGuardConfiguration.xml
file),which will help you to authenticate a user or not.
each loginModule has got a flag which can be
'REQUIRED','OPTIONAL','REQUISITE'
ou 'SUFFICIENT' (JAAS
documentation from SUN™):
REQUIRED
The LoginModule is required to succeed. If it succeeds or fails, authentication still continues to proceed down the LoginModule list.
REQUISITE
The LoginModule is required to succeed. If it succeeds, authentication continues down the LoginModule list.If it fails, control immediately returns to the application (authentication does not proceed down the LoginModule list).
SUFFICIENT
The LoginModule is not required to succeed. If it does succeed, control immediately returns to the application (authentication does not proceed down the LoginModule list).If it fails, authentication continues down the LoginModule list.
OPTIONAL
The LoginModule is not required to succeed. If it succeeds or fails, authentication still continues to proceed down the LoginModule list.
You should have noticed that the configuration for
loginModules involved in validating user identity is very small:
configuration already defined in
AuthenticationManager are reused to
establish connections in loginmodules. so,
JdbcLoginmodule uses
JdbcAuthenticationManager configuration to
establish database connections and so on…
This loginModule is an abstract class.
its subclasses grab informations in various locations
(database,LDAP,Xml and so on...) to authenticate users.
stores are configured into AuthenticationManager implementations and are reused by UserLoginModule subclasses.So, you don't have to declare stores into UserLoginModule subclasses.
This Loginmodule inherit from UserLoginmodule and use
users and roles located in an XML file called
jGuardUsersPrincipals.xml to authenticate
users.
debug
This optional parameter, when set to
true, activate the debug mode (provide
more logs to detect easily misconfiguration).
Example 3.1. configuration of XMLLoginModule into a fragment of jGuardAuthentication.xml
to reference XMLLoginModule, you have to declare it
into jGuardAuthentication.xml
file.
....
....
<authentication>
<loginModules>
<loginModule>
<name>net.sf.jguard.ext.authentication.loginmodules.XmlLoginModule</name>
<flag>REQUIRED</flag>
<loginModuleOptions>
<option>
<name>debug</name>
<value>false</value>
</option>
</loginModuleOptions>
</loginModule>
</loginModules>
</authentication>
....
....Example 3.2. jGuardUsersPrincipals.xml example
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<authentication xmlns="http://jguard.sourceforge.net/xsd/jGuardUsersPrincipals_1.1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://jguard.sourceforge.net/xsd/jGuardUsersPrincipals_1.1.0 jGuardUsersPrincipals_1.1.0.xsd">
<principals>
<principal>
<name>admin</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>jguard-struts-example</applicationName>
<organizationRef>myenterpriseId</organizationRef>
</principal>
<principal>
<name>guest</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>jguard-struts-example</applicationName>
<organizationRef>system</organizationRef>
</principal>
<principal>
<name>role3</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>anotherApplication</applicationName>
<organizationRef>system</organizationRef>
</principal>
</principals>
<users>
<user>
<privateCredentials>
<credential>
<id>login</id>
<value>admin</value>
</credential>
<credential>
<id>password</id>
<value>admin</value>
</credential>
</privateCredentials>
<publicCredentials>
<credential>
<id>firstname</id>
<value>Rick</value>
</credential>
<credential>
<id>lastname</id>
<value>Dangerous</value>
</credential>
<credential>
<id>location</id>
<value>Paris</value>
</credential>
</publicCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example" definition="${subject.publicCredentials.location.contains('Paris')}" active="true"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
<organizationRef>system</organizationRef>
</user>
<user>
<privateCredentials>
<credential>
<id>login</id>
<value>guest</value>
</credential>
<credential>
<id>password</id>
<value>guest</value>
</credential>
</privateCredentials>
<publicCredentials/>
<principalsRef>
<principalRef name="guest" applicationName="jguard-struts-example" />
</principalsRef>
<organizationRef>system</organizationRef>
</user>
</users>
<organizations>
<organizationTemplate>
<userTemplate>
<privateRequiredCredentials>
<credTemplateId>login</credTemplateId>
<credTemplateId digestNeeded="true">password</credTemplateId>
</privateRequiredCredentials>
<publicRequiredCredentials>
<credTemplateId>firstname</credTemplateId>
<credTemplateId>lastname</credTemplateId>
<credTemplateId>location</credTemplateId>
</publicRequiredCredentials>
<privateOptionalCredentials>
<credTemplateId>country</credTemplateId>
<credTemplateId>religion</credTemplateId>
</privateOptionalCredentials>
<publicOptionalCredentials>
<credTemplateId>hobbies</credTemplateId>
</publicOptionalCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</userTemplate>
<credentials>
<credTemplateId>id</credTemplateId>
</credentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</organizationTemplate>
<organization>
<userTemplate>
<privateRequiredCredentials>
<credTemplateId>login</credTemplateId>
<credTemplateId digestNeeded="true">password</credTemplateId>
</privateRequiredCredentials>
<publicRequiredCredentials>
<credTemplateId>firstname</credTemplateId>
<credTemplateId>lastname</credTemplateId>
<credTemplateId>location</credTemplateId>
</publicRequiredCredentials>
<privateOptionalCredentials>
<credTemplateId>country</credTemplateId>
<credTemplateId>religion</credTemplateId>
</privateOptionalCredentials>
<publicOptionalCredentials>
<credTemplateId>hobbies</credTemplateId>
</publicOptionalCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</userTemplate>
<credentials>
<credential>
<id>id</id>
<value>system</value>
</credential>
<credential>
<id>creation date</id>
<value>1965</value>
</credential>
</credentials>
<principalsRef>
<principalRef applicationName="jguard-struts-example" name="guest"/>
<principalRef name="admin" applicationName="jguard-struts-example" />
</principalsRef>
</organization>
</organizations>
</authentication>This loginModule inherit from UserLoginmodule and allows a database-based authentication for your application.
debug
This optional parameter, when set to
true, activate the debug mode (provide
more logs to detect easily misconfiguration).
Example 3.3. configuration of HibernateLoginModule into a fragment of jGuardAuthentication.xml
to reference HibernateLoginModule, you have to declare
it into jGuardAuthentication.xml
file.
....
....
<authentication>
<loginModule>
<name>net.sf.jguard.ext.authentication.loginmodules.HibernateLoginModule</name>
<!-- flag :'REQUIRED','OPTIONAL','REQUISITE' or 'SUFFICIENT' -->
<flag>REQUIRED</flag>
<loginModuleOptions>
<option>
<name>debug</name>
<value>false</value>
</option>
</loginModuleOptions>
</loginModule>
....
....this UserLoginModule subclass, authenticate users and roles into a JNDI directory like LDAP.
most of the parameters detailed in this page comes from the JNDI Context constants detailed in the related JNDI javadoc.
this loginmodule does NOT yet retrieve roles from the directory. only authentication against credentials are supported. roles support will be rpovided in a future release.
connections can be established either through manual
configuration, or via application server JNDI lookup. for all
parameters, you have to include the prefix
('preauth.' or 'auth.').
these settings apply to direct authentication
and pre-authentication modes.
initial context factory
.....
<option>
<name>preauth.java.naming.factory.initial</name>
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
</option>
.....provider url
.....
<option>
<name>preauth.java.naming.provider.url</name>
<value>ldap://mycompany.com:389</value>
</option>
.....authentication mode
you can use none ,
simple or a SASL
mechanism type defined in the RFC
2195.
.....
<option>
<name>java.naming.security.authentication</name>
<value>none</value>
</option>
.....activate connection pooling
you can sometimes activate the connection pooling of the JNDI service providers. if you use the one provided by sun, here is the configuration:
.....
<option>
<name>preauth.com.sun.jndi.ldap.connect.pool</name>
<value>true</value>
</option>
.....define the preferred number of connections
.....
<option>
<name>preauth.com.sun.jndi.ldap.connect.pool.prefsize</name>
<value>5</value>
</option>
.....define connection timout
.....
<option>
<name>preauth.com.sun.jndi.ldap.connect.pool.timeout</name>
<value>300000</value>
</option>
.....this example defines the number of milliseconds (5 minutes in this example) that an idle connection may remain in the pool without being closed and removed from the pool.
other connection pool settings
other settings can be reached at the JNDI/LDAP Service provider documentation page.
activate the Fast bind connection mode for Active Directory
a specific LDAP control can be activated against Active Directory server. more details on it here: Active directory LDAP server fast bind mode documentation
.....
<option>
<name>preauth.fastBindConnection</name>
<value>true</value>
</option>
.....connections can be retrieved via the application servers JNDI system. to specify which name must be used to grab the context, you have to use after the prefix, the jndi name.
.....
<option>
<name>preauth.jndi</name>
<value>myDs</value>
</option>
.....different use cases are possible, depending on how to find the Distinguished Name(DN), which is the path to the user Entry.this DN will be used to :
authenticate the user
grab its associated credentials.
authentication parameters starts with the
'auth.' prefix. the DN is
known, directly from the userDN parameter and
the user login. for example,
....
<option>
<name>auth.userDN</name>
<value>dc=com,dc=mycompany,ou=mysection,cn={0}</value>
</option>
....the {0} will be replaced by the login
provided by the user.
when the user DN cannot be known, a
first search should be done to know what is the
DN. authentication parameters starts with the
'preauth.' prefix.
base DN
this parameter defines from which Distinguished Name (path) starts the search.
....
<option>
<name>preauth.search.base.dn</name>
<value>dc=mycompany,dc=com</value>
</option>
....search filter
this parameter define the LDAP filter used to locate the DN of the user.
....
<option>
<name>preauth.search.filter</name>
<value>(&(samAccountName={0})(!(proxyAddresses=*)))</value>
</option>
....search scope
for object scope, use 0. for one level scope, use 1. for subtree scope, use 2.
....
<option>
<name>preauth.searchcontrols.searchscope</name>
<value>2</value>
</option>
....usually, jGuard reuses the connection used to authenticate the user, to do a lookup on the user entry. sometimes, it can be useful to grab the informations directly from the LDAP entry found to know the user DN. to do it, you have to include this parameter:
....
<option>
<name>contextforcommit</name>
<value>true</value>
</option>
....in your jGuardAuthentication.xml
file:
.......
<loginModule>
<name>net.sf.jguard.ext.authentication.loginmodules.JNDILoginModule</name>
<flag>REQUIRED</flag>
<loginModuleOptions>
<option>
<name>preauth.java.naming.factory.initial</name>
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
</option>
<option>
<name>preauth.java.naming.provider.url</name>
<value>ldap://yourcompany.com:389</value>
</option>
<option>
<name>java.naming.security.authentication</name>
<value>none</value>
</option>
<option>
<name>preauth.searchcontrols.searchscope</name>
<value>2</value>
</option>
<option>
<name>preauth.search.base.dn</name>
<value>dc=stuff,dc=com</value>
</option>
<option>
<name>preauth.search.filter</name>
<value>(&(samAccountName={0})(!(proxyAddresses=*)))</value>
</option>
<option>
<name>auth.java.naming.factory.initial</name>
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
</option>
<option>
<name>auth.java.naming.provider.url</name>
<value>ldap://yourcompany.com:389</value>
</option>
<option>
<name>auth.java.naming.security.authentication</name>
<value>simple</value>
</option>
<option>
<name>contextforcommit</name>
<value>true</value>
</option>
</loginModuleOptions>
</loginModule>
..............
<loginModule>
<name>net.sf.jguard.ext.authentication.loginmodules.JNDILoginModule</name>
<flag>REQUIRED</flag>
<loginModuleOptions>
<option>
<name>preauth.java.naming.factory.initial</name>
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
</option>
<option>
<name>auth.java.naming.provider.url</name>
<value>ldap://168.12.45.88:389</value>
</option>
<option>
<name>auth.java.naming.security.authentication</name>
<value>simple</value>
</option>
<option>
<name>auth.java.naming.security.authentication</name>
<value>simple</value>
</option>
<option>
<name>com.sun.jndi.ldap.connect.pool</name>
<value>true</value>
</option>
<option>
<name>com.sun.jndi.ldap.connect.pool.prefsize</name>
<value>5</value>
</option>
<option>
<name>contextforcommit</name>
<value>false</value>
</option>
<option>
<name>auth.userDN</name>
<value>{0}</value>
</option>
</loginModuleOptions>
</loginModule>
.......jGuard looks into the X509 Certificate provided by the user
and checks against the Certificate Authority its validity (with
the loginMoules described below). When the certicate is valid,
jGuard uses the informations present in it to populate the
javax.security.auth.Subject.
jGuard only handle the first certificate provided by the user (theorically, a user can provide multiple certificates at the same time).
unique ID
If the certificate field
subjectUniqueID is present in the
certificate, jGuard create a credential called
uniqueID in the
javax.security.auth.Subject. this field
is OPTIONAL in the certificate. jGuard use the method
getSubjectUniqueID from the class
java.security.cert.X509Certificate to
grab this information.
alternative names
if a SubjectAltName extension is
present in the certificate, jGuard grab the subject
alternatives names with the method
getSubjectAlternativeNames, and
create for each alternative name a credential with the name
alternativeName#aSequenceNumber
.SubjectAltName extension in certificate is
OPTIONAL.
X500 principal
jguard grab a principal object from the field
subject in the certificate, with the method
getSubjectX500Principal method,and
put it into the Principals set of the
Subject.
this field in the certificate is REQUIRED.
When you use the
JdbcLoginmodule (or
XmlLoginModule) in conjunction with
a certificate-related loginModule, jGuard will check this
value against the value of the credential called
'login'.
you can use other loginModules like
XMLLoginModule and
JdbcLoginmodule in collaboration with
CRLLoginModule or
OCSPLoginModule. in others authentication
schemes, i.e FORM,BASIC,
or DIGEST, the user actively send its login
and password informations. These informations are used by
XMLLoginModule or
JdbcLoginmodule to check if the user
eixsts and if its password is valid. after this step, it
populates the Subject with some
informations from the Datasource (XML or Database). with
CLIENT-CERT authentication, the mechanism is
in the same way. the only difference is that the user
automatically send its login and other information with its
certificate. No password are required, because some powerful
cryptographic mechanisms check the validity of the certificate.
so, when the user transmit its certificate, jGuard populate the
Subject with a X500Principal object.
jGuard use the String returned by the
getName method of the
X500Principal stored in the
Subject as the login information.
to summarize, the only information required in the
certificate is the 'subject' field. the value
of 'subject' field should be a
'distinguished name' (DN), compliant with the
RFC
2253. to have more informations on certificate
structure(which fields can be inserted), you can look towards
the RFC
2459.
This loginModule permits an authentication based on X509
certificates: it validates their certPath,
and checks if some of them are revoked against a CRL
(Certificate Revocation List) which lists certificates that has
been revoked by the Certificate Authority
(CA) before their scheduled expiration date.
Note this certificate validation mechanism is not
based on real-time mechanism: the accuracy of this mechanism
is based on the CRL generation frequency
of the Certificate Authority. If you authenticate
successfully a user, but the CRL used to check it is too
old, you will have a security threat.
These parameters comes from the PKIXParameters
java class: parameters description comes from the JDK's
javadoc.
debug
This optional parameter, when set to
true, activate the debug mode (provide
more logs to detect easily misconfiguration).
certPathAnyPolicyInhibited
Sets state to determine if the any policy
OID should be processed if it is included
in a certificate. can be true or
false, and default value is
false if not set.
certPathExplicitPolicyRequired
If this flag is true, an acceptable
policy needs to be explicitly identified in every
certificate. default value is
false.
certPathPolicyMappingInhibited
If this flag is true, policy
mapping is inhibited. default value is
false.
certPathPolicyQualifiersRejected
f this flag is true, certificates
that include policy qualifiers in a certificate policies
extension that is marked critical are
rejected. If the flag is false,
certificates are not rejected on this basis.Applications
that want to use a more sophisticated policy must set this
flag to false.Default value is
true.
Note that the PKIX certification
path validation algorithm specifies that any policy
qualifier in a certificate policies extension that is
marked critical must be processed and
validated. Otherwise the certification path must be
rejected. If the
policyQualifiersRejected flag is set to
false, it is up to the application to validate all policy
qualifiers in this manner in order to be
PKIX compliant.
certPathRevocationEnabled
If this flag is true, the default
revocation checking mechanism of the underlying
PKIX service provider will be used. If
this flag is false, the default
revocation checking mechanism will be disabled (not
used).When a PKIXParameters object is created, this flag is
set to true. This setting reflects the
most common strategy for checking revocation, since each
service provider must support revocation checking to be
PKIX compliant. Sophisticated
applications should set this flag to
false when it is not practical to use a
PKIX service provider's default
revocation checking mechanism or when an alternative
revocation checking mechanism is to be substituted.Default
value is true.
certPathSigProvider
Sets the signature provider's name. The specified provider will be preferred when creating Signature objects. If null or not set, the first provider found supporting the algorithm will be used.
certPathCrlPath
if this value is defined, it grabs the CRL from a file and add it to the CRLs collection. the value is a system-dependent fileName.
certPathUrlCrlPath
if this value is defined, it grabs the CRL from an HTTP URL and add it to the CRLs collection.
trustedCaCertsDirPath
this directory path must contain Trusted
certificates to build Trust
Anchors.
securityProvider
a security provider class name to use. default value
is
org.bouncycastle.jce.provider.BouncyCastleProvider.
certPathCertStoreType
define from which source the certstore will retrieve
certificates and CRLs. value can be LDAP
or Collection.
certPathLdapServerName
server name used to grab certificates and CRLS for the
certstore.default value is
localhost.
certPathLdapServerPort
server port used to grab certificates and CRLS for the
certstore. default value is
389.
javax.net.ssl.trustStore
file path of the trustStore.
javax.net.ssl.trustStorePassword
password protecting access to
TrustStore data present in the
file.
keyStorePath
file path of the keyStore.
keyStorePassword
password protecting access to
keyStore data present in the file.
keyStoreType
Valid types can be those returned by the
java.security.Security.getAlgorithms("KeyStore")
attribute(JKS,JCEKS,PKCS12,PKCS11
(Java crypto
device),CMSKS,JCERACFKS
...)
This loginModule permits an authentication for your web
application based on X509 certificates: it validates their
certPath, and checks if some of them are
revoked against a OCSP mechanism. this
mechanism permits real-time certificate revocation check.
ocspServerURL
URL of the server which rpovide OCSP validation service .this parameter is mandatory.
IssuerCACertLocation
location of the certificate of the issuer Certificate Authority.
OcspSignerCertLocation
location of the certificate of the OCSP signer.
Example 3.4. configuration of OCSPLoginModule into a fragment of jGuardAuthentication.xml
…
…
<loginModule>
<name>net.sf.jguard.ext.authentication.loginmodules.OCSPLoginModule</name>
<flag>REQUIRED</flag>
<loginModuleOptions>
<option>
<name>debug</name>
<value>true</value>
</option>
<option>
<name>ocspServerURL</name>
<value>http://127.0.0.1:8080/ejbca/publicweb/status/ocsp</value>
</option>
<option>
<name>IssuerCACertLocation</name>
<value>/home/user/certificates/AdminCA1.der</value>
</option>
<option>
<name>OcspSignerCertLocation</name>
<value>/home/user/certificates/AdminCA1.der</value>
</option>
</loginModuleOptions>
</loginModule>
…
...since jGuard 0.80, this loginModule permits to validate a user against a CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart), to determine if the user is human or not.
to use this loginModule, you need firstly to insert in your login page, this kind of code to generate an image containing the challenge:
<img id="captcha" src="<html:rewrite action='/Captcha.do'/>" />
note this code is used with the Struts framework, because we use the html:rewrite taglib to generate the url to access to the Captcha Action which will generate the image. but you can use any framework to do the same thing. to permit the user to answer to the challenge, you need also to insert in your login form, the related fields:
<div>
<label for="captchaAnswer">captchaAnswer(required)</label>
<input id="captchaAnswer" type="text" value="" size="30" name="captchaAnswer" tabindex="3" />
</div>to use this loginMoule, you need to insert in your JGuardConfiguration.xml file, this declaration:
<loginModule>
<name>net.sf.jguard.authentication.loginmodules.JCaptchaLoginModule</name>
<flag>REQUIRED</flag>
</loginModule>note that you can use other flags,depending on your needs.
this loginModule use to generate and validate the Captcha, the JCaptcha open source library. Note that the archive shipped with the distribution is not the last release; we use only the JCaptcha 1.0 RC2 release: since the release 1.0 RC3, the JCaptcha project has changed its licence from LGPL to GPL, which prevents us to ship it with jGuard (licensed under the LGPL). But we've tested jGuard with JCaptcha 1.0 RC3 or higher successfully, so we advice you to use this JCaptcha release if you accept that your application will be under the GPL umbrella.
JCaptcha team has produced other releases under the LGPL licence.So, you can use these releases with jGuard, but be aware that JCaptcha need a Java 5 or higher JVM to work.
you can add your own loginModule on the authentication
loginModules list. To do it, you have to implements the
javax.security.auth.spi.LoginModule
interface.
to authenticate a user against a store shipped with an
AuthenticationManager, you have to inherit
from
net.sf.jguard.ext.authentication.loginmodules.UserLoginModule.
this class defines which loginModules are involved in the authentication process, for a defined application (identified by its name). Each application has its own loginModules stack. With some special keywords to customize the mechanism.
Object resulting from a successful authentication. it represents a "real" entity like a user, a machine, and so on.... it contains some Principals and some credentials present in relative Sets.
Principals are often considered as Identities (one user can have more than one identity) or roles.
Credentials are user's attributes specific to him. it can be a first name, a credit card number, a birth date....
credentials are present either in a public credential Set
or a private credential set (access to them is protected by a
PrivateCredentialPermission).
subject, which represents authenticated user, contains its own
credentials, and also some Principals. the main implementation of
principal provided in Subject by jGuard is
net.sf.jguard.core.principals.RolePrincipal;
this class represent a role, a responsability
granted to the user.
Another implementation provided is
net.sf.jguard.core.organization.Organization
;it represents the entity which grants the user to use the
application.Every user has got an Organization and only one. This
feature permits to handle in your application multiple organization
support; RolePrincipals are owned by
organization declared in your application.if no Organization are
declared, users are linked with a default organization.
jGuard provides a mechanism that allows to automatically enable or disable a role (RolePrincipal) based on user credentials. This feature is defined in the attribute “definition” of “principalRef” tag. This attribute must evaluate “true” or “false”. For example, we could have in jGuardUsersPrincipals.xml the following:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<authentication xmlns="http://jguard.sourceforge.net/xsd/jGuardUsersPrincipals_1.1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://jguard.sourceforge.net/xsd/jGuardUsersPrincipals_1.1.0 jGuardUsersPrincipals_1.1.0.xsd">
<principals>
<principal>
<name>admin</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>jguard-struts-example</applicationName>
<organizationRef>myenterpriseId</organizationRef>
</principal>
<principal>
<name>guest</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>jguard-struts-example</applicationName>
<organizationRef>system</organizationRef>
</principal>
<principal>
<name>role3</name>
<class>net.sf.jguard.core.principals.RolePrincipal</class>
<applicationName>anotherApplication</applicationName>
<organizationRef>system</organizationRef>
</principal>
</principals>
<users>
<user>
<privateCredentials>
<credential>
<id>login</id>
<value>admin</value>
</credential>
<credential>
<id>password</id>
<value>admin</value>
</credential>
</privateCredentials>
<publicCredentials>
<credential>
<id>firstname</id>
<value>Rick</value>
</credential>
<credential>
<id>lastname</id>
<value>Dangerous</value>
</credential>
<credential>
<id>location</id>
<value>Paris</value>
</credential>
</publicCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example" definition="${subject.publicCredentials.location.contains('Paris')}" active="true"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
<organizationRef>system</organizationRef>
</user>
<user>
<privateCredentials>
<credential>
<id>login</id>
<value>guest</value>
</credential>
<credential>
<id>password</id>
<value>guest</value>
</credential>
</privateCredentials>
<publicCredentials/>
<principalsRef>
<principalRef name="guest" applicationName="jguard-struts-example" />
</principalsRef>
<organizationRef>system</organizationRef>
</user>
</users>
<organizations>
<organizationTemplate>
<userTemplate>
<privateRequiredCredentials>
<credTemplateId>login</credTemplateId>
<credTemplateId digestNeeded="true">password</credTemplateId>
</privateRequiredCredentials>
<publicRequiredCredentials>
<credTemplateId>firstname</credTemplateId>
<credTemplateId>lastname</credTemplateId>
<credTemplateId>location</credTemplateId>
</publicRequiredCredentials>
<privateOptionalCredentials>
<credTemplateId>country</credTemplateId>
<credTemplateId>religion</credTemplateId>
</privateOptionalCredentials>
<publicOptionalCredentials>
<credTemplateId>hobbies</credTemplateId>
</publicOptionalCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</userTemplate>
<credentials>
<credTemplateId>id</credTemplateId>
</credentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</organizationTemplate>
<organization>
<userTemplate>
<privateRequiredCredentials>
<credTemplateId>login</credTemplateId>
<credTemplateId digestNeeded="true">password</credTemplateId>
</privateRequiredCredentials>
<publicRequiredCredentials>
<credTemplateId>firstname</credTemplateId>
<credTemplateId>lastname</credTemplateId>
<credTemplateId>location</credTemplateId>
</publicRequiredCredentials>
<privateOptionalCredentials>
<credTemplateId>country</credTemplateId>
<credTemplateId>religion</credTemplateId>
</privateOptionalCredentials>
<publicOptionalCredentials>
<credTemplateId>hobbies</credTemplateId>
</publicOptionalCredentials>
<principalsRef>
<principalRef name="admin" applicationName="jguard-struts-example"/>
<principalRef name="role3" applicationName="anotherApplication"/>
</principalsRef>
</userTemplate>
<credentials>
<credential>
<id>id</id>
<value>system</value>
</credential>
<credential>
<id>creation date</id>
<value>1965</value>
</credential>
</credentials>
<principalsRef>
<principalRef applicationName="jguard-struts-example" name="guest"/>
<principalRef name="admin" applicationName="jguard-struts-example" />
</principalsRef>
</organization>
</organizations>
</authentication>The application could provide a way to allow the user to change its credential “loggedProject” between “ProjectA” and “ProjectB”. If the users chooses “ProjectA”, jGuard will automatically enable those roles where attribute “definition” evaluates “true”. You could use more complex expressions using logical operators, for example:
(subject.publicCredentials.loggedProject.contains('ProjectA') || subject.publicCredentials.loggedProject.contains('ProjectB')) && subject.privateCredentials.login.contains('userA')jguard uses the jakarta commons JEXL project expression library to provide expressiveness on contextual variables. this project has got a syntax page: http://jakarta.apache.org/commons/jexl/reference/syntax.html
You can get role definition using:
RolePrincipal ppal = (RolePrincipal)AuthenticationManagerFactory.getAuthenticationManager().getRole(subject, role, applicationName); String roleDefinition = ppal.getDefinition();
And you can set role definition using:
AuthenticationManagerFactory.getAuthenticationManager().updateRoleDefinition(subject, roleName, applicationName, roleDefinition);
jGuard can use a cryptographic
hash function to avoid password to be stored in clear on the
server. This function has the characteristic to produce a unique
digest of any string. So, a password 'secret1' will
produce with one of these functions a digest like
'1gE1r'. a password 'secret2'
will produce a digest like 'sF42'. For each
password, a different digest will be produced. So,each original
password will have its unique digest.
another characteristic is that it is very difficult to know which password is the origin of a related digest . So, if we store 'digested' password and not the original, anyone which will read these ones will not have the original password. But when we receive the password from the end user, we calculate the digest of it, and compare it with the one stored on the webapp using jGuard.
Cryptographic hash functions also called
MessageDigest algorithms, are available in Java.
Different algorithms are supported. You need to refer to the
documentation of your JVM vendor, especially the Java
Cryptography Architecture section. For example, many JVM
vendors provides these algorithms:
MD2
MD5
SHA-1
SHA-256
SHA-384
SHA-512
Other ones are also available. To use one algorithm in jGuard,
you have to use the right code related to the algorithm chosen like
the ones listed above. To use this algorithm, you have to uncomment
the digestAlgorithm markup in the
jGuardAuthentication.xml file and put into your
messageDigest algorithm code.
<digestAlgorithm>MD5</digestAlgorithm>
password salting is described on
wikipedia. Password are impossible to know if you have only
their digest. But if you store the digest of some popular password and
the origin in some big tables, you can lookup easily the origin based
on the digest. These tables are called rainbow
tables.
Password salting is used to prevent some attackers to use
rainbow tables. These tables are based on a known password origin. But
if you modify the origin with a 'salt' specific to
your application, it will be impossible to create rainbow tables with
all the possibilities of salt.
For example, if you concatenate 'passord1'
with the salt 'salt1' before to calculate the
digest, the result will be different and very difficult to know. To
use salt in conjunction of digest algorithm functions (you cannot only
use salt without digest algorithm), you have to uncomment in the
jGuardAuthentication.xml file the salt markup and put into it the salt
chosen. Be aware that sometimes, some rainbow tables also contains
some short salts. To be very safe, you should use long
salts.
<salt>qsd846ss2q6ds4</salt>
Table of Contents
Registration is an optional process in jGuard. to not use it, don't configure it.
when you want a user register in your application, you have to
define which informations he need to fill in. for example, he need to
provide a chosen login, a password, a first name, a last name and so
on... but all these informations are not always
required; some of them can be
optional.In the same way, these informations can be
either public or private; they
can be read from anyone (first name ) or kept secret (credit card
number). So, a subjectTemplate is not a user but
a template for defining a user.
these requirements are configured in your datasource (XML or
database), and used to build a SubjectTemplate
object too.
during the registration, a user submit the required information to
your application; these informations are used to build a user candidate.
this candidate is also expressed as a SubjectTemplate.
A subjectTemplate which define global
requirements to register a user (must have for example a
login and password and a
city credential), is also used to validate other
subjectTemplate which are user candidates.if
credentials provided by the candidate user (expressed
also as a SubjectTemplate), are not listed in the
subjectTemplate, they will be ignored. if the
credentials marked as required, are not provided,
the registration will fails. The
SubjectTemplate should also contains an
'Identity' crendetial, which is a credential to
uniquely identify a user(prevents identity stealth).
this autovalidation mechanism is also used with java
permissions with their 'implies'
method.
Table of Contents
Authorization part is involved to determine which
resources will be accessible from an authenticated
user. jGuard uses an Access Control model which involves the use of
roles domains and
permissions concepts.
Roles are present in authentication and authorization parts, and represent the unique link between these two parts.
To configure authorization of your web application, you have to :
defines your application resources
you can divide your application into resources by different ways, depending on your architecture style and environment.
you want to prevent a user to execute a
privileged code
this privileged code can be in the local
JVM or in another one (via RMI,JINI,
or Web service with SOAP, for example); your resources will be
Java methods, i.e you want to prevent unauthorized users to
execute some specific methods. This approach is Java
code centric, and often used with standalone
applications.
For distributed applications, the RPC
architecture style aims to calls remote methods. This style
tries to achieve call transparency by hiding the
remote characteristic of the
infrastructure. So, with RPC architecture
like Java's RMI, client code thinks call code
locally but remotely.
you want to prevent a user to use a resource
this way is often used in web applications, by representing a resource with an URL. This architecture style is often known as the RESTarchitecture style. So, you have to identify which URLs you want to protect (often all of them).
map your resources to permissions
Permissions are a security view of your
resources: it represents which actions you can do on your
resources. So, you can map one resource to a permission, or
multiple resources to a permission. You can protect your
application with any
java.security.permission subclasses, either
permissions provided by JDK or jGuard, or custom
permissions subclasses implemented by you; jGuard will persist and
use any of them.
which java.security.permission
subclass use for the architecture style I've chosen?
to secure a privileged method, you can use any Business
permission code by your own. For example, you can define a
com.mycompany.security.AccountPermission
subclass which will have a name (of the
account) and actions
(getTotal,
balance and so on...).
to secure resource, jGuard provides a permission
implementation based on URL:
URLPermission.
defines the roles of your web application
you need to define which roles will use your application. a role is a functional entity used to describe the activity of a set of person which will use your application.
a good practice is to define some roles
local to your application. Sometimes, users
want to define roles with a scope global to
an enterprise : this work can be time-consuming and
unproductive. So, we think you should be aware before trying to
achieve this role unification across multiple
applications.
map roles to permissions
java.security.Policy,principal,permission....
the default implementation provided delegates all security check
to the current java.security.Policy
implementation.
Authorization configuration in jGuard, is done via the
jGuardAuthorization.xml file.
goals of this configuration file is to:
define the authorization scope
<scope>local</scope>
enable/disable permission resolution caching
<permissionResolutionCaching>true</permissionResolutionCaching>
permission resolution expressions (used in contextual permisisons) mechanism can be sometimes time-consuming. to speed-up this mechanism, jGuard proposes to cache resolved expressions, via the cache library ehcache.
Sometimes, you can have some issues with caching mechanism used by jGuard, if you use other libraries which already use ehcache like Hibernate for example. To confirm this hypothesis, you have to inactivate cache mechanism and see if it solves your problem (performances can be lower, but not in a dramatic way).Ehcache need to be configured only one time. to fix this issue, you can enable caching mechanism in jGuard and include in the ehcache master configuration file this configuration part (cache names need to be followed strictly, but other parameters can be tweaked):
<cache name = "unresolvedPermToNeededExpressions"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<cache name = "unresolvedPermAndValuesToResolvedPerm"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"