<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.HashingEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>MD5</value> </option>
GateIn Portal is using Picketlink IDM framework to store information about identity objects (users/groups/memberships) and more info about this is in PicketLink IDM integration . For better security, Picketlink IDM does not save user passwords into database in plain-text, but it uses CredentialEncoder, which encode password and save the encoded form into Picketlink IDM database.
Later when user want to authenticate, he needs to provide his password in plain-text via web login form. Provided password is then encoded and compared with encoded password from Picketlink IDM database. GateIn Portal is then able to authenticate user based on this comparison.
Default implementation of CredentialEncoder is using password hashing with MD5 algorithm and storing those MD5 hashes in database. It does not use any salting of passwords. This is not safest solution, but it's backward compatible with previous releases of GateIn Portal before version 3.5, where MD5 password hashing was only possible encoding form. So if you migrate from older release of GateIn Portal, your users will be still able to authenticate.
However if you are starting from fresh database (no migration from previous GateIn Portal release), you may increase security by using better hashing algorithm and especially by enable password salting. See below for details.
The implementation of CredentialEncoder is configured in file GATEIN_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/organization/picketlink-idm/picketlink-idm-config.xml . Usually the most important are options of realm idm_portal starting with prefix credentialEncoder.. Possible implementations are:
This is the default choice. It uses only hashing of passwords with MD5 algorithm without salting. As mentioned previously, it's not safest solution but it's backward compatible with previous GateIn Portal releases, so there are no issues with database migration from previous release. Configuration looks like this:
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.HashingEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>MD5</value> </option>
This implementation provides salting of password in addition to hashing. The salt is unique for each user, so it's much more complicated to decrypt password via brute force, if some attacker steal encoded passwords from your database. The salt is generated randomly for each user and stored in Picketlink IDM database as attribute. Random generation of salt ensure that all users have different salts, so even if two users have same password, the encoded password in database will be different for them. Here is configuration example, which is using SHA-256 algorithm for hashing (more secure than MD5) and algorithm SHA1PRNG for generation of random salts.
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.DatabaseReadingSaltEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>SHA-256</value> </option> <option> <name>credentialEncoder.secureRandomAlgorithm</name> <value>SHA1PRNG</value> </option>
It also uses hashing and salting, so it's similar like previous encoder. But it's theoretically even more secure, because salts are not stored in Picketlink IDM database together with passwords. Salt of each user is generated from saltPrefix and user's username. And saltPrefix is read from some file in your filesystem. Configuration can look like this:
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.FileReadingSaltEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>SHA-256</value> </option> <option> <name>credentialEncoder.fileLocation</name> <value>/salt/mysalt.txt</value> </option>
Please note that specified file /salt/mysalt.txt must exist and must be readable by user, which executed GateIn Portal. But file should be properly secured to not be readable by every user of your OS. The file can have some random content phrase, for example a4564dac2aasddsklklkajdgnioiow .
So the FileReadingSaltEncoder is probably most secure of all options, but in addition to DatabaseReadingSaltEncoder you need to set the file with salt.
The CredentialEncoder from above is actually used only for encoding of passwords in Picketlink IDM database. It's not used for LDAP. Picketlink IDM LDAP implementation (LDAPIdentityStore) is sending passwords to LDAP server in plain form, because password encoding is usually provided by LDAP server itself. For example OpenDS 2 is using SHA1 based hashing of passwords with random generation of user salt (so actually something similar to our DatabaseReadingSaltEncoder implementation).
The Remember Me feature of GateIn Portal uses a token mechanism to be able to authenticate returning users without requiring an explicit login. However, to be able to authenticate these users, the token needs to store the username and password in clear text in JCR.
Administrators have two options available to ameliorate this risk:
The Remember Me feature can be disabled by removing the corresponding checkbox in:
JBOSS_HOME/gatein/gatein.ear/portal.war/login/jsp/login.jsp and
JBOSS_HOME/gatein/gatein.ear/portal.war/groovy/portal/webui/UILoginForm.gtmpl
Passwords can be encoded prior to being saved to the JCR. This option requires administrators to provide a custom subclass of org.exoplatform.web.security.security.AbstractCodec and set up a codec implementation with CookieTokenService:
Create a Java class similar to:
package org.example.codec; import org.exoplatform.container.xml.InitParams; import org.exoplatform.web.security.security.AbstractCodec; import org.exoplatform.web.security.security.CookieTokenService; import org.picocontainer.Startable; public class ExampleCodec extends AbstractCodec implements Startable { private String simpleParam; private CookieTokenService cookieTokenService; public ExampleCodec(InitParams params, CookieTokenService cookieTokenService) { simpleParam = params.getValueParam("encodingParam").getValue(); this.cookieTokenService = cookieTokenService; } public void start() { cookieTokenService.setupCodec(this); } public void stop() { } /** * Very simple encoding algorithm used only for demonstration purposes. * You should use stronger algorithm in real production environment!!! */ public String encode(String plainInput) { return plainInput + simpleParam; } public String decode(String encodedInput) { return encodedInput.substring(0, encodedInput.length() - simpleParam.length()); } }
ExampleCodec is using very simple encoding algorithm used only for demonstration purposes. You should use stronger algorithm in real production environment!!!
Compile the class and package it into a .jar file. For this example, you will call the codec-example.jar file.
Create a conf/portal/configuration.xml file within the codec-example.jar similar to the example below. This allows the portal kernel to find and use the new codec implementation.
<?xml version="1.0" encoding="ISO-8859-1"?> <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <component> <key>org.example.codec.ExampleCodec</key> <type>org.example.codec.ExampleCodec</type> <init-params> <value-param> <name>encodingParam</name> <value>aaa</value> </value-param> </init-params> </component> </configuration>
Deploy codec-example.jar into your JBOSS_HOME/modules/org/gatein/lib/main directory and update file module.xml of this directory (new jar needs to be added to AS7 modules)
Start (or restart) your GateIn Portal.
Any passwords written to the JCR will now be encoded and not plain text.