From 409b55f4dbb4267e83e8ae2fda56f243ab8be250 Mon Sep 17 00:00:00 2001 From: Robert Kaiser Date: Fri, 28 Oct 2016 19:08:02 +0200 Subject: [PATCH] make login on authorize actually work and redirect back to the authorize form after login --- authorize.php | 31 +++++++++++++++++++++++-------- authsystem.inc.php | 1 + authsystem.js | 5 ++++- authutils.php-class | 41 +++++++++++++++++++++++++++++++++++++++++ index.php | 39 +++++++++------------------------------ 5 files changed, 78 insertions(+), 39 deletions(-) diff --git a/authorize.php b/authorize.php index 45f0b03..2a7e0a5 100644 --- a/authorize.php +++ b/authorize.php @@ -18,12 +18,28 @@ $style = $head->appendElement('link'); $style->setAttribute('rel', 'stylesheet'); $style->setAttribute('href', 'authsystem.css'); $head->appendJSFile('authsystem.js'); +$title->appendText('Authorization Request | KaiRo.at'); +$h1 = $body->appendElement('h1', 'KaiRo.at Authentication Server'); $errors = $utils->checkForSecureConnection(); +$para = $body->appendElement('p', _('This login system does not work without JavaScript. Please activate JavaScript for this site to log in.')); +$para->setAttribute('id', 'jswarning'); +$para->setAttribute('class', 'warn'); + if (!count($errors)) { $session = $utils->initSession(); // Read session or create new session and set cookie. - $user = array('id' => 0, 'email' => ''); + if (intval($session['user'])) { + $result = $db->prepare('SELECT `id`,`email`,`verify_hash` FROM `auth_users` WHERE `id` = :userid;'); + $result->execute(array(':userid' => $session['user'])); + $user = $result->fetch(PDO::FETCH_ASSOC); + if (!$user['id']) { + $utils->log('user_read_failure', 'user: '.$session['user']); + } + } + else { + $user = array('id' => 0, 'email' => ''); + } $pagetype = 'default'; if (is_null($session)) { $errors[] = _('The session system is not working. Please contact KaiRo.at and tell the team about this.'); @@ -41,13 +57,6 @@ if (!count($errors)) { // Display an authorization form. if (empty($_POST)) { - $title->appendText('Authorization Request | KaiRo.at'); - $h1 = $body->appendElement('h1', 'KaiRo.at Authentication Server'); - - $para = $body->appendElement('p', _('This login system does not work without JavaScript. Please activate JavaScript for this site to log in.')); - $para->setAttribute('id', 'jswarning'); - $para->setAttribute('class', 'warn'); - $para = $body->appendElement('p', sprintf(_('Hi %s!'), $user['email'])); $para->setAttribute('class', 'userwelcome'); @@ -79,6 +88,12 @@ if (!count($errors)) { // Display login/register form. $para = $body->appendElement('p', _('You need to log in or register to continue.')); $para->setAttribute('class', 'logininfo'); + $utils->appendLoginForm($body, $session, $user); + // Save the request in the session so we can get back to fulfilling it. + $result = $db->prepare('UPDATE `auth_sessions` SET `saved_redirect` = :redir WHERE `id` = :sessid;'); + if (!$result->execute(array(':redir' => $_SERVER['REQUEST_URI'], ':sessid' => $session['id']))) { + $utils->log('redir_save_failure', 'session: '.$session['id'].', redirect: '.$_SERVER['REQUEST_URI']); + } } } diff --git a/authsystem.inc.php b/authsystem.inc.php index 8b26e4f..5354cd9 100644 --- a/authsystem.inc.php +++ b/authsystem.inc.php @@ -42,6 +42,7 @@ CREATE TABLE `auth_sessions` ( `logged_in` BOOLEAN NOT NULL DEFAULT FALSE , `time_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `time_expire` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , + `saved_redirect` VARCHAR(255) NOT NULL DEFAULT '' , PRIMARY KEY (`id`), INDEX (`sesskey`), INDEX (`time_expire`) diff --git a/authsystem.js b/authsystem.js index 8fd9756..2e21b0f 100644 --- a/authsystem.js +++ b/authsystem.js @@ -3,7 +3,10 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ window.onload = function() { - document.getElementById("jswarning").classList.add("hidden"); + var jsWarning = document.getElementById("jswarning"); + if (jsWarning) { + document.getElementById("jswarning").classList.add("hidden"); + } var loginForm = document.getElementById("loginform"); if (loginForm) { loginForm.classList.remove("hidden"); diff --git a/authutils.php-class b/authutils.php-class index bcf1b38..4d5680a 100755 --- a/authutils.php-class +++ b/authutils.php-class @@ -34,6 +34,9 @@ class AuthUtils { // function initSession() // Initialize a session. Returns an associative array of all the DB fields of the session. // + // function getDomainBaseURL() + // Get the base URL of the current domain, e.g. 'https://example.com'. + // // function checkPasswordConstraints($new_password, $user_email) // Check password constraints and return an array of error messages (empty if all constraints are met). // @@ -60,6 +63,9 @@ class AuthUtils { // // function pwdNeedsRehash($user) // Return true if the pwdhash field of the user uses an outdated standard and needs to be rehashed. + // + // function appendLoginForm($dom_element, $session, $user) + // append a login form for the given session to the given DOM element, possibly prefilling the email from the given user info array. function __construct($settings, $db) { // *** constructor *** @@ -125,6 +131,10 @@ class AuthUtils { return $session; } + function getDomainBaseURL() { + return ($this->running_on_localhost?'http':'https').'://'.$_SERVER['SERVER_NAME']; + } + function checkPasswordConstraints($new_password, $user_email) { $errors = array(); if ($new_password != trim($new_password)) { @@ -210,5 +220,36 @@ class AuthUtils { return true; } } + + function appendLoginForm($dom_element, $session, $user) { + $form = $dom_element->appendForm('./', 'POST', 'loginform'); + $form->setAttribute('id', 'loginform'); + $form->setAttribute('class', 'loginarea hidden'); + $ulist = $form->appendElement('ul'); + $ulist->setAttribute('class', 'flat login'); + $litem = $ulist->appendElement('li'); + $inptxt = $litem->appendInputEmail('email', 30, 20, 'login_email', (intval(@$user['id'])?$user['email']:'')); + $inptxt->setAttribute('autocomplete', 'email'); + $inptxt->setAttribute('required', ''); + $inptxt->setAttribute('placeholder', _('Email')); + $inptxt->setAttribute('class', 'login'); + $litem = $ulist->appendElement('li'); + $inptxt = $litem->appendInputPassword('pwd', 20, 20, 'login_pwd', ''); + $inptxt->setAttribute('required', ''); + $inptxt->setAttribute('placeholder', _('Password')); + $inptxt->setAttribute('class', 'login'); + $litem = $ulist->appendElement('li'); + $litem->appendLink('./?reset', _('Forgot password?')); + $litem = $ulist->appendElement('li'); + $cbox = $litem->appendInputCheckbox('remember', 'login_remember', 'true', false); + $cbox->setAttribute('class', 'logincheck'); + $label = $litem->appendLabel('login_remember', _('Remember me')); + $label->setAttribute('id', 'rememprompt'); + $label->setAttribute('class', 'loginprompt'); + $litem = $ulist->appendElement('li'); + $litem->appendInputHidden('tcode', $this->createTimeCode($session)); + $submit = $litem->appendInputSubmit(_('Log in / Register')); + $submit->setAttribute('class', 'loginbutton'); + } } ?> diff --git a/index.php b/index.php index c69424b..e01c7d1 100644 --- a/index.php +++ b/index.php @@ -67,6 +67,10 @@ if (!count($errors)) { $utils->log('login', 'user: '.$user['id']); $sesskey = $utils->createSessionKey(); setcookie('sessionkey', $sesskey, 0, "", "", !$utils->running_on_localhost, true); // Last two params are secure and httponly, secure is not set on localhost. + // If the session has a redirect set, make sure it's performed. + if (strlen(@$session['saved_redirect'])) { + header('Location: '.$utils->getDomainBaseURL().$session['saved_redirect']); + } // If the session has a user set, create a new one - otherwise take existing session entry. if (intval($session['user'])) { $result = $db->prepare('INSERT INTO `auth_sessions` (`sesskey`, `time_expire`, `user`, `logged_in`) VALUES (:sesskey, :expire, :userid, TRUE);'); @@ -148,7 +152,7 @@ if (!count($errors)) { $mail->addMailText(sprintf(_('This email address, %s, has been used for registration on "%s".'), $user['email'], _('KaiRo.at Authentication Service'))."\n\n"); $mail->addMailText(_('Please confirm that registration by clicking the following link (or calling it up in your browser):')."\n"); - $mail->addMailText(($utils->running_on_localhost?'http':'https').'://'.$_SERVER['SERVER_NAME'].strstr($_SERVER['REQUEST_URI'], '?', true) + $mail->addMailText($utils->getDomainBaseURL().strstr($_SERVER['REQUEST_URI'], '?', true) .'?email='.rawurlencode($user['email']).'&verification_code='.rawurlencode($user['verify_hash'])."\n\n"); $mail->addMailText(_('With this confirmation, you accept that we handle your data for the purpose of logging you into other websites when you request that.')."\n"); $mail->addMailText(_('Those websites will get to know your email address but not your password, which we store securely.')."\n"); @@ -186,7 +190,7 @@ if (!count($errors)) { $mail->addMailText(sprintf(_('A request for setting a new password for this email address, %s, has been submitted on "%s".'), $user['email'], _('KaiRo.at Authentication Service'))."\n\n"); $mail->addMailText(_('You can set a new password by clicking the following link (or calling it up in your browser):')."\n"); - $mail->addMailText(($utils->running_on_localhost?'http':'https').'://'.$_SERVER['SERVER_NAME'].strstr($_SERVER['REQUEST_URI'], '?', true) + $mail->addMailText($utils->getDomainBaseURL().strstr($_SERVER['REQUEST_URI'], '?', true) .'?email='.rawurlencode($user['email']).'&reset_code='.rawurlencode($resetcode)."\n\n"); $mail->addMailText(_('If you do not call this confirmation link within 1 hour, this link expires and the existing password is being kept in place.')."\n\n"); $mail->addMailText(sprintf(_('The %s team'), 'KaiRo.at')); @@ -316,6 +320,8 @@ if (!count($errors)) { if ($pagetype == 'verification_sent') { $para = $body->appendElement('p', sprintf(_('An email for confirmation has been sent to %s. Please follow the link provided there to complete the process.'), $user['email'])); $para->setAttribute('class', 'verifyinfo pending'); + $para = $body->appendElement('p', _('Reload this page after you confirm to continue.')); + $para->setAttribute('class', 'verifyinfo pending'); } elseif ($pagetype == 'resetmail_sent') { $para = $body->appendElement('p', @@ -390,34 +396,7 @@ if (!count($errors)) { $para = $body->appendElement('p', _('Your password has successfully been reset. You can log in now with the new password.')); $para->setAttribute('class', 'resetinfo done'); } - $form = $body->appendForm('./', 'POST', 'loginform'); - $form->setAttribute('id', 'loginform'); - $form->setAttribute('class', 'loginarea hidden'); - $ulist = $form->appendElement('ul'); - $ulist->setAttribute('class', 'flat login'); - $litem = $ulist->appendElement('li'); - $inptxt = $litem->appendInputEmail('email', 30, 20, 'login_email', (intval($user['id'])?$user['email']:'')); - $inptxt->setAttribute('autocomplete', 'email'); - $inptxt->setAttribute('required', ''); - $inptxt->setAttribute('placeholder', _('Email')); - $inptxt->setAttribute('class', 'login'); - $litem = $ulist->appendElement('li'); - $inptxt = $litem->appendInputPassword('pwd', 20, 20, 'login_pwd', ''); - $inptxt->setAttribute('required', ''); - $inptxt->setAttribute('placeholder', _('Password')); - $inptxt->setAttribute('class', 'login'); - $litem = $ulist->appendElement('li'); - $litem->appendLink('./?reset', _('Forgot password?')); - $litem = $ulist->appendElement('li'); - $cbox = $litem->appendInputCheckbox('remember', 'login_remember', 'true', false); - $cbox->setAttribute('class', 'logincheck'); - $label = $litem->appendLabel('login_remember', _('Remember me')); - $label->setAttribute('id', 'rememprompt'); - $label->setAttribute('class', 'loginprompt'); - $litem = $ulist->appendElement('li'); - $litem->appendInputHidden('tcode', $utils->createTimeCode($session)); - $submit = $litem->appendInputSubmit(_('Log in / Register')); - $submit->setAttribute('class', 'loginbutton'); + $utils->appendLoginForm($body, $session, $user); } } -- 2.35.3