Class FileBasedAuthenticator

  • All Implemented Interfaces:
    Authenticator

    public class FileBasedAuthenticator
    extends AbstractAuthenticator
    Reference implementation of the Authenticator interface. This reference implementation is backed by a simple text file that contains serialized information about users. Many organizations will want to create their own implementation of the methods provided in the Authenticator interface backed by their own user repository. This reference implementation captures information about users in a simple text file format that contains user information separated by the pipe "|" character. Here's an example of a single line from the users.txt file:

     

    account id | account name | hashed password | roles | lockout | status | old password hashes | last hostname | last change | last login | last failed | expiration | failed --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1203123710837 | mitch | 44k/NAzQUlrCq9musTGGkcMNmdzEGJ8w8qZTLzpxLuQ= | admin,user | unlocked | enabled | u10dW4vTo3ZkoM5xP+blayWCz7KdPKyKUojOn9GJobg= | 192.168.1.255 | 1187201000926 | 1187200991568 | 1187200605330 | 2187200605330 | 1

    Since:
    June 1, 2007
    Author:
    Jeff Williams at Aspect Security, Chris Schmidt (chrisisbeef .at. gmail.com) Digital Ritual Software
    See Also:
    Authenticator
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void changePassword​(User user, java.lang.String currentPassword, java.lang.String newPassword, java.lang.String newPassword2)
      Changes the password for the specified user.
      User createUser​(java.lang.String accountName, java.lang.String password1, java.lang.String password2)
      Creates a new User with the information provided.
      java.lang.String generateStrongPassword()
      Generate a strong password.
      java.lang.String generateStrongPassword​(User user, java.lang.String oldPassword)
      Generate strong password that takes into account the user's information and old password.
      static Authenticator getInstance()  
      User getUser​(long accountId)
      Returns the User matching the provided accountId.
      User getUser​(java.lang.String accountName)
      Returns the User matching the provided accountName.
      java.util.Set getUserNames()
      Gets a collection containing all the existing user names.
      java.lang.String hashPassword​(java.lang.String password, java.lang.String accountName)
      Returns a string representation of the hashed password, using the accountName as the salt.
      protected void loadUsersIfNecessary()
      Load users if they haven't been loaded in a while.
      protected void loadUsersImmediately()  
      static void main​(java.lang.String[] args)
      Fail safe main program to add or update an account in an emergency.
      void removeUser​(java.lang.String accountName)
      Removes the account of the specified accountName.
      void saveUsers()
      Saves the user database to the file system.
      protected void saveUsers​(java.io.PrintWriter writer)
      Save users.
      void verifyAccountNameStrength​(java.lang.String newAccountName)
      Ensures that the account name passes site-specific complexity requirements, like minimum length.
      boolean verifyPassword​(User user, java.lang.String password)
      Verify that the supplied password matches the password for this user.
      void verifyPasswordStrength​(java.lang.String oldPassword, java.lang.String newPassword, User user)
      Ensures that the password meets site-specific complexity requirements, like length or number of character sets.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • main

        public static void main​(java.lang.String[] args)
                         throws java.lang.Exception
        Fail safe main program to add or update an account in an emergency.

        Warning: this method does not perform the level of validation and checks generally required in ESAPI, and can therefore be used to create a username and password that do not comply with the username and password strength requirements.

        Example: Use this to add the alice account with the admin role to the users file:

         

        java -Dorg.owasp.esapi.resources="/path/resources" -classpath esapi.jar org.owasp.esapi.Authenticator alice password admin

        Parameters:
        args - the arguments (username, password, role)
        Throws:
        java.lang.Exception - the exception
      • createUser

        public User createUser​(java.lang.String accountName,
                               java.lang.String password1,
                               java.lang.String password2)
                        throws AuthenticationException
        Creates a new User with the information provided. Implementations should check accountName and password for proper format and strength against brute force attacks ( verifyAccountNameStrength(String), verifyPasswordStrength(String, String) ). Two copies of the new password are required to encourage user interface designers to include a "re-type password" field in their forms. Implementations should verify that both are the same.
        Parameters:
        accountName - the account name of the new user
        password1 - the password of the new user
        password2 - the password of the new user. This field is to encourage user interface designers to include two password fields in their forms.
        Returns:
        the User that has been created
        Throws:
        AuthenticationException - if user creation fails due to any of the qualifications listed in this method's description
      • generateStrongPassword

        public java.lang.String generateStrongPassword()
        Generate a strong password. Implementations should use a large character set that does not include confusing characters, such as i I 1 l 0 o and O. There are many algorithms to generate strong memorable passwords that have been studied in the past.
        Returns:
        a password with strong password strength
      • changePassword

        public void changePassword​(User user,
                                   java.lang.String currentPassword,
                                   java.lang.String newPassword,
                                   java.lang.String newPassword2)
                            throws AuthenticationException
        Changes the password for the specified user. This requires the current password, as well as the password to replace it with. The new password should be checked against old hashes to be sure the new password does not closely resemble or equal any recent passwords for that User. Password strength should also be verified. This new password must be repeated to ensure that the user has typed it in correctly.
        Parameters:
        user - the user to change the password for
        currentPassword - the current password for the specified user
        newPassword - the new password to use
        newPassword2 - a verification copy of the new password
        Throws:
        AuthenticationException - if any errors occur
      • verifyPassword

        public boolean verifyPassword​(User user,
                                      java.lang.String password)
        Verify that the supplied password matches the password for this user. Password should be stored as a hash. It is recommended you use the hashPassword(password, accountName) method in this class. This method is typically used for "reauthentication" for the most sensitive functions, such as transactions, changing email address, and changing other account information.
        Parameters:
        user - the user who requires verification
        password - the hashed user-supplied password
        Returns:
        true, if the password is correct for the specified user
      • generateStrongPassword

        public java.lang.String generateStrongPassword​(User user,
                                                       java.lang.String oldPassword)
        Generate strong password that takes into account the user's information and old password. Implementations should verify that the new password does not include information such as the username, fragments of the old password, and other information that could be used to weaken the strength of the password.
        Parameters:
        user - the user whose information to use when generating password
        oldPassword - the old password to use when verifying strength of new password. The new password may be checked for fragments of oldPassword.
        Returns:
        a password with strong password strength
      • getUser

        public User getUser​(long accountId)
        Returns the User matching the provided accountId. If the accoundId is not found, an Anonymous User or null may be returned.
        Parameters:
        accountId - the account id
        Returns:
        the matching User object, or the Anonymous User if no match exists
      • getUser

        public User getUser​(java.lang.String accountName)
        Returns the User matching the provided accountName. If the accoundId is not found, an Anonymous User or null may be returned.
        Parameters:
        accountName - the account name
        Returns:
        the matching User object, or the Anonymous User if no match exists
      • getUserNames

        public java.util.Set getUserNames()
        Gets a collection containing all the existing user names.
        Returns:
        a set of all user names
      • hashPassword

        public java.lang.String hashPassword​(java.lang.String password,
                                             java.lang.String accountName)
                                      throws EncryptionException
        Returns a string representation of the hashed password, using the accountName as the salt. The salt helps to prevent against "rainbow" table attacks where the attacker pre-calculates hashes for known strings. This method specifies the use of the user's account name as the "salt" value. The Encryptor.hash method can be used if a different salt is required.
        Parameters:
        password - the password to hash
        accountName - the account name to use as the salt
        Returns:
        the hashed password
        Throws:
        EncryptionException
      • loadUsersIfNecessary

        protected void loadUsersIfNecessary()
        Load users if they haven't been loaded in a while.
      • loadUsersImmediately

        protected void loadUsersImmediately()
      • removeUser

        public void removeUser​(java.lang.String accountName)
                        throws AuthenticationException
        Removes the account of the specified accountName.
        Parameters:
        accountName - the account name to remove
        Throws:
        AuthenticationException - the authentication exception if user does not exist
      • saveUsers

        public void saveUsers()
                       throws AuthenticationException
        Saves the user database to the file system. In this implementation you must call save to commit any changes to the user file. Otherwise changes will be lost when the program ends.
        Throws:
        AuthenticationException - if the user file could not be written
      • verifyAccountNameStrength

        public void verifyAccountNameStrength​(java.lang.String newAccountName)
                                       throws AuthenticationException
        Ensures that the account name passes site-specific complexity requirements, like minimum length.

        This implementation simply verifies that account names are at least 5 characters long. This helps to defeat a brute force attack, however the real strength comes from the name length and complexity.

        Parameters:
        newAccountName -
        Throws:
        AuthenticationException - if account name does not meet complexity requirements
      • verifyPasswordStrength

        public void verifyPasswordStrength​(java.lang.String oldPassword,
                                           java.lang.String newPassword,
                                           User user)
                                    throws AuthenticationException
        Ensures that the password meets site-specific complexity requirements, like length or number of character sets. This method takes the old password so that the algorithm can analyze the new password to see if it is too similar to the old password. Note that this has to be invoked when the user has entered the old password, as the list of old credentials stored by ESAPI is all hashed. Additionally, the user object is taken in order to verify the password and account name differ.

        This implementation checks: - for any 3 character substrings of the old password - for use of a length * character sets > 16 (where character sets are upper, lower, digit, and special jtm - 11/16/2010 - added check to verify pw != username (fix for http://code.google.com/p/owasp-esapi-java/issues/detail?id=108)

        Parameters:
        oldPassword - the old password
        newPassword - the new password
        user - the user
        Throws:
        AuthenticationException - if newPassword is too similar to oldPassword or if newPassword does not meet complexity requirements