Change Password for SUSI Accounts Using Access Token and Email-ID
In this blog, I discuss how the SUSI server synchronizes with SUSI Accounts and SUSI webchat for users to Change Password. When a user logs in, the clients store the email id of the user along with the access token in cookies. These are stored once the client gets a positive login response from the server. Both of these are required at the time of making the final call. Web clients store the email id and access token in the following way.
cookies.set('loggedIn', loggedIn, { path: '/', maxAge: time }); cookies.set('emailId', email, { path: '/', maxAge: time });
First, the client has to ask the user to enter their current password. A javascript test is used to validate that at least 6 characters must be entered by the user. A similar test is run on the new password. But while confirming the password, client checks whether the user has entered the same password as new password or not. These are just the basics. In next stage (which is achieved only when all the above conditions are met), client encodes the email id (which it gets from cookies), current password, new password and the access token (which it again extracts from cookies).
Now, Client just has to make an ajax request to the server. The response is processed and sent back to the client. Let us now look at PasswordChange Servlet.
The base user role is defined as USER. Initial steps of the servlet are to extract the values form the request it receives. The values extracted from the request are in turn used to make a client’s identity. Before that, server checks if current and new password have same values or not. If not, then server returns a JSON response to user stating, “Your current password and new password matches”. Otherwise, it will continue its control flow as it is. Look at the code snippet below:
if(password.equals(newpassword)){ result.put("message", "Your current password and new password matches"); result.put("accepted", false); return new ServiceResponse(result); }
The reader here may think that they have discovered a hack. But they have not. Why? Because this is just the first step. In later stages, the hash of passwords are used to match to see whether the passwords match or not. To obtain a proper client identity, first a Client credentials object is made with support from the email id which is received in ‘changepassword’ attribute. Using the ClientCredentials object made above, an object of Authentication class is made. This object uses a method defined in its class to return a valid client identity. Using the client identity, value of password hash is extracted from the database along with the salt used to hash the password. If any error is encountered while extracting the client’s password hash value and/or salt value, an error is thrown towards the client, with a message stating “invalid credentials”.
ClientCredential pwcredential = new ClientCredential(ClientCredential.Type.passwd_login, useremail); Authentication authentication = DAO.getAuthentication(pwcredential); ClientCredential emailcred = new ClientCredential(ClientCredential.Type.passwd_login, authentication.getIdentity().getName()); ClientIdentity identity = authentication.getIdentity(); String passwordHash; String salt; try { passwordHash = authentication.getString("passwordHash"); salt = authentication.getString("salt"); } catch (Throwable e) { Log.getLog().info("Invalid password try for user: " + identity.getName() + " from host: " + post.getClientHost() + " : password or salt missing in database"); result.put("message", "invalid credentials"); throw new APIException(422, "Invalid credentials"); }
Using the same salt value that was used earlier, a hash for password entered by the user will be generated which now matches the previous value. This is the point where the hack you were thinking you found, failed. Again the server throws an error message if user’s credential did not match. Passwords are hard to handle and easy to guess. So here we have used quite many tests before changing them. Users are not allowed to use their email id as a password as well.
If the server is clear on all the above facts and tests, It finally generates a new hashed value of the password received in the parameter ‘newpassword’ and replaces the old hash value with the new one. To notify the clients that password change exited with a success response, it sends a JSON object with message “Your password has been changed!” and accepted flag set to true.
if (DAO.hasAuthentication(emailcred)) { Authentication emailauth = DAO.getAuthentication(emailcred); String newsalt = createRandomString(20); emailauth.remove("passwordHash"); emailauth.put("passwordHash", getHash(newpassword, salt)); Log.getLog().info("password change for user: " + identity.getName() + " via newpassword from host: " + post.getClientHost()); result.put("message", "Your password has been changed!"); result.put("accepted", true); }
Additional Resources:
- Stackoverflow, post by user erickson about How can I hash a password in java
- Blog post on blog.sodhanalibrary.com by Srinivas Dasari about How to implement Change Password in a JAVA server
Wikipedia article: What is DAO?
You must be logged in to post a comment.