Some enhancements to token logins

This commit is contained in:
Deon George 2011-10-12 14:52:04 +11:00
parent 718c42be65
commit c419b50bac
3 changed files with 121 additions and 28 deletions

View File

@ -146,31 +146,58 @@ class Auth_OSB extends Auth_ORM {
* @return mixed The user
*/
private function _get_token_user($token) {
// This has been implemented, as we sometimes we seem to come here twice
static $user = NULL;
if (! is_null($user))
return $user;
$mmto = ORM::factory('module_method_token',array('token'=>$token));
$user = FALSE;
if ($mmto->loaded()) {
if ($mmto->date_expire < time()) {
if (! is_null($mmto->date_expire) AND $mmto->date_expire < time()) {
SystemMessage::add(array(
'title'=>_('Token Not Valid'),
'type'=>'warning',
'body'=>_('Token expired')));
// @todo Log the token deletion
Session::instance()->delete('token');
$mmto->delete();
} elseif (! is_null($mmto->uses) AND $mmto->uses < 1) {
SystemMessage::add(array(
'title'=>_('Token Not Valid'),
'type'=>'warning',
'body'=>_('Token expired')));
// @todo Log the token deletion
Session::instance()->delete('token');
$mmto->delete();
} else {
// Check that the token is for this URI
$mo = ORM::factory('module',array('name'=>Request::current()->controller()));
$mmo = ORM::factory('module_method',
array('name'=>Request::current()->directory() ? sprintf('%s_%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()));
$mmo = ORM::factory('module_method',array(
'module_id'=>$mo->id,
'name'=>Request::current()->directory() ? sprintf('%s_%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()
));
// Ignore the token if this is not the right method.
if ($mmo->id == $mmto->method_id) {
// @todo Implement single use tokens
// If this is a usage count token, reduce the count.
if (! is_null($mmto->uses))
$mmto->uses -= 1;
// Record the date this token was used
$mmto->date_last = time();
$mmto->save();
Session::instance()->set('token',$token);
$user = ORM::factory('account',$mmto->account_id);
$user->log(sprintf('Token %s used for method %s',$mmto->token,$mmto->method_id));
}
}
}

View File

@ -132,40 +132,24 @@ class Controller_lnApp_Login extends Controller_TemplateDefault {
if ($_POST) {
// If the email address is correct, create a method token
if (! empty($_POST['email']) AND ($ao=ORM::factory('account',array('email'=>$_POST['email']))) AND $ao->loaded()) {
$mt = ORM::factory('module_method_token');
// Find out our password reset method id
// @todo move this to a more generic method, so that it can be called by other methods
$mo = ORM::factory('module',array('name'=>'account'));
$mmo = ORM::factory('module_method',array('name'=>'user_resetpassword','module_id'=>$mo->id));
// Check to see if there is already a token, if so, do nothing.
if ($mt->where('account_id','=',$ao->id)->and_where('method_id','=',$mmo->id)->find()) {
if ($mt->loaded() AND ($mt->date_expire < time())) {
$mt->delete();
$mt->clear();
}
}
if (! $mt->loaded()) {
$mt->account_id = $ao->id;
$mt->method_id = $mmo->id;
$mt->date_expire = time() + $token_expire*60;
$mt->token = md5(sprintf('%s:%s:%s',$mt->account_id,$mt->method_id,$mt->date_expire));
$mt->save();
$mmto = ORM::factory('module_method_token')
->method(array('account','user_resetpassword'))
->account($ao)
->expire(time()+$token_expire*60);
if ($mmto->generate()) {
// Send our email with the token
// @todo Need to provide an option if Email_Template is not installed/activited.
// @todo Need to provide an option if account_reset_password template doesnt exist.
$et = Email_Template::instance('account_reset_password');
$et->to = array('account'=>array($mt->account_id));
$et->to = array('account'=>array($mmto->account_id));
$et->variables = array(
'SITE'=>URL::base(TRUE,TRUE),
'SITE_ADMIN'=>Config::sitename(),
'SITE_NAME'=>Config::sitename(),
'TOKEN'=>$mt->token,
'TOKEN'=>$mmto->token,
'TOKEN_EXPIRE_MIN'=>$token_expire,
'USER_NAME'=>sprintf('%s %s',$mt->account->first_name,$mt->account->last_name),
'USER_NAME'=>sprintf('%s %s',$mmto->account->first_name,$mmto->account->last_name),
);
$et->send();

View File

@ -22,5 +22,87 @@ class Model_Module_Method_Token extends ORMOSB {
// This module doesnt keep track of column updates automatically
protected $_update_column = FALSE;
public function method(array $modmeth) {
list($module,$method) = $modmeth;
if (! $method instanceof Model_Module_Method) {
if (is_numeric($module))
$mo = ORM::factory('module',$module);
elseif (is_string($module))
$mo = ORM::factory('module',array('name'=>$module));
elseif (! $module instanceof Model_Module)
throw new Kohana_Exception('Unknown module :module',array(':module'=>serialize($module)));
else
$mo = $module;
if (! $mo->loaded())
throw new Kohana_Exception('Unknown module :module - not loaded?',array(':module'=>$mo->id));
if (is_numeric($method))
$mmo = ORM::factory('module_method',$method);
elseif (is_string($method))
$mmo = ORM::factory('module_method',array('name'=>$method,'module_id'=>$mo->id));
else
throw new Kohana_Exception('Unknown method :method',array(':method'=>serialize($method)));
} else
$mmo = $method;
if (! $mmo->loaded())
throw new Kohana_Exception('Unknown method :method - not loaded?',array(':method'=>$mmo->id));
$this->method_id = $mmo->id;
return $this;
}
public function account($account) {
if (! $account instanceof Model_Account) {
if (is_numeric($account))
$ao = ORM::factory('account',$account);
else
throw new Kohana_Exception('Unknown account :account',array(':account'=>serialize($account)));
} else
$ao = $account;
$this->account_id = $ao->id;
return $this;
}
public function uses($uses) {
$this->uses = $uses;
return $this;
}
public function expire($expire) {
$this->date_expire = $expire;
return $this;
}
public function generate() {
if (! $this->account_id OR ! $this->method_id OR ! ($this->date_expire OR $this->uses))
return NULL;
// Check we dont already have a valid token
$mmto = ORM::factory('module_method_token')
->where('account_id','=',$this->account_id)
->where('method_id','=',$this->method_id)
->find();
if ($mmto->loaded()) {
if ((is_null($mmto->date_expire) OR $mmto->date_expire > time()) AND (is_null($mmto->uses) OR $mmto->uses > 0))
return $mmto->token;
else
$mmto->delete();
}
$this->token = md5(sprintf('%s:%s:%s',$this->account_id,$this->method_id,time()));
$this->save();
return $this->saved() ? $this->token : NULL;
}
}
?>