Reset Password as the name suggests is one of the features in the SUSI iOS app which allows a user to change his/her password when they are logged in. This feature was added because a user would want to change his password sometimes to prevent unauthorized access or make his account security stronger. We can find many popular apps online such as Facebook, Gmail, which allow the user to reset their password. The way this is done is pretty simple and all we need from the user is his current and the new password he/she wants to set. In this blog post, I am going to explain step by step how this is implemented in the iOS client.
Implementation
The option to Reset Password is provided to the user under the Settings Controller. On selecting the row, the user is presented with another view which asks the user for his/her current password, new password, and another field to confirm the newly entered password.
First, the user needs to provide his current password followed by the new password. The user’s current password is required just to authenticate that the account’s owner is requesting the password change. The new password field is followed by another field called confirm password just to make sure there isn’t any typo.
Now when the field is filled, the user clicks the `Reset password` button at the bottom. What happens here is, first, the fields are validated to ensure the correct length of the passwords followed by an API request to update the same. The endpoint for the same is as below:
http://api.susi.ai/aaa/changepassword.json?changepassword=user_email&password=current _pass&newpassword=new_pass&access_token=user_access_token
This endpoint requires 3 things:
- Current Password
- New Password
- User’s email
- Access Token obtained at the time of login
func validatePassword() -> [Bool:String] { if let newPassword = newPasswordField.text, let confirmPassword = confirmPasswordField.text { if newPassword.characters.count > 5 { if newPassword == confirmPassword { return [true: ""] } else { return [false: ControllerConstants.passwordDoNotMatch] } } else { return [false: ControllerConstants.passwordLengthShort] } } return [false: Client.ResponseMessages.ServerError] }
Initially, we were not saving the user’s email, so we added the user’s email to the User’s object which is saved at the time of login.
if var userData = results { userData[Client.UserKeys.EmailOfAccount] = user.email UserDefaults.standard.set(userData, forKey: ControllerConstants.UserDefaultsKeys.user) self.saveUserGlobally(user: currentUser) }
At last, the API call is made which is implemented as below:
let params = [ Client.UserKeys.AccessToken: user.accessToken, Client.UserKeys.EmailOfAccount: user.emailID, Client.UserKeys.Password: currentPasswordField.text ?? "", Client.UserKeys.NewPassword: newPasswordField.text ?? "" ] Client.sharedInstance.resetPassword(params as [String : AnyObject], { (_, message) in DispatchQueue.main.async { self.view.makeToast(message) self.setUIActive(active: false) } })
Below is the final UI.
Reference
- Alamofire Docs for making network calls: https://github.com/Alamofire/Alamofire
- Tutorial on how to create static table view cells: https://www.appcoda.com/ios-static-table-view-storyboard/
- Pull Request for API reference: https://github.com/fossasia/susi_server/pull/352