private function _forgotPassword2(){
		$view = $this->getView();
		$request = $this->getPageRequest();

		$genericauth = new \Core\User\AuthDrivers\datastore();

		// Create a simple form to render.  This is better than doing it in the template.
		$form = new Form();
		$form->set('method', 'POST');
		$form->addElement('password', ['name' => 'p1', 'title' => 'Password', 'required' => true]);
		$form->addElement('password', ['name' => 'p2', 'title' => 'Confirm', 'required' => true]);
		$form->addElement('submit', ['name' => 'submit', 'value' => 'Set New Password']);

		$view->title = 'Forgot Password';
		$view->assign('step', 2);
		$view->assign('form', $form);
		$view->assign('requirements', $genericauth->getPasswordComplexityAsHTML());

		$n = $request->getParameter(0);

		/** @var $nonce NonceModel */
		$nonce = NonceModel::Construct($n);

		if(!$nonce->isValid()){
			SystemLogModel::LogSecurityEvent('/user/forgotpassword/confirm', 'Failed Forgot Password. Invalid nonce requested: [' . $n . ']');
			\Core\set_message('t:MESSAGE_ERROR_USER_LOGIN_EMAIL_NOT_FOUND');
			\core\redirect('/');
			return;
		}

		$nonce->decryptData();
		$data = $nonce->get('data');

		/** @var UserModel $u */
		$u = UserModel::Construct($data['user']);
		if(!$u){
			SystemLogModel::LogSecurityEvent('/user/forgotpassword/confirm', 'Failed Forgot Password. Invalid user account requested: [' . $data['user'] . ']');
			\Core\set_message('t:MESSAGE_ERROR_USER_LOGIN_EMAIL_NOT_FOUND');
			\core\redirect('/');
			return;
		}


		if($request->isPost()){
			// Validate the password.
			if($_POST['p1'] != $_POST['p2']){
				\Core\set_message('t:MESSAGE_ERROR_USER_REGISTER_PASSWORD_MISMATCH');
				return;
			}

			// Else, try to set it... the user model will complain if it's invalid.
			try{
				$u->enableAuthDriver('datastore');
				/** @var \Core\User\AuthDrivers\datastore $auth */
				$auth = $u->getAuthDriver('datastore');

				$auth->setPassword($_POST['p1']);
				$u->save();
				// NOW I can invalidate that nonce!
				$nonce->markUsed();
				SystemLogModel::LogSecurityEvent('/user/forgotpassword/confirm', 'Reset password successfully!', null, $u->get('id'));
				\Core\set_message('Reset password successfully', 'success');
				if($u->get('active')){
					\Core\Session::SetUser($u);
				}
				\core\redirect('/');
			}
			catch(ModelValidationException $e){
				SystemLogModel::LogSecurityEvent('/user/forgotpassword/confirm', 'Failed Forgot Password. ' . $e->getMessage(), null, $u->get('id'));
				\Core\set_message($e->getMessage(), 'error');
				return;
			}
			catch(Exception $e){
				SystemLogModel::LogSecurityEvent('/user/forgotpassword/confirm', 'Failed Forgot Password. ' . $e->getMessage(), null, $u->get('id'));
				\Core\set_message((DEVELOPMENT_MODE ? $e->getMessage() : 'An unknown error occured'), 'error');
				return;
			}
		}
	}
Beispiel #2
0
 /**
  * Shorthand function to validate and "mark as used" a Nonce key.
  * @param string            $key  The nonce key to validate
  * @param string|null|mixed $hash An optional hash to validate also
  *
  * @return boolean
  */
 public static function ValidateAndUse($key, $hash = null)
 {
     /** @var $nonce NonceModel */
     $nonce = NonceModel::Construct(strtolower($key));
     if ($nonce->isValid($hash)) {
         $nonce->markUsed();
         return true;
     } else {
         return false;
     }
 }
	/**
	 * The actual Core registration page.
	 *
	 * This renders all the user's configurable options at registration.
	 */
	public function register2(){
		$view    = $this->getView();
		$request = $this->getPageRequest();
		$manager = \Core\user()->checkAccess('p:/user/users/manage'); // Current user an admin?

		// Anonymous users should have access to this if it's allow public.
		if(!\Core\user()->exists() && !ConfigHandler::Get('/user/register/allowpublic')){
			return View::ERROR_BADREQUEST;
		}

		// Authenticated users must check the permission to manage users.
		if(\Core\user()->exists() && !$manager){
			return View::ERROR_ACCESSDENIED;
		}

		/** @var NonceModel $nonce */
		$nonce = NonceModel::Construct($request->getParameter(0));
		if(!$nonce->isValid()){
			\Core\set_message('Invalid nonce token, please try again.', 'error');
			\Core\go_back();
		}
		$nonce->decryptData();
		$data = $nonce->get('data');

		if(!isset($data['user']) || !($data['user'] instanceof UserModel)){
			if(DEVELOPMENT_MODE){
				\Core\set_message('Your nonce does not include a "user" key.  Please ensure that this is set to a non-existent UserModel object!', 'error');
			}
			else{
				\Core\set_message('Invalid login type, please try again later.', 'error');
			}
			\Core\go_back();
		}

		/** @var UserModel $user */
		$user = $data['user'];

		$form = \Core\User\Helper::GetForm($user);
		
		// If the total number of form elements here are only 2, then only the user object and submit button are present.
		// Instead of showing the form, auto-submit to that destination.
		if(sizeof($form->getElements()) <= 2){
			$user->setDefaultGroups();
			$user->setDefaultMetaFields();
			$user->setDefaultActiveStatuses();
			$user->generateNewApiKey();
			$user->save();

			// User created... make a log of this!
			\SystemLogModel::LogSecurityEvent('/user/register', 'User registration successful', null, $user->get('id'));

			// Send a thank you for registering email to the user.
			try{
				$user->sendWelcomeEmail();
			}
			catch(\Exception $e){
				\Core\ErrorManagement\exception_handler($e);
				\Core\set_message('t:MESSAGE_ERROR_CANNOT_SEND_WELCOME_EMAIL');
			}

			// "login" this user if not already logged in.
			if(!\Core\user()->exists()){
				if($user->get('active')){
					$user->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT));
					$user->save();
					\Core\Session::SetUser($user);
				}
				\Core\set_message('t:MESSAGE_SUCCESS_CREATED_USER_ACCOUNT');

				if(($overrideurl = \HookHandler::DispatchHook('/user/postlogin/getredirecturl'))){
					// Allow an external script to override the redirecting URL.
					$url = $overrideurl;
				}
				elseif($form->getElementValue('redirect')){
					// The preferred default redirect method.
					// This is set from /user/register2, which is in turn passed in, (hopefully), by the original callee registration page.
					$url = $form->getElementValue('redirect');
				}
				elseif(strpos(REL_REQUEST_PATH, '/user/register') === 0){
					// If the user came from the registration page, get the page before that.
					$url = '/';
				}
				else{
					// else the registration link is now on the same page as the 403 handler.
					$url = REL_REQUEST_PATH;
				}

				\Core\redirect($url);
			}
			// It was created administratively; redirect there instead.
			else{
				\Core\set_message('t:MESSAGE_SUCCESS_CREATED_USER_ACCOUNT');
				\Core\redirect('/user/admin');
			}
		}
		
		$form->addElement('hidden', ['name' => 'redirect', 'value' => $data['redirect']]);

		$view->title = 'Complete Registration';
		$view->assign('form', $form);
	}
 /**
  * Page to enable Facebook logins for user accounts.
  *
  * @return int|null|string
  */
 public function enable()
 {
     $request = $this->getPageRequest();
     $auths = \Core\User\Helper::GetEnabledAuthDrivers();
     if (!isset($auths['facebook'])) {
         // Facebook isn't enabled, simply redirect to the home page.
         \Core\redirect('/');
     }
     if (!FACEBOOK_APP_ID) {
         \Core\redirect('/');
     }
     if (!FACEBOOK_APP_SECRET) {
         \Core\redirect('/');
     }
     // If it was a POST, then it should be the first page.
     if ($request->isPost()) {
         $facebook = new Facebook(['appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET]);
         // Did the user submit the facebook login request?
         if (isset($_POST['login-method']) && $_POST['login-method'] == 'facebook' && $_POST['access-token']) {
             try {
                 $facebook->setAccessToken($_POST['access-token']);
                 /** @var int $fbid The user ID from facebook */
                 $fbid = $facebook->getUser();
                 /** @var array $user_profile The array of user data from Facebook */
                 $user_profile = $facebook->api('/me');
             } catch (Exception $e) {
                 \Core\set_message($e->getMessage(), 'error');
                 \Core\go_back();
                 return null;
             }
             // If the user is logged in, then the verification logic is slightly different.
             if (\Core\user()->exists()) {
                 // Logged in users, the email must match.
                 if (\Core\user()->get('email') != $user_profile['email']) {
                     \Core\set_message('Your Facebook email is ' . $user_profile['email'] . ', which does not match your account email!  Unable to link accounts.', 'error');
                     \Core\go_back();
                     return null;
                 }
                 $user = \Core\user();
             } else {
                 /** @var \UserModel|null $user */
                 $user = UserModel::Find(['email' => $user_profile['email']], 1);
                 if (!$user) {
                     \Core\set_message('No local account found with the email ' . $user_profile['email'] . ', please <a href="' . \Core\resolve_link('/user/register') . '"create an account</a> instead.', 'error');
                     \Core\go_back();
                     return null;
                 }
             }
             // Send an email with a nonce link that will do the actual activation.
             // This is a security feature so just anyone can't link another user's account.
             $nonce = NonceModel::Generate('20 minutes', null, ['user' => $user, 'access_token' => $_POST['access-token']]);
             $email = new Email();
             $email->to($user->get('email'));
             $email->setSubject('Facebook Activation Request');
             $email->templatename = 'emails/facebook/enable_confirmation.tpl';
             $email->assign('link', \Core\resolve_link('/facebook/enable/' . $nonce));
             if ($email->send()) {
                 \Core\set_message('An email has been sent to your account with a link enclosed.  Please click on that to complete activation within twenty minutes.', 'success');
                 \Core\go_back();
                 return null;
             } else {
                 \Core\set_message('Unable to send a confirmation email, please try again later.', 'error');
                 \Core\go_back();
                 return null;
             }
         }
     }
     // If there is a nonce enclosed, then it should be the second confirmation page.
     // This is the one that actually performs the action.
     if ($request->getParameter(0)) {
         /** @var NonceModel $nonce */
         $nonce = NonceModel::Construct($request->getParameter(0));
         if (!$nonce->isValid()) {
             \Core\set_message('Invalid key requested.', 'error');
             \Core\redirect('/');
             return null;
         }
         $nonce->decryptData();
         $data = $nonce->get('data');
         /** @var UserModel $user */
         $user = $data['user'];
         try {
             $facebook = new Facebook(['appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET]);
             $facebook->setAccessToken($data['access_token']);
             $facebook->getUser();
             $facebook->api('/me');
         } catch (Exception $e) {
             \Core\set_message($e->getMessage(), 'error');
             \Core\redirect('/');
             return null;
         }
         $user->enableAuthDriver('facebook');
         /** @var \Facebook\UserAuth $auth */
         $auth = $user->getAuthDriver('facebook');
         $auth->syncUser($data['access_token']);
         \Core\set_message('Linked Facebook successfully!', 'success');
         // And log the user in!
         if (!\Core\user()->exists()) {
             $user->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT));
             $user->save();
             \Core\Session::SetUser($user);
         }
         \Core\redirect('/');
         return null;
     }
 }
Beispiel #5
0
	/**
	 * Validate the verification email, part 2 of confirmation.
	 *
	 * @param string $nonce
	 * @param string $signature
	 *
	 * @return bool|string
	 */
	public static function ValidateVerificationResponse($nonce, $signature) {
		/** @var \NonceModel $nonce */
		$nonce = \NonceModel::Construct($nonce);

		if(!$nonce->isValid()){
			\SystemLogModel::LogSecurityEvent('/user/gpg/verified', 'FAILED to verify key (Invalid NONCE)', null);
			return 'Invalid nonce provided!';
		}

		// Now is where the real fun begins.

		$nonce->decryptData();

		$data = $nonce->get('data');

		/** @var \UserModel $user */
		$user   = \UserModel::Construct($data['user']);
		$gpg    = new \Core\GPG\GPG();
		$key    = $data['key'];
		$pubKey = $gpg->getKey($key);

		try{
			$sig = $gpg->verifyDataSignature($signature, $data['sentence']);
		}
		catch(\Exception $e){
			\SystemLogModel::LogSecurityEvent('/user/gpg/verified', 'FAILED to verify key ' . $key, null, $user->get('id'));
			return 'Invalid signature';
		}

		$fpr = str_replace(' ', '', $sig->fingerprint); // Trim spaces.
		if($key != $fpr && $key != $sig->keyID){
			// They must match!
			\SystemLogModel::LogSecurityEvent('/user/gpg/verified', 'FAILED to verify key ' . $key, null, $user->get('id'));
			return 'Invalid signature';
		}

		// Otherwise?
		$user->enableAuthDriver('gpg');
		$user->set('gpgauth_pubkey', $fpr);

		// Was there a photo attached to this public key?
		if(sizeof($pubKey->getPhotos()) > 0){
			$p = $pubKey->getPhotos();
			// I just want the first.
			/** @var \Core\Filestore\File $p */
			$p = $p[0];

			$localFile = \Core\Filestore\Factory::File('public/user/avatar/' . $pubKey->fingerprint . '.' . $p->getExtension());
			$p->copyTo($localFile);
			$user->set('avatar', $localFile->getFilename(false));
		}
		
		$user->save();

		$nonce->markUsed();

		\SystemLogModel::LogSecurityEvent('/user/gpg/verified', 'Verified key ' . $fpr, null, $user->get('id'));

		return true;
	}