Skip to content
Snippets Groups Projects
Commit 395d435e authored by Jared Hancock's avatar Jared Hancock
Browse files

Implement a remote user import process

This adds a feature for remote authentication methods for clients, such as
LDAP, which will, after successful authentication, yield a
ClientCreateRequest rather than an AuthenticatedUser. The
ClientCreateRequest represents a successful authentication and user
information lookup for a remote client. The client is then presented with a
registration page where their information for their account in the local
system can be reviewed prior to the account creation. Once created, the
client account is confirmed without an email confirmation and is logged in
immediately without reentering a password.
parent cbab2c6a
No related branches found
No related tags found
No related merge requests found
...@@ -55,15 +55,13 @@ elseif ($_POST) { ...@@ -55,15 +55,13 @@ elseif ($_POST) {
$user_form = UserForm::getUserForm()->getForm($_POST); $user_form = UserForm::getUserForm()->getForm($_POST);
if (!$user_form->isValid(function($f) { return !$f->get('internal'); })) if (!$user_form->isValid(function($f) { return !$f->get('internal'); }))
$errors['err'] = 'Incomplete client information'; $errors['err'] = 'Incomplete client information';
elseif (!$_POST['passwd1']) elseif (!$_POST['backend'] && !$_POST['passwd1'])
$errors['passwd1'] = 'New password required'; $errors['passwd1'] = 'New password required';
elseif ($_POST['passwd2'] != $_POST['passwd1']) elseif (!$_POST['backend'] && $_POST['passwd2'] != $_POST['passwd1'])
$errors['passwd1'] = 'Passwords do not match'; $errors['passwd1'] = 'Passwords do not match';
// XXX: The email will always be in use already if a guest is logged in // XXX: The email will always be in use already if a guest is logged in
// and is registering for an account. Instead, // and is registering for an account. Instead,
elseif (!($user = $thisclient ?: User::fromForm($user_form)))
$errors['err'] = 'Unable to register account. See messages below';
elseif (($addr = $user_form->getField('email')->getClean()) elseif (($addr = $user_form->getField('email')->getClean())
&& ClientAccount::lookupByUsername($addr)) { && ClientAccount::lookupByUsername($addr)) {
$user_form->getField('email')->addError( $user_form->getField('email')->addError(
...@@ -71,6 +69,12 @@ elseif ($_POST) { ...@@ -71,6 +69,12 @@ elseif ($_POST) {
.urlencode($addr).'" style="color:inherit"><strong>sign in</strong></a>?'); .urlencode($addr).'" style="color:inherit"><strong>sign in</strong></a>?');
$errors['err'] = 'Unable to register account. See messages below'; $errors['err'] = 'Unable to register account. See messages below';
} }
// Users created from ClientCreateRequest
elseif (isset($_POST['backend']) && !($user = User::fromVars($user_form->getClean())))
$errors['err'] = 'Unable to create local account. See messages below';
// New users and users registering from a ticket access link
elseif (!$user && !($user = $thisclient ?: User::fromForm($user_form)))
$errors['err'] = 'Unable to register account. See messages below';
else { else {
if (!($acct = ClientAccount::createForUser($user))) if (!($acct = ClientAccount::createForUser($user)))
$errors['err'] = 'Internal error. Unable to create new account'; $errors['err'] = 'Internal error. Unable to create new account';
...@@ -84,6 +88,18 @@ elseif ($_POST) { ...@@ -84,6 +88,18 @@ elseif ($_POST) {
$content = Page::lookup(Page::getIdByType('registration-confirm')); $content = Page::lookup(Page::getIdByType('registration-confirm'));
$inc = 'register.confirm.inc.php'; $inc = 'register.confirm.inc.php';
$acct->sendResetEmail('registration-client'); $acct->sendResetEmail('registration-client');
break;
case 'import':
foreach (UserAuthenticationBackend::allRegistered() as $bk) {
if ($bk::$id == $_POST['backend']) {
$cl = new ClientSession(new EndUser($user));
$acct->confirm();
if ($user = $bk->login($cl, $bk))
Http::redirect('tickets.php');
break;
}
}
break;
} }
} }
......
...@@ -50,6 +50,44 @@ interface AuthDirectorySearch { ...@@ -50,6 +50,44 @@ interface AuthDirectorySearch {
function search($query); function search($query);
} }
/**
* Class: ClientCreateRequest
*
* Simple container to represent a remote authentication success for a
* client which should be imported into the local database. The class will
* provide access to the backend that authenticated the user, the username
* that the user entered when logging in, and any other information about
* the user that the backend was able to lookup. Generally, this extra
* information would be the same information retrieved from calling the
* AuthDirectorySearch::lookup() method.
*/
class ClientCreateRequest {
var $backend;
var $username;
var $info;
function __construct($backend, $username, $info=array()) {
$this->backend = $backend;
$this->username = $username;
$this->info = $info;
}
function getBackend() {
return $this->backend;
}
function setBackend($what) {
$this->backend = $what;
}
function getUsername() {
return $this->username;
}
function getInfo() {
return $this->info;
}
}
/** /**
* Authentication backend * Authentication backend
* *
...@@ -133,6 +171,9 @@ abstract class AuthenticationBackend { ...@@ -133,6 +171,9 @@ abstract class AuthenticationBackend {
if ($result instanceof AuthenticatedUser if ($result instanceof AuthenticatedUser
&& ($bk->login($result, $bk))) && ($bk->login($result, $bk)))
return $result; return $result;
elseif ($result instanceof ClientCreateRequest
&& $bk instanceof UserAuthenticationBackend)
return $result;
elseif ($result instanceof AccessDenied) { elseif ($result instanceof AccessDenied) {
break; break;
} }
...@@ -407,8 +448,20 @@ abstract class UserAuthenticationBackend extends AuthenticationBackend { ...@@ -407,8 +448,20 @@ abstract class UserAuthenticationBackend extends AuthenticationBackend {
} }
function getAllowedBackends($userid) { function getAllowedBackends($userid) {
// White listing backends for specific user not supported. $backends = array();
return array(); $sql = 'SELECT A1.backend FROM '.USER_ACCOUNT_TABLE
.' A1 INNER JOIN '.USER_EMAIL_TABLE.' A2 ON (A2.user_id = A1.user_id)'
.' WHERE backend IS NOT NULL '
.' AND (A1.username='.db_input($userid)
.' OR A2.`address`='.db_input($userid).')';
if (!($res=db_query($sql, false)))
return $backends;
while (list($bk) = db_fetch_row($res))
$backends[] = $bk;
return array_filter($backends);
} }
function login($user, $bk) { function login($user, $bk) {
......
...@@ -474,6 +474,12 @@ class ClientAccount extends ClientAccountModel { ...@@ -474,6 +474,12 @@ class ClientAccount extends ClientAccountModel {
$this->set('timezone_id', $vars['timezone_id']); $this->set('timezone_id', $vars['timezone_id']);
$this->set('dst', isset($vars['dst']) ? 1 : 0); $this->set('dst', isset($vars['dst']) ? 1 : 0);
if ($vars['backend']) {
$this->set('backend', $vars['backend']);
if ($vars['username'])
$this->set('username', $vars['username']);
}
if ($vars['passwd1']) { if ($vars['passwd1']) {
$this->set('passwd', Passwd::hash($vars['passwd1'])); $this->set('passwd', Passwd::hash($vars['passwd1']));
$info = array('password' => $vars['passwd1']); $info = array('password' => $vars['passwd1']);
......
<?php <?php
$info = $_POST ?: array( $info = $_POST;
'timezone_id' => $cfg->getDefaultTimezoneId(), if (!isset($info['timezone_id']))
'dst' => $cfg->observeDaylightSaving(), $info += array(
); 'timezone_id' => $cfg->getDefaultTimezoneId(),
'dst' => $cfg->observeDaylightSaving(),
'backend' => null,
);
if (isset($user) && $user instanceof ClientCreateRequest) {
$bk = $user->getBackend();
$info = array_merge($info, array(
'backend' => $bk::$id,
'username' => $user->getUsername(),
));
}
?> ?>
<h1>Account Registration</h1> <h1>Account Registration</h1>
<p> <p>
Use the forms below to update the information we have on file for your Use the forms below to create or update the information we have on file for
account your account
</p> </p>
<form action="account.php" method="post"> <form action="account.php" method="post">
<?php csrf_token(); ?> <?php csrf_token(); ?>
<input type="hidden" name="do" value="<?php echo $_REQUEST['do'] ?: 'create'; ?>" /> <input type="hidden" name="do" value="<?php echo $_REQUEST['do']
?: ($info['backend'] ? 'import' :'create'); ?>" />
<table width="800" class="padded"> <table width="800" class="padded">
<tbody>
<?php <?php
$cf = $user_form ?: UserForm::getInstance(); $cf = $user_form ?: UserForm::getInstance();
$cf->render(false); $cf->render(false);
...@@ -54,6 +67,23 @@ account ...@@ -54,6 +67,23 @@ account
<div><hr><h3>Access Credentials</h3></div> <div><hr><h3>Access Credentials</h3></div>
</td> </td>
</tr> </tr>
<?php if ($info['backend']) { ?>
<tr>
<td width="180">
Login With:
</td>
<td>
<input type="hidden" name="backend" value="<?php echo $info['backend']; ?>"/>
<input type="hidden" name="username" value="<?php echo $info['username']; ?>"/>
<?php foreach (UserAuthenticationBackend::allRegistered() as $bk) {
if ($bk::$id == $info['backend']) {
echo $bk::$name;
break;
}
} ?>
</td>
</tr>
<?php } else { ?>
<tr> <tr>
<td width="180"> <td width="180">
Create a Password: Create a Password:
...@@ -72,6 +102,8 @@ account ...@@ -72,6 +102,8 @@ account
&nbsp;<span class="error">&nbsp;<?php echo $errors['passwd2']; ?></span> &nbsp;<span class="error">&nbsp;<?php echo $errors['passwd2']; ?></span>
</td> </td>
</tr> </tr>
<?php } ?>
</tbody>
</table> </table>
<hr> <hr>
<p style="text-align: center;"> <p style="text-align: center;">
......
...@@ -35,7 +35,21 @@ if ($_POST && isset($_POST['luser'])) { ...@@ -35,7 +35,21 @@ if ($_POST && isset($_POST['luser'])) {
$errors['err'] = 'Valid username or email address is required'; $errors['err'] = 'Valid username or email address is required';
elseif (($user = UserAuthenticationBackend::process($_POST['luser'], elseif (($user = UserAuthenticationBackend::process($_POST['luser'],
$_POST['lpasswd'], $errors))) { $_POST['lpasswd'], $errors))) {
Http::redirect($_SESSION['_client']['auth']['dest'] ?: 'tickets.php'); if ($user instanceof ClientCreateRequest) {
if ($cfg && $cfg->isClientRegistrationEnabled()) {
$inc = 'register.inc.php';
$user_form = UserForm::getUserForm()->getForm($user->getInfo());
}
else {
$errors['err'] = 'Access Denied. Contact your help desk
administrator to have an account registered for you';
// fall through to show login page again
}
}
else {
Http::redirect($_SESSION['_client']['auth']['dest']
?: 'tickets.php');
}
} elseif(!$errors['err']) { } elseif(!$errors['err']) {
$errors['err'] = 'Invalid username or password - try again!'; $errors['err'] = 'Invalid username or password - try again!';
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment