Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explains activation code #1277

Merged
merged 4 commits into from
Oct 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libraries/Ion_auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public function register($identity, $password, $email, $additional_data = [], $g
return FALSE;
}

// deactivate so the user much follow the activation flow
// deactivate so the user must follow the activation flow
$deactivate = $this->ion_auth_model->deactivate($id);

// the deactivate method call adds a message, here we need to clear that
Expand Down
105 changes: 62 additions & 43 deletions models/Ion_auth_model.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,31 @@ class Ion_auth_model extends CI_Model

/**
* activation code
*
*
* Set by deactivate() function
* Also set on register() function, if email_activation
* option is activated
*
* This is the value devs should give to the user
* (in an email, usually)
*
* It contains the *user* version of the activation code
* It's a value of the form "selector.validator"
*
* This is not the same activation_code as the one in DB.
* The DB contains a *hashed* version of the validator
* and a selector in another column.
*
* THe selector is not private, and only used to lookup
* the validator.
*
* The validator is private, and to be only known by the user
* So in case of DB leak, nothing could be actually used.
*
* @var string
*/
public $activation_code;

/**
* forgotten password key
*
* @var string
*/
public $forgotten_password_code;

/**
* new password
*
Expand Down Expand Up @@ -359,11 +372,42 @@ public function rehash_password_if_needed($hash, $identity, $password)
}
}

/**
* Get a user by its activation code
*
* @param bool $user_code the activation code
* It's the *user* one, containing "selector.validator"
* the one you got in activation_code member
*
* @return bool|object
* @author Indigo
*/
public function get_user_by_activation_code($user_code)
{
// Retrieve the token object from the code
$token = $this->_retrieve_selector_validator_couple($user_code);

// Retrieve the user according to this selector
$user = $this->where('activation_selector', $token->selector)->users()->row();

if ($user)
{
// Check the hash against the validator
if ($this->verify_password($token->validator, $user->activation_code))
{
return $user;
}
}

return FALSE;
}

/**
* Validates and removes activation code.
*
* @param int|string $id
* @param bool $code if omitted, simply activate the user without check
* @param int|string $id the user identifier
* @param bool $code the *user* activation code
* if omitted, simply activate the user without check
*
* @return bool
* @author Mathew
Expand All @@ -372,40 +416,14 @@ public function activate($id, $code = FALSE)
{
$this->trigger_events('pre_activate');

$token = $this->_retrieve_selector_validator_couple($code);

if ($token !== FALSE)
{
// A token was provided, we need to check it

$query = $this->db->select([$this->identity_column, 'activation_code'])
->where('activation_selector', $token->selector)
->where('id', $id)
->limit(1)
->get($this->tables['users']);

if ($query->num_rows() === 1)
{
$user = $query->row();

if ($this->verify_password($token->validator, $user->activation_code))
{
$data = [
'activation_selector' => NULL,
'activation_code' => NULL,
'active' => 1
];

$this->trigger_events('extra_where');
$this->db->update($this->tables['users'], $data, ['id' => $id]);
return TRUE;
}
}
if ($code !== FALSE) {
$user = $this->get_user_by_activation_code($code);
}
else
{
// A token was NOT provided, simply activate the user

// Activate if no code is given
// Or if a user was found with this code, and that it matches the id
if ($code === FALSE || ($user && $user->id === $id))
{
$data = [
'activation_selector' => NULL,
'activation_code' => NULL,
Expand Down Expand Up @@ -2644,6 +2662,7 @@ protected function _get_hash_algo()

/**
* Generate a random selector/validator couple
* This is a user code
*
* @param $selector_size int size of the selector token
* @param $validator_size int size of the validator token
Expand Down Expand Up @@ -2677,7 +2696,7 @@ protected function _generate_selector_validator_couple($selector_size = 40, $val
/**
* Retrieve remember cookie info
*
* @param $user_code string
* @param $user_code string A user code of the form "selector.validator"
*
* @return object
* ->selector simple token to retrieve the user in DB
Expand Down