CSC/ECE 517 Fall 2016/E1690 Improvements to password recovery and repeated login failures
E1690 Improvements to password recovery and repeated login failures
This wiki page is for the description of changes made under E1690 FinalProject for Fall 2016, CSC/ECE 517.
Background
Expertiza is an Open Source web application developed on Ruby On Rails platform. It is a platform which allows students to access assignments posted by the course instructor. Expertiza also allows students to select assignment topics, form teams and submit their work. It also allows them to review other students' submissions and improve their work based on the feedback provided. The instructor can look at the feedback provided by students and rate the student based on feedback provided for others work. It helps organize and upload assignments and reducing the manual review process and helps students provide a peer feedback and also learn from reviewed work. Teams can be chosen by the student or can be assigned automatically based on a priority list inputted alongside each topic available for the assignment.
Project Description
Our final project consists of two cases of the password recovery process. Use case 1, Currently, when a user forgets his/her password and wants to reset the password, Expertiza system randomly generates a new password and sends the password as plain text in a email. It is normally considered as a bad practice to send passwords as paint text. We are replacing this practice by sending a reset password link that expires after a certain amount of time. Use case 2 deals with when a user enters wrong credentials. Currently, the login page simply shows an error. Irrespective of the number of times that a user enters wrong login credentials, the system produces a general error message. We are going to be replacing this system by using the alternative 2, using a captcha to verify that the user is indeed a human and not a bot trying to run a brute force attack on the system. This will add the needed layer of security and should serve as a great solution. Below are more details of our implementation.
Files Created/Modified
As a part of the project the files mentioned below were the ones, created/modified as needed.
- auth_controller.rb
- password_retrieval_controller.rb
- password_reset.rb (model)
- reset_password.html.erb (view)
Implementation
We have implemented the new password recovery system by sending a reset password link to the user's email. This link will be comprised of a generated path to a newly created view for resetting the password with a uniquely randomly generated token. This parameter will be a string attribute of a new model reset_password. This link will expire after a given amount of time. Using logic to compare the createdAt timestamp as well as the current time, the application would decide if the token is expired or not.
We are also implementing a backoff system that will require the user to complete a smart captcha after 3 failed attempts. This smart captcha will be generated through Recaptcha gem and the user will then be redirected to the login page after successfully changing the password. This will ensure that the system is not vulnerable to Brute Force attacks as well as bots.
Password Reset
Model Schema
Model: password_reset.rb
Attributes
- -id(autogenerated) -integer
- -unique_tokenhash -String
- -createdAt (autogenerated) -timestamp
- -user_email -string
Model Details
When the user clicks on reset password, it will redirect to a view that has an input to enter the email address of the user. Reset password button will generate a random token (Long string) which will be hashed and saved in the database of the model reset_password. An expiration date will be generated and saved along with the user_id by looking up the user table using email id. The unhashed Token value will be appended on the url emailed to the user for the password reset page.
www.expertiza.com/password_edit/check_reset_url?token=ZB71yObR-Tdssg-@#%
On clicking the url, the link will take you to password_retrieval_controller that will direct you to a reset page. Before redirecting , the controller checks the parameters in the link (username and token) and makes sure that token username pair exists and not expired. Token from the params will be hashed again and checked with the DB. This prevents an attacker who has read access to the database from making a token for some other user, reading the value that was sent in the email, then sending the same value himself. Once the controller completes all the necessary checks, it will redirect to a reset password page for that specific user (based on the user_id / username)
Each Email Address can have only one active token saved in the database. Every time a new token is generated, it will replace the existing one which ensures that only one reset link is available. Also, this will make sure that DB content of password_reset can never exceed the number of users registered in the application. This eliminates the need to clear out expired Tokens.
Captcha
The project will be using reCAPTCHA gem. reCAPTCHA is a free service from Google that helps protect websites from spam and abuse. A “CAPTCHA” is a test to tell humans and robot apart. This kind of service is important for websites or web applications with lots of user generated content. The test is easy for a human to solve, but hard for bots and other malicious software to figure out.
After 3 failed Login attempts, a captcha would appear to make sure that a bot or a malicious software is not trying to attempt login using brute force.
Gem File
Adding this line to the Gem file allows us to have access to the recaptcha gem.
gem "recaptcha", require: "recaptcha/rails"
Registration
To let reCAPTCHA work normally, we need to register the domains that the project will be deployed on [reCAPTCHA official website][1]. Currently, we can use it on expertiza.com, 0.0.0.0, and localhost. Once the registration is done, two keys will be automatically generated -- site key and secret key. The site key is used in HTML, and the secret key is used for communication between the site and Google.
Add reCAPTCHA to codes
To show reCAPTCHA in webpages is easy, all we need to do is add this code to _form.html.erb
<div class="g-recaptcha" data-sitekey="6Lci0wwUAAAAAB69GEpUbEmkIu4frJ8dgqx90o7b"></div>
And, we need to create a recaptcha.rb file into config/initializers folder, which stores our site key and secret key.
Recaptcha.configure do |config| config.site_key = '6Lci0wwUAAAAAB69GEpUbEmkIu4frJ8dgqx90o7b' config.secret_key = '6Lci0wwUAAAAAIZ***********RNeDD6e84q9XlM' end
Backoff System
In Auth Controller we added the following code. The variable @@attempts acts as a counter to track the amount of invalid login attempts a user makes. By utilizing the existing login code we were able to place the increment code. Once the attempts variable is greater than or equal to 3 we then force the user to use the recaptcha question in addition to their correct logic credentials. Once the new requirements to login are satisfied the user is redirected to the password retrieval, otherwise they are redirected to the root screen with the captcha question.
@@attemps = 0 def login if request.get? AuthController.clear_session(session) else user = User.find_by_login(params[:login][:name]) if user and user.valid_password?(params[:login][:password]) after_login(user) else @@attemps = @@attemps + 1 logger.warn "Failed login attempt." flash[:error] = "Your username or password is incorrect." if @@attemps >= 3 ##User entered invalid login credentials at least 3 times if verify_recaptcha(model: @user) @@attemps = 0 redirect_to controller: 'password_retrieval', action: 'forgotten' end else redirect_to root_path end end end end # def login
Testing
To run the Rspecs test cases:
rspec path_to_expertiza/spec/controllers/password_retrieval_controller_spec.rb
To test from UI:
i) Enter the wrong password on login page three consecutive times, you will shown with Google Captcha for the fourth attempt. ii) On entering the password, wrong the fourth time you will be redirected to "forgot password" page. It can also be reached by clicking "forgot password" page on login page. iii) Enter the email Id, for which new password has to be set. On clicking "Request password" you will get a mail with password reset link. iv) Clicking on the password reset link, you will be redirected to password reset page where you can set your new password.
Here is a short video demonstrating the same.