Thursday, August 18, 2016

Writing a User Operation Event Listener in WSO2 Servers and Practical Usecases

From my previous post [1], I explained the concept of user operation event listeners in WSO2 products. In this post I will demonstrate how to write your own event listener for a real world scenario.

Here I take the usecase as printing audit logs for sensitive user management operations such as password reset, delete roles, delete users etc. When such event happens, we can print audit logs with the user who performed the operation to be traced later. However, you can refer the sample and implement your own usecases.

When writing a user operation event listener, you have to extend the org.wso2.carbon.user.core.common.AbstractUserOperationEventListener class and override the methods you need to add functionality. Here I have overridden all methods of the class and simply added audit logs for them to identify the user and the particular operation he is performing. The audit logs are printed in SERVER_HOME/repository/logs/audit.log file.

You can find the maven project in [2], build it and put it into the dropins [3] directory of the WSO2 server. I have written the sample to be supported for WSO2 Identity Server 5.1.0 version. However, if you want to use it in some other WSO2 server, you can simply modify the pom.xml file’s project dependency versions matching the same version packed in the product. If you want to just try out the sample, you can download the built jar file from [4].

Once you have put the jar file into dropins, restart the server. You can tail the audit.log file of the server to monitor how the user operation event listener prints logs that I have added.

Now if you login to the management console, you can see in the audit log following logs are printed.

Since the authenticate method is called here, the pre and post authenticate events are called respectively. Additionally we see the post event of getting user claim value. It should be due to retrieving some user claim during the authentication.

If you create a new user, we can see the pre and post event of addUser method is called. Here we see an audit log for addUser operation as well. It was coming from the server itself as add user operation is already writing to audit log for tracing purposes.

If you assign a role to the user, the respective pre and post events’ audit logs for updating the roles of a user can be seen.

In this sample I have added audit logs for all user operations in the listener. However in your usecase, you can do appropriate changes referring the source code of this sample.

There are many usecases where user operation event listeners are helpful. Following are some examples.

  1. Track user's’ password reset timestamp. For this, we can override the  doPostUpdateCredential method if the password is reset by the user himself or else we can override the method doPostUpdateCredentialByAdmin if the password is reset by an admin for a user.

  1. Send an email to a user when the user account is created. For this, we can override the doPostAddUser method and implement email sending functionality. We can get to know the user’s username inside the method. The email address of the user can be read from user’s claims.

  1. Track the last successful login attempt timestamp of a user. For this, we can override the doPostAuthenticate method and set the timestamp as a user’s claim.

  1. Handle account locking policies. For this, we can override the doPostAuthenticate method and increment the number of false login attempts as a user’s claim. Then in the doPreAuthenticate method, we can check if the maximum allowed false attempts count is reached and if so we can consider the user account is locked and block proceeding with authentication. Upon account is locked, you can reset the false attempt count of the user.
  1. Tracking user’s password history and avoid users using passwords that were set previously in the same account. For example we can track the last 3 passwords of the user and when the user tries to reset the password, we do not allow user to use a password from that he had set in last 3 passwords. In doPreUpdateCredential method, we can check the password value the user is trying to set and if it’s in the history we can stop proceeding with the operation. In the doPostUpdateCredential method, we can add the new password to the history.

Above are only se examples for usecases that you can implement using a custom user operation event listener. With the knowledge you have got now, you should be able to write your own implementation to support your requirements.


No comments:

Post a Comment