From ed5828f30ea0f7a30e01d407058990b06164c6f3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 8 Jan 2010 17:20:25 -0800 Subject: Redirect to a one-time-password when ssl and regular server are different --- actions/login.php | 97 ++++++++++++++++++------------------ actions/otp.php | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 47 deletions(-) create mode 100644 actions/otp.php (limited to 'actions') diff --git a/actions/login.php b/actions/login.php index c775fa692..a2f853e3a 100644 --- a/actions/login.php +++ b/actions/login.php @@ -76,15 +76,10 @@ class LoginAction extends Action { parent::handle($args); - $disabled = common_config('logincommand','disabled'); - $disabled = isset($disabled) && $disabled; - if (common_is_real_login()) { $this->clientError(_('Already logged in.')); } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->checkLogin(); - } else if (!$disabled && isset($args['user_id']) && isset($args['token'])){ - $this->checkLogin($args['user_id'],$args['token']); } else { common_ensure_session(); $this->showForm(); @@ -103,46 +98,21 @@ class LoginAction extends Action function checkLogin($user_id=null, $token=null) { - if(isset($token) && isset($user_id)){ - //Token based login (from the LoginCommand) - $login_token = Login_token::staticGet('user_id',$user_id); - if($login_token && $login_token->token == $token){ - if($login_token->modified > time()+2*60){ - //token has expired - //delete the token as it is useless - $login_token->delete(); - $this->showForm(_('Invalid or expired token.')); - return; - }else{ - //delete the token so it cannot be reused - $login_token->delete(); - //it's a valid token - let them log in - $user = User::staticGet('id', $user_id); - //$user = User::staticGet('nickname', "candrews"); - } - }else{ - $this->showForm(_('Invalid or expired token.')); - return; - } - }else{ - // Regular form submission login - - // XXX: login throttle - - // CSRF protection - token set in NoticeForm - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->clientError(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } - - $nickname = $this->trimmed('nickname'); - $password = $this->arg('password'); - - $user = common_check_user($nickname, $password); + // XXX: login throttle + + // CSRF protection - token set in NoticeForm + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. '. + 'Try again, please.')); + return; } + $nickname = $this->trimmed('nickname'); + $password = $this->arg('password'); + + $user = common_check_user($nickname, $password); + if (!$user) { $this->showForm(_('Incorrect username or password.')); return; @@ -162,6 +132,12 @@ class LoginAction extends Action $url = common_get_returnto(); + if (common_config('ssl', 'sometimes') && // mixed environment + common_config('site', 'server') != common_config('site', 'sslserver')) { + $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); + return; + } + if ($url) { // We don't have to return to it again common_set_returnto(null); @@ -240,9 +216,9 @@ class LoginAction extends Action function showContent() { $this->elementStart('form', array('method' => 'post', - 'id' => 'form_login', - 'class' => 'form_settings', - 'action' => common_local_url('login'))); + 'id' => 'form_login', + 'class' => 'form_settings', + 'action' => common_local_url('login'))); $this->elementStart('fieldset'); $this->element('legend', null, _('Login to site')); $this->elementStart('ul', 'form_data'); @@ -255,7 +231,7 @@ class LoginAction extends Action $this->elementStart('li'); $this->checkbox('rememberme', _('Remember me'), false, _('Automatically login in the future; ' . - 'not for shared computers!')); + 'not for shared computers!')); $this->elementEnd('li'); $this->elementEnd('ul'); $this->submit('submit', _('Login')); @@ -306,4 +282,31 @@ class LoginAction extends Action $nav = new LoginGroupNav($this); $nav->show(); } + + function redirectFromSSL($user, $returnto, $rememberme) + { + try { + $login_token = Login_token::makeNew($user); + } catch (Exception $e) { + $this->serverError($e->getMessage()); + return; + } + + $params = array(); + + if (!empty($returnto)) { + $params['returnto'] = $returnto; + } + + if (!empty($rememberme)) { + $params['rememberme'] = $rememberme; + } + + $target = common_local_url('otp', + array('user_id' => $login_token->user_id, + 'token' => $login_token->token), + $params); + + common_redirect($target, 303); + } } diff --git a/actions/otp.php b/actions/otp.php new file mode 100644 index 000000000..acf84aee8 --- /dev/null +++ b/actions/otp.php @@ -0,0 +1,145 @@ +. + * + * @category Login + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Allow one-time password login + * + * This action will automatically log in the user identified by the user_id + * parameter. A login_token record must be constructed beforehand, typically + * by code where the user is already authenticated. + * + * @category Login + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 + * @link http://status.net/ + */ + +class OtpAction extends Action +{ + var $user; + var $token; + var $rememberme; + var $returnto; + var $lt; + + function prepare($args) + { + parent::prepare($args); + + if (common_is_real_login()) { + $this->clientError(_('Already logged in.')); + return false; + } + + $id = $this->trimmed('user_id'); + + if (empty($id)) { + $this->clientError(_('No user ID specified.')); + return false; + } + + $this->user = User::staticGet('id', $id); + + if (empty($this->user)) { + $this->clientError(_('No such user.')); + return false; + } + + $this->token = $this->trimmed('token'); + + if (empty($this->token)) { + $this->clientError(_('No login token specified.')); + return false; + } + + $this->lt = Login_token::staticGet('user_id', $id); + + if (empty($this->lt)) { + $this->clientError(_('No login token requested.')); + return false; + } + + if ($this->lt->token != $this->token) { + $this->clientError(_('Invalid login token specified.')); + return false; + } + + if ($this->lt->modified > time() + Login_token::TIMEOUT) { + //token has expired + //delete the token as it is useless + $this->lt->delete(); + $this->lt = null; + $this->clientError(_('Login token expired.')); + return false; + } + + $this->rememberme = $this->boolean('rememberme'); + $this->returnto = $this->trimmed('returnto'); + + return true; + } + + function handle($args) + { + parent::handle($args); + + // success! + if (!common_set_user($this->user)) { + $this->serverError(_('Error setting user. You are probably not authorized.')); + return; + } + + // We're now logged in; disable the lt + + $this->lt->delete(); + $this->lt = null; + + if ($this->rememberme) { + common_rememberme($this->user); + } + + if (!empty($this->returnto)) { + $url = $this->returnto; + // We don't have to return to it again + common_set_returnto(null); + } else { + $url = common_local_url('all', + array('nickname' => + $this->user->nickname)); + } + + common_redirect($url, 303); + } +} -- cgit v1.2.3-54-g00ecf From 6d66a28b3591b579f0230620339882e9ba8078ab Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 9 Jan 2010 16:23:41 -0800 Subject: Use OTP to set cookies from registration action --- actions/register.php | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'actions') diff --git a/actions/register.php b/actions/register.php index 57f8e7bdf..108d05f5a 100644 --- a/actions/register.php +++ b/actions/register.php @@ -259,6 +259,16 @@ class RegisterAction extends Action // Re-init language env in case it changed (not yet, but soon) common_init_language(); + + if (common_config('ssl', 'sometimes') && // mixed environment + common_config('site', 'server') != common_config('site', 'sslserver')) { + $url = common_local_url('all', + array('nickname' => + $user->nickname)); + $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); + return; + } + $this->showSuccess(); } else { $this->showForm(_('Invalid username or password.')); @@ -578,5 +588,32 @@ class RegisterAction extends Action $nav = new LoginGroupNav($this); $nav->show(); } + + function redirectFromSSL($user, $returnto, $rememberme) + { + try { + $login_token = Login_token::makeNew($user); + } catch (Exception $e) { + $this->serverError($e->getMessage()); + return; + } + + $params = array(); + + if (!empty($returnto)) { + $params['returnto'] = $returnto; + } + + if (!empty($rememberme)) { + $params['rememberme'] = $rememberme; + } + + $target = common_local_url('otp', + array('user_id' => $login_token->user_id, + 'token' => $login_token->token), + $params); + + common_redirect($target, 303); + } } -- cgit v1.2.3-54-g00ecf From 304f3b4f188d92720848ae1e3ac85ee04bd5ef71 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 00:18:17 -0800 Subject: correctly check for ssl enabled --- actions/login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/login.php b/actions/login.php index a2f853e3a..ea9b96a46 100644 --- a/actions/login.php +++ b/actions/login.php @@ -133,7 +133,7 @@ class LoginAction extends Action $url = common_get_returnto(); if (common_config('ssl', 'sometimes') && // mixed environment - common_config('site', 'server') != common_config('site', 'sslserver')) { + 0 != strcasecmp(common_config('site', 'server'), common_config('site', 'sslserver'))) { $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); return; } -- cgit v1.2.3-54-g00ecf From 06ed0bc7913e6af0a4aaab93459148c690be70f1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 00:19:46 -0800 Subject: correctly check for ssl enabled --- actions/register.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'actions') diff --git a/actions/register.php b/actions/register.php index 108d05f5a..ec6534eee 100644 --- a/actions/register.php +++ b/actions/register.php @@ -260,8 +260,9 @@ class RegisterAction extends Action // Re-init language env in case it changed (not yet, but soon) common_init_language(); - if (common_config('ssl', 'sometimes') && // mixed environment - common_config('site', 'server') != common_config('site', 'sslserver')) { + if (common_config('site', 'ssl') == 'sometimes' && // mixed environment + 0 != strcasecmp(common_config('site', 'server'), common_config('site', 'sslserver'))) { + $url = common_local_url('all', array('nickname' => $user->nickname)); -- cgit v1.2.3-54-g00ecf From 8c6ec0b59ef282c5b2910689255b52de99d477a2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 00:23:26 -0800 Subject: fix check for ssl diff in login --- actions/login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/login.php b/actions/login.php index ea9b96a46..8694de188 100644 --- a/actions/login.php +++ b/actions/login.php @@ -132,7 +132,7 @@ class LoginAction extends Action $url = common_get_returnto(); - if (common_config('ssl', 'sometimes') && // mixed environment + if (common_config('site', 'ssl') == 'sometimes' && // mixed environment 0 != strcasecmp(common_config('site', 'server'), common_config('site', 'sslserver'))) { $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); return; -- cgit v1.2.3-54-g00ecf From 54d532e12f5dac8924d30d21c15f331ce5d16550 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 22:58:33 -0800 Subject: remove redirect to OTP on login from login, register --- actions/login.php | 33 --------------------------------- actions/register.php | 37 ------------------------------------- 2 files changed, 70 deletions(-) (limited to 'actions') diff --git a/actions/login.php b/actions/login.php index 8694de188..9c47d88b1 100644 --- a/actions/login.php +++ b/actions/login.php @@ -132,12 +132,6 @@ class LoginAction extends Action $url = common_get_returnto(); - if (common_config('site', 'ssl') == 'sometimes' && // mixed environment - 0 != strcasecmp(common_config('site', 'server'), common_config('site', 'sslserver'))) { - $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); - return; - } - if ($url) { // We don't have to return to it again common_set_returnto(null); @@ -282,31 +276,4 @@ class LoginAction extends Action $nav = new LoginGroupNav($this); $nav->show(); } - - function redirectFromSSL($user, $returnto, $rememberme) - { - try { - $login_token = Login_token::makeNew($user); - } catch (Exception $e) { - $this->serverError($e->getMessage()); - return; - } - - $params = array(); - - if (!empty($returnto)) { - $params['returnto'] = $returnto; - } - - if (!empty($rememberme)) { - $params['rememberme'] = $rememberme; - } - - $target = common_local_url('otp', - array('user_id' => $login_token->user_id, - 'token' => $login_token->token), - $params); - - common_redirect($target, 303); - } } diff --git a/actions/register.php b/actions/register.php index ec6534eee..6339ea117 100644 --- a/actions/register.php +++ b/actions/register.php @@ -260,16 +260,6 @@ class RegisterAction extends Action // Re-init language env in case it changed (not yet, but soon) common_init_language(); - if (common_config('site', 'ssl') == 'sometimes' && // mixed environment - 0 != strcasecmp(common_config('site', 'server'), common_config('site', 'sslserver'))) { - - $url = common_local_url('all', - array('nickname' => - $user->nickname)); - $this->redirectFromSSL($user, $url, $this->boolean('rememberme')); - return; - } - $this->showSuccess(); } else { $this->showForm(_('Invalid username or password.')); @@ -589,32 +579,5 @@ class RegisterAction extends Action $nav = new LoginGroupNav($this); $nav->show(); } - - function redirectFromSSL($user, $returnto, $rememberme) - { - try { - $login_token = Login_token::makeNew($user); - } catch (Exception $e) { - $this->serverError($e->getMessage()); - return; - } - - $params = array(); - - if (!empty($returnto)) { - $params['returnto'] = $returnto; - } - - if (!empty($rememberme)) { - $params['rememberme'] = $rememberme; - } - - $target = common_local_url('otp', - array('user_id' => $login_token->user_id, - 'token' => $login_token->token), - $params); - - common_redirect($target, 303); - } } -- cgit v1.2.3-54-g00ecf From 5ec25a9691cac0f7bfa02fb2f6237f91fc1a2e82 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 11 Jan 2010 08:40:22 +0000 Subject: inject session before redirect for login --- actions/login.php | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'actions') diff --git a/actions/login.php b/actions/login.php index 9c47d88b1..8ea3c800b 100644 --- a/actions/login.php +++ b/actions/login.php @@ -103,6 +103,15 @@ class LoginAction extends Action // CSRF protection - token set in NoticeForm $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { + $st = common_session_token(); + if (empty($token)) { + common_log(LOG_WARNING, 'No token provided by client.'); + } else if (empty($st)) { + common_log(LOG_WARNING, 'No session token stored.'); + } else { + common_log(LOG_WARNING, 'Token = ' . $token . ' and session token = ' . $st); + } + $this->clientError(_('There was a problem with your session token. '. 'Try again, please.')); return; @@ -135,6 +144,7 @@ class LoginAction extends Action if ($url) { // We don't have to return to it again common_set_returnto(null); + $url = common_inject_session($url); } else { $url = common_local_url('all', array('nickname' => -- cgit v1.2.3-54-g00ecf