AIRAVATA-2342 implement reset password
Project: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/repo Commit: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/commit/c62cb173 Tree: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/tree/c62cb173 Diff: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/diff/c62cb173 Branch: refs/heads/develop Commit: c62cb173c00e6c5cec1a4fad75f3fc13478e1f03 Parents: 5e50b51 Author: Marcus Christie <[email protected]> Authored: Mon May 22 16:31:49 2017 -0400 Committer: Marcus Christie <[email protected]> Committed: Mon May 22 16:31:49 2017 -0400 ---------------------------------------------------------------------- app/controllers/AccountController.php | 86 +++++++++----------- app/libraries/EmailUtilities.php | 12 ++- app/libraries/Keycloak/Keycloak.php | 6 +- .../Keycloak/KeycloakServiceProvider.php | 4 +- app/views/account/reset-password.blade.php | 2 +- 5 files changed, 53 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c62cb173/app/controllers/AccountController.php ---------------------------------------------------------------------- diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 8e54d42..7698ad3 100644 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -2,6 +2,8 @@ class AccountController extends BaseController { + const PASSWORD_VALIDATION = "required|min:6|max:48|regex:/^.*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@!$#*]).*$/"; + const PASSWORD_VALIDATION_MESSAGE = "Password needs to contain at least (a) One lower case letter (b) One Upper case letter and (c) One number (d) One of the following special characters - !@#$&*"; public function __construct() { @@ -17,13 +19,13 @@ class AccountController extends BaseController { $rules = array( "username" => "required|min:6", - "password" => "required|min:6|max:48|regex:/^.*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@!$#*]).*$/", + "password" => self::PASSWORD_VALIDATION, "confirm_password" => "required|same:password", "email" => "required|email", ); $messages = array( - 'password.regex' => 'Password needs to contain at least (a) One lower case letter (b) One Upper case letter and (c) One number (d) One of the following special characters - !@#$&*', + 'password.regex' => self::PASSWORD_VALIDATION_MESSAGE, ); $validator = Validator::make(Input::all(), $rules, $messages); @@ -273,27 +275,13 @@ class AccountController extends BaseController CommonUtilities::print_error_message("Please provide a valid username"); return View::make("account/forgot-password"); }else{ - $wsisConfig = Config::get('pga_config.wsis'); - if( $wsisConfig['tenant-domain'] == "") - $username = $username; - else - $username = $username . "@" . $wsisConfig['tenant-domain']; try{ - $key = WSIS::validateUser(Input::get("userAnswer"),Input::get("imagePath"),Input::get("secretKey"), $username); - if(!empty($key)){ - $result = WSIS::sendPasswordResetNotification($username, $key); - if($result===true){ - CommonUtilities::print_success_message("Password reset notification was sent to your email account"); - return View::make("home"); - }else{ - CommonUtilities::print_error_message("Failed to send password reset notification email"); - return View::make("home"); - } - }else{ - CommonUtilities::print_error_message("Failed to validate the given username"); - return View::make("account/forgot-password"); - } + $user_profile = Keycloak::getUserProfile($username); + EmailUtilities::sendPasswordResetEmail($username, $user_profile["firstname"], $user_profile["lastname"], $user_profile["email"]); + CommonUtilities::print_success_message("Password reset notification was sent to your email account"); + return View::make("home"); }catch (Exception $ex){ + Log::error($ex); CommonUtilities::print_error_message("Password reset operation failed"); return View::make("home"); } @@ -328,28 +316,13 @@ class AccountController extends BaseController public function resetPassword() { - $confirmation = Input::get("confirmation"); - $username = Input::get("username"); - if(empty($username) || empty($confirmation)){ + $code = Input::get("code", Input::old("code")); + $username = Input::get("username", Input::old("username")); + if(empty($username) || empty($code)){ return View::make("home"); }else{ - $wsisConfig = Config::get('pga_config.wsis'); - if( $wsisConfig['tenant-domain'] == "") - $username = $username; - else - $username = $username . "@" . $wsisConfig['tenant-domain']; - try{ - $key = WSIS::validateConfirmationCode($username, $confirmation); - if(!empty($key)){ - return View::make("account/reset-password", array("key" => $key, "username"=>$username)); - }else{ - return View::make("home"); - } - }catch (Exception $e){ - return View::make("home"); - } + return View::make("account/reset-password", array("code" => $code, "username"=>$username)); } - } public function confirmAccountCreation() @@ -393,7 +366,9 @@ class AccountController extends BaseController $mail = new PHPMailer; $mail->isSMTP(); - $mail->SMTPDebug = 3; + // Note: setting SMTPDebug will cause output to be dumped into the + // response, so only enable for testing purposes + // $mail->SMTPDebug = 3; $mail->Host = Config::get('pga_config.portal')['portal-smtp-server-host']; $mail->SMTPAuth = true; @@ -434,33 +409,46 @@ class AccountController extends BaseController public function resetPasswordSubmit() { $rules = array( - "new_password" => "required|min:6", + "new_password" => self::PASSWORD_VALIDATION, "confirm_new_password" => "required|same:new_password", ); + $messages = array( + 'password.regex' => self::PASSWORD_VALIDATION_MESSAGE, + ); - $validator = Validator::make(Input::all(), $rules); + $validator = Validator::make(Input::all(), $rules, $messages); if ($validator->fails()) { + Log::debug("validation failed", array($validator->messages())); return Redirect::to("reset-password") - ->withInput(Input::except('new_password', 'confirm)new_password')) + ->withInput(Input::except('new_password', 'confirm_new_password')) ->withErrors($validator); } - $key = $_POST['key']; + $code = $_POST['code']; $username = $_POST['username']; $new_password = $_POST['new_password']; try{ - $result = WSIS::resetPassword($username, $new_password, $key); + $verified = EmailUtilities::verifyPasswordResetCode($username, $code); + if (!$verified){ + CommonUtilities::print_error_message("Resetting user password operation failed. Please request to reset user password again."); + return View::make("home"); + } + + $admin_authz_token = Keycloak::getAdminAuthzToken(); + $tenant_id = Config::get('pga_config.wsis')['tenant-domain']; + + $result = IamAdminServices::resetUserPassword($admin_authz_token, $tenant_id, $username, $new_password); if($result){ CommonUtilities::print_success_message("User password was reset successfully"); - return View::make("account/login"); + return View::make("login"); }else{ CommonUtilities::print_error_message("Resetting user password operation failed"); - return View::make("account/home"); + return View::make("home"); } }catch (Exception $e){ CommonUtilities::print_error_message("Resetting user password operation failed"); - return View::make("account/home"); + return View::make("home"); } } http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c62cb173/app/libraries/EmailUtilities.php ---------------------------------------------------------------------- diff --git a/app/libraries/EmailUtilities.php b/app/libraries/EmailUtilities.php index c2d6741..541d9f2 100644 --- a/app/libraries/EmailUtilities.php +++ b/app/libraries/EmailUtilities.php @@ -5,7 +5,8 @@ class EmailUtilities { public static function sendVerifyEmailAccount($username, $firstName, $lastName, $email){ - $validTime = Config::get('pga_config.portal')['mail-verify-code-valid-time']; + $portalConfig = Config::get('pga_config.portal'); + $validTime = isset($portalConfig['mail-verify-code-valid-time']) ? $portalConfig['mail-verify-code-valid-time'] : 30; $code = uniqid(); Cache::put('PGA-VERIFY-EMAIL-' . $username, $code, $validTime); @@ -32,7 +33,8 @@ class EmailUtilities } public static function sendPasswordResetEmail($username, $firstName, $lastName, $email){ - $validTime = Config::get('pga_config.portal')['mail-verify-code-valid-time']; + $portalConfig = Config::get('pga_config.portal'); + $validTime = isset($portalConfig['mail-verify-code-valid-time']) ? $portalConfig['mail-verify-code-valid-time'] : 30; $code = uniqid(); Cache::put('PGA-RESET-PASSWORD-' . $username, $code, $validTime); @@ -40,7 +42,7 @@ class EmailUtilities $subject = $emailTemplates->password_reset->subject; $body = trim(implode($emailTemplates->password_reset->body)); - $body = str_replace("\$url", URL::to('/'). '/resetPassword?username=' . $username . '&code='.$code, $body); + $body = str_replace("\$url", URL::to('/'). '/reset-password?username=' . urlencode($username) . '&code='.urlencode($code), $body); $body = str_replace("\$firstName", $firstName, $body); $body = str_replace("\$lastName", $lastName, $body); $body = str_replace("\$validTime", $validTime, $body); @@ -63,7 +65,9 @@ class EmailUtilities $mail = new PHPMailer(); $mail->isSMTP(); - $mail->SMTPDebug = 3; + // Note: setting SMTPDebug will cause output to be dumped into the + // response, so only enable for testing purposes + // $mail->SMTPDebug = 3; $mail->Host = Config::get('pga_config.portal')['portal-smtp-server-host']; $mail->SMTPAuth = true; http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c62cb173/app/libraries/Keycloak/Keycloak.php ---------------------------------------------------------------------- diff --git a/app/libraries/Keycloak/Keycloak.php b/app/libraries/Keycloak/Keycloak.php index dfa8f0c..6a7ecad 100644 --- a/app/libraries/Keycloak/Keycloak.php +++ b/app/libraries/Keycloak/Keycloak.php @@ -24,6 +24,7 @@ class Keycloak { private $base_endpoint_url; private $admin_username; private $admin_password; + private $gateway_id; // API clients private $role_mapper; @@ -34,7 +35,7 @@ class Keycloak { * Constructor * */ - public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret, $callback_url, $cafile_path, $verify_peer, $base_endpoint_url, $admin_username, $admin_password) { + public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret, $callback_url, $cafile_path, $verify_peer, $base_endpoint_url, $admin_username, $admin_password, $gateway_id) { $this->realm = $realm; $this->openid_connect_discovery_url = $openid_connect_discovery_url; @@ -46,6 +47,7 @@ class Keycloak { $this->base_endpoint_url = $base_endpoint_url; $this->admin_username = $admin_username; $this->admin_password = $admin_password; + $this->gateway_id = $gateway_id; $this->role_mapper = new RoleMapper($base_endpoint_url, $admin_username, $admin_password, $verify_peer); $this->roles = new Roles($base_endpoint_url, $admin_username, $admin_password, $verify_peer); @@ -402,7 +404,7 @@ class Keycloak { $access_token = KeycloakUtil::getAPIAccessToken($this->base_endpoint_url, $this->realm, $this->admin_username, $this->admin_password, $this->verify_peer); $authzToken = new \Airavata\Model\Security\AuthzToken(); $authzToken->accessToken = $access_token; - $authzToken->claimsMap['gatewayID'] = $this->realm; + $authzToken->claimsMap['gatewayID'] = $this->gateway_id; $authzToken->claimsMap['userName'] = $this->admin_username; return $authzToken; } http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c62cb173/app/libraries/Keycloak/KeycloakServiceProvider.php ---------------------------------------------------------------------- diff --git a/app/libraries/Keycloak/KeycloakServiceProvider.php b/app/libraries/Keycloak/KeycloakServiceProvider.php index 530d446..14971fd 100644 --- a/app/libraries/Keycloak/KeycloakServiceProvider.php +++ b/app/libraries/Keycloak/KeycloakServiceProvider.php @@ -33,6 +33,7 @@ class KeycloakServiceProvider extends ServiceProvider { $this->app['keycloak'] = $this->app->share(function($app) { $identityServerConfig = Config::get('pga_config.wsis'); + $airavataConfig = Config::get('pga_config.airavata'); return new Keycloak( $identityServerConfig['tenant-domain'], // TODO: we can derive this from tenant-domain and service-url @@ -44,7 +45,8 @@ class KeycloakServiceProvider extends ServiceProvider { $identityServerConfig['verify-peer'], $identityServerConfig['service-url'], $identityServerConfig['admin-username'], - $identityServerConfig['admin-password'] + $identityServerConfig['admin-password'], + $airavataConfig['gateway-id'] ); }); http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c62cb173/app/views/account/reset-password.blade.php ---------------------------------------------------------------------- diff --git a/app/views/account/reset-password.blade.php b/app/views/account/reset-password.blade.php index c830f06..7bc07e0 100644 --- a/app/views/account/reset-password.blade.php +++ b/app/views/account/reset-password.blade.php @@ -17,7 +17,7 @@ <form role="form" method="POST" action="{{ URL::to('/') }}/reset-password"> <div class="form-group form-horizontal"> <input name="username" type="hidden" value="{{$username}}" class="form-control"/> - <input name="key" type="hidden" value="{{$key}}" class="form-control"/> + <input name="code" type="hidden" value="{{{$code}}}" class="form-control"/> <div class="form-group required"><label class="control-label">Password</label> <div><input class="form-control" id="new_password" minlength="6" name="new_password" placeholder="New Password"
