Add changes for API Authenication and force API to use SSL

This commit is contained in:
james 2010-08-24 16:04:12 +00:00
parent 05432715e4
commit 4bf2897f18
3 changed files with 282 additions and 152 deletions

69
api.php
View File

@ -23,8 +23,18 @@
?>
<?
include "common.inc.php";
require_once("account.inc.php");
require_once("user.inc.php");
if($_SERVER['HTTPS']!="on") {
$ret['status']="error";
$ret['error']="SSL is required for API access, please access the API over https";
echo json_encode($ret);
exit;
}
$request=explode("/",$_GET['request']);
$ret=array();
switch($request[0]) {
case "conferences":
@ -56,6 +66,65 @@ switch($request[0]) {
}
break;
case "auth":
if($request[1]=="login") {
$user = $_POST['username'];
$pass = $_POST['password'];
$accounts_id = try_login($user, $pass);
if($accounts_id == false) {
$ret['status']="error";
$ret['error']="Invalid Username/Password";
}
else {
$a = account_load($accounts_id);
$_SESSION['username']=$a['username'];
$_SESSION['email']=$a['email'];
$_SESSION['accounts_id']=$accounts_id;
$_SESSION['superuser'] = ($a['superuser'] == 'yes') ? 'yes' : 'no';
$_SESSION['roles']=array();
$status=user_conference_load($accounts_id,$_SESSION['conferences_id']);
$ret['status']="ok";
$ret['account']=$a;
$ret['roles']=$_SESSION['roles'];
}
}
if($request[1]=="logout") {
unset($_SESSION['username']);
unset($_SESSION['email']);
unset($_SESSION['accounts_id']);
unset($_SESSION['superuser']);
unset($_SESSION['roles']);
$ret['status']="ok";
}
break;
case "testauth":
if($request[1]) {
$ok=api_user_auth_required($request[1]);
}
else {
$ok=api_user_auth_required();
}
if($ok['status']=="ok") {
$ret['status']='ok';
}
else {
$ret['status']="error";
$ret['error']=$ok['error'];
}
break;
case "soteams":
api_user_auth_required('teacher');
break;
default:
$ret['status']="error";
$ret['error']="Invalid API command ({$request[0]})";

View File

@ -557,6 +557,59 @@ function user_auth_required($all_required = array(), $one_required = array())
return $match[0];
}
/* Perform some checks. Make sure the person is logged in, and that their
* password hasn't expired (the password_expired var is set in the login page)
*/
function api_user_auth_required($all_required = array(), $one_required = array())
{
global $config;
$ok = true;
$ret=array();
if(!isset($_SESSION['roles'])) {
$ret['status']="error";
$ret['error']="Not logged in";
return $ret;
}
/* Make sure the user has each role in $all_required, this returns
* an array in the same order as $all_required, with all members
* in $all_required that are also in the session roles */
if(!is_array($all_required)) $all_required = array($all_required);
$match = array_intersect($all_required, $_SESSION['roles']);
if($all_required != $match) {
/* Something is missing */
$ok = false;
}
/* Make sure the user has one role in $one_required */
if(!is_array($one_required)) $one_required = array($one_required);
if(count($one_required)) {
$match = array_intersect($one_required, $_SESSION['roles']);
if(count($match) == 0) {
/* Missing any role in $one_required */
$ok = false;
}
}
if(!$ok) {
$ret['status']="error";
$ret['error']="You do not have permission to access that information";
exit;
}
/* Forward to password expired, remember the target URI */
if($_SESSION['password_expired'] == true) {
$ret['status']="error";
$ret['error']="Your password has expired";
exit;
}
$ret['status']="ok";
$ret['match']=$match[0];
return $ret;
}
function user_volunteer_registration_status()
{
@ -666,4 +719,154 @@ function superuser_required() {
}
}
function try_login($user, $pass)
{
/* Ensure sanity of inputs */
/* User could be a username, or could be an email, check */
if(!account_valid_user($user) && !account_valid_email($user)) {
return false;
}
/* Don't check for a valid password, administrators can set any password they'd like, but
* there has to be a password */
if(!strlen($pass)) {
return false;
}
$user = mysql_real_escape_string($user);
$q = mysql_query("SELECT id,password,deleted FROM accounts WHERE username='$user'");
echo mysql_error();
/*
$q = mysql_query("SELECT id,username,password,year,deleted
FROM users
WHERE username='$user'
AND deleted='no'
ORDER BY year DESC LIMIT 1");
*/
if(mysql_num_rows($q) < 1) return false;
$r = mysql_fetch_assoc($q);
/* See if the user account has been deleted */
if($r['deleted'] == 'yes') return false;
/* See if the password matches */
if($r['password'] != $pass) return false;
/* Login successful */
return $r['id'];
}
function user_conference_load($accounts_id,$conferences_id) {
global $config;
/* Use the active conference to find the user id to load */
/* FIXME: Need to be able to handle the case where there is no
* active conference, but one step at a time */
$q = mysql_query("SELECT id FROM users WHERE accounts_id=$accounts_id AND conferences_id=$conferences_id");
if(mysql_num_rows($q) == 0) {
/* FIXME: this should probably just return false, but for now, see if there's an error */
return false;
// header("location: user_edit.php");
// echo "No user {$accounts_id} for conference {$_SESSION['conferences_id']}";
exit;
}
if(mysql_num_rows($q) > 1) {
echo "DATABASE ERROR: More than one user for account $accounts_id conference {$conferences_id}";
exit;
}
$uid = mysql_fetch_assoc($q);
$id = $uid['id'];
$u = user_load($id);
$_SESSION['name']="{$u['firstname']} {$u['lastname']}";
$_SESSION['users_id']=$u['id'];
$_SESSION['roles']=array_keys($u['roles']);
/* Load the password expiry for each user role, and
* find the longest expiry, which is the one we'll use
* for this user to determine if the passwd has
* expired. */
$longest_expiry = 0;
foreach(array_keys($u['roles']) as $r) {
$e = $config["{$r}_password_expiry_days"];
if($e == 0) {
/* Catch a never expire case. */
$longest_expiry = 0;
break;
} else if($e > $longest_expiry) {
$longest_expiry = $e;
}
}
if($u['passwordset'] == '0000-00-00') {
/* Force the password to expire */
$_SESSION['password_expired'] = true;
} else if($longest_expiry == 0) {
/* Never expires */
unset($_SESSION['password_expired']);
} else {
/* Check expiry */
$expires = date('Y-m-d', strtotime("{$u['passwordset']} +$longest_expiry days"));
$now = date('Y-m-d');
if($now > $expires) {
$_SESSION['password_expired'] = true;
} else {
unset($_SESSION['password_expired']);
}
}
/* If password_expired == true, the main page (or any
* other user page) will catch this and require
* them to set a password */
/* Call login functions for each role */
foreach(array_keys($u['roles']) as $r) {
if(is_callable("user_{$r}_login")) {
call_user_func_array("user_{$r}_login", array($u));
}
}
// mysql_query("UPDATE accounts SET lastlogin=NOW()
// WHERE id={$u['id']}");
/* Setup multirole so a multirole user can switch if they want to
* without logging in/out */
/* if(count($u['roes']) > 1) {
$_SESSION['multirole'] = true;
} else {
$_SESSION['multirole'] = false;
}
*/
/* See if there is a redirect, and do that instead of
* taking them to their main page */
/* if($redirect != '') {
switch($redirect) {
case 'roleadd':
if(!user_valid_role($multirole_data))
$multirole_data = '';
header("location: user_multirole.php?action=add&role=$multirole_data");
exit;
case 'roleattached':
message_push(happy(i18n('The %1 role has been attached to your account', array($roles[$role]['name']))));
message_push(notice(i18n('Use the [Switch Roles] link in the upper right to change roles while you are logged in')));
header("location: {$role}_main.php");
exit;
}
}
*/
/* Is there a saved requesT_uri from a failed login attempt?, if so
* take them there */
if(array_key_exists('request_uri', $_SESSION)) {
// header("location: {$_SESSION['request_uri']}");
unset($_SESSION['request_uri']);
return $_SESSION['request_uri'];
}
return "user_main.php";
// header("location: user_main.php");
//exit;
}
?>

View File

@ -27,154 +27,6 @@ require_once('common.inc.php');
require_once('account.inc.php');
require_once('user.inc.php');
function try_login($user, $pass)
{
/* Ensure sanity of inputs */
/* User could be a username, or could be an email, check */
if(!account_valid_user($user) && !account_valid_email($user)) {
return false;
}
/* Don't check for a valid password, administrators can set any password they'd like, but
* there has to be a password */
if(!strlen($pass)) {
return false;
}
$user = mysql_real_escape_string($user);
$q = mysql_query("SELECT id,password,deleted FROM accounts WHERE username='$user'");
echo mysql_error();
/*
$q = mysql_query("SELECT id,username,password,year,deleted
FROM users
WHERE username='$user'
AND deleted='no'
ORDER BY year DESC LIMIT 1");
*/
if(mysql_num_rows($q) < 1) return false;
$r = mysql_fetch_assoc($q);
/* See if the user account has been deleted */
if($r['deleted'] == 'yes') return false;
/* See if the password matches */
if($r['password'] != $pass) return false;
/* Login successful */
return $r['id'];
}
function user_conference_load($accounts_id,$conferences_id) {
global $config;
/* Use the active conference to find the user id to load */
/* FIXME: Need to be able to handle the case where there is no
* active conference, but one step at a time */
$q = mysql_query("SELECT id FROM users WHERE accounts_id=$accounts_id AND conferences_id=$conferences_id");
if(mysql_num_rows($q) == 0) {
/* FIXME: this should probably just return false, but for now, see if there's an error */
header("location: user_edit.php");
// echo "No user {$accounts_id} for conference {$_SESSION['conferences_id']}";
exit;
}
if(mysql_num_rows($q) > 1) {
echo "DATABASE ERROR: More than one user for account $accounts_id conference {$conferences_id}";
exit;
}
$uid = mysql_fetch_assoc($q);
$id = $uid['id'];
$u = user_load($id);
$_SESSION['name']="{$u['firstname']} {$u['lastname']}";
$_SESSION['users_id']=$u['id'];
$_SESSION['roles']=array_keys($u['roles']);
/* Load the password expiry for each user role, and
* find the longest expiry, which is the one we'll use
* for this user to determine if the passwd has
* expired. */
$longest_expiry = 0;
foreach(array_keys($u['roles']) as $r) {
$e = $config["{$r}_password_expiry_days"];
if($e == 0) {
/* Catch a never expire case. */
$longest_expiry = 0;
break;
} else if($e > $longest_expiry) {
$longest_expiry = $e;
}
}
if($u['passwordset'] == '0000-00-00') {
/* Force the password to expire */
$_SESSION['password_expired'] = true;
} else if($longest_expiry == 0) {
/* Never expires */
unset($_SESSION['password_expired']);
} else {
/* Check expiry */
$expires = date('Y-m-d', strtotime("{$u['passwordset']} +$longest_expiry days"));
$now = date('Y-m-d');
if($now > $expires) {
$_SESSION['password_expired'] = true;
} else {
unset($_SESSION['password_expired']);
}
}
/* If password_expired == true, the main page (or any
* other user page) will catch this and require
* them to set a password */
/* Call login functions for each role */
foreach(array_keys($u['roles']) as $r) {
if(is_callable("user_{$r}_login")) {
call_user_func_array("user_{$r}_login", array($u));
}
}
// mysql_query("UPDATE accounts SET lastlogin=NOW()
// WHERE id={$u['id']}");
/* Setup multirole so a multirole user can switch if they want to
* without logging in/out */
/* if(count($u['roes']) > 1) {
$_SESSION['multirole'] = true;
} else {
$_SESSION['multirole'] = false;
}
*/
/* See if there is a redirect, and do that instead of
* taking them to their main page */
/* if($redirect != '') {
switch($redirect) {
case 'roleadd':
if(!user_valid_role($multirole_data))
$multirole_data = '';
header("location: user_multirole.php?action=add&role=$multirole_data");
exit;
case 'roleattached':
message_push(happy(i18n('The %1 role has been attached to your account', array($roles[$role]['name']))));
message_push(notice(i18n('Use the [Switch Roles] link in the upper right to change roles while you are logged in')));
header("location: {$role}_main.php");
exit;
}
}
*/
/* Is there a saved requesT_uri from a failed login attempt?, if so
* take them there */
if(array_key_exists('request_uri', $_SESSION)) {
header("location: {$_SESSION['request_uri']}");
unset($_SESSION['request_uri']);
exit;
}
header("location: user_main.php");
exit;
}
/* Don't do any login stuff if they're already logged in */
if(isset($_SESSION['accounts_id'])) {
/* They're already logged in, if they're not trying to logout, don't
@ -253,11 +105,17 @@ if(isset($_SESSION['accounts_id'])) {
$_SESSION['superuser'] = ($a['superuser'] == 'yes') ? 'yes' : 'no';
$_SESSION['roles']=array();
user_conference_load($accounts_id,$_SESSION['conferences_id']);
$val=null;
if($val=user_conference_load($accounts_id,$_SESSION['conferences_id'])) {
header("Location: $status");
}
} else if($_GET['action']=="switchconference") {
//get rid of their current roles, and load their record for the new conference
$_SESSION['roles']=array();
user_conference_load($_SESSION['accounts_id'],$_SESSION['conferences_id']);
if($val=user_conference_load($_SESSION['accounts_id'],$_SESSION['conferences_id'])) {
header("Location: $val");
}
} else if($_GET['action']=='logout') {
/* Session keys to skip on logout */
$skip = array('debug', 'lang', 'messages');
@ -310,6 +168,7 @@ if(isset($_SESSION['accounts_id'])) {
<div style="font-size: 0.75em;">
<?=i18n('If you didn\'t register using an email address and you have lost your password, please contact the committee to have your password reset.')?></div><br />
<?
send_footer();
}
else if($_POST['action'] == "recoverconfirm")
{
@ -406,8 +265,7 @@ if(isset($_SESSION['accounts_id'])) {
break;
}
send_footer();
}
send_footer();
?>