*/ require_once ("domframework/auth.php"); require_once ("domframework/authparams.php"); require_once ("domframework/authsession.php"); require_once ("domframework/ratelimit.php"); require_once ("domframework/ratelimitfile.php"); /** All the authentication protocol */ class authentication { /** The email of the authenticated/nonauthenticated user */ //private $email = "anonymous"; /** The debug of the authentication methods */ public $debug = 0; /** The route object */ private $route; /** Number of authentication maximum by minute */ public $ratelimitAuth = 3; /** Directory to store the ratelimit files */ public $ratelimitDir = "/tmp"; /** The rest authentication methods. Can be http, session, post. Attention : session case = CSRF ! */ public $restMethods = array ("http"); /** The html authentication methods. Can be http, session, post */ public $htmlMethods = array ("session"); /** The authentication methods. Can be ldap, sympa...*/ public $authMethods = array (); /** The authentication servers configuration array ("authXXXX"=>array ( array ("ldapserver"=>"ldaps://annuaire.grenoble.cnrs.fr", "ldapport"=>636, "ldaptimeout"=>5, "ldapauth"=>"uid=annuaire,ou=people,dc=grenoble,dc=cnrs,dc=fr", "ldappwd"=>";authANNUAIRE2013", "ldapbase"=>"", "ldapfilter"=>"(mail=%s)", "ldapfield"=>"mail", "ldapfiltersearch"=>"(objectClass=inetOrgPerson)" ), ), );*/ public $authServers = array (); /** The application Name displayed on authentication page */ public $appName = null; public function __construct ($route) { $this->route = $route; } /* public function email () { return $this->email; }*/ /** Disconnect the user */ public function logout () { if ($this->debug) echo "
LOGOUT\n";
$authsession = new authsession ();
$param = $authsession->getdetails ();
if ($this->debug) echo "Logout for '".$param["email"]."'\n";
trigger_error ("Logout for '".$param["email"]."'", E_USER_NOTICE);
$authsession->logout ();
unset ($_SESSION["domframework"]["authentication"]);
$_SESSION["domframework"]["authentication"]["message"] =
dgettext("domframework", "You have been logged out");
if ($this->debug) echo "Redirect to authentication page";
if ($this->debug) $this->route->debug = $this->debug;
$this->route->redirect ("/authentication", "");
}
/** Display the login page */
public function pageHTML ($url = "")
{
// If the user is already connected, redirect to the main page of the site
$auth = new auth ();
$pre = new authparams (array ("session"));
if (isset ($_SESSION["domframework"]["authentication"]["message"]))
$message = $_SESSION["domframework"]["authentication"]["message"];
else
$message = "";
unset ($_SESSION["domframework"]["authentication"]["message"]);
$alreadyAuth = false;
if ($pre->email !== "anonymous")
$alreadyAuth = $pre->email;
if ($this->appName !== null)
$auth->appName = $this->appName;
echo $auth->pageHTML ($this->route->baseURL(), $message, $url,
$alreadyAuth);
}
/** Check the authentication page */
public function verifAuthLoginPage ($url = "")
{
// rate-limit the connections
$ratelimiter = new ratelimitfile ();
// 3 connections by minutes
$ratelimiter->maxEntries = $this->ratelimitAuth;
$ratelimiter->storageDir = $this->ratelimitDir;
if (isset ($_SERVER["HTTP_X_FORWARDED_FOR"]))
$ipClient = $_SERVER["HTTP_X_FORWARDED_FOR"];
else
$ipClient = $_SERVER["REMOTE_ADDR"];
if ($ratelimiter->set ("loggin-$ipClient") === false)
{
trigger_error ("Ratelimiting for $ipClient", E_USER_WARNING);
$_SESSION["domframework"]["authentication"]["message"] =
dgettext("domframework", "Too much connections");
if ($url === "")
{
$this->route->redirect ("/authentication", "");
}
else
{
$this->route->redirect ("/authentication/$url", "");
}
}
$authparams = new authparams (array ("post"));
$res = $this->verifAuth ($authparams->email, $authparams->password);
if (! is_array ($res))
{
// Authentication error
// Redirect to login page after logout
trigger_error ("Logging error for '$authparams->email' (HTML) : $res",
E_USER_WARNING);
$authsession = new authsession ();
$authsession->logout ();
$baseURL = $this->route->baseURL ();
$_SESSION["domframework"]["authentication"]["message"] = $res;
// Check the provided URL before using it
if ($url === "")
{
$this->route->redirect ("/authentication", "");
}
else
{
$this->route->redirect ("/authentication/$url", "");
}
}
// Login OK : save in SESSION and go to main page
trigger_error ("Logging in for '$authparams->email'", E_USER_NOTICE);
$session = new authsession ();
$session-> savedata ($authparams->email, $authparams->password,
$res["lastname"], $res["firstname"]);
if ($url === "")
$this->route->redirect ("/", "");
else
$this->route->redirect ("/$url", "");
}
/** Check all the REST API */
public function verifAuthREST ()
{
$authparams = new authparams ($this->restMethods);
$res = array ("email"=>"anonymous", "password"=>"anonymous");
if ($authparams->email !== "anonymous" &&
$authparams->password !== "anonymous")
{
if ($this->debug)
echo "verifAuth ($authparams->email, $authparams->password)\n";
$res = $this->verifAuth ($authparams->email, $authparams->password);
}
if (! is_array ($res))
{
trigger_error ("Logging error for '$authparams->email' (REST) : $res",
E_USER_WARNING);
// Authentication error
// TODO : header 401 ? Block previously in the framework auth process
exit;
}
return $res;
}
/** Check all the others pages of the site */
public function verifAuthHTML ()
{
if ($this->debug) echo "verifAuthHTML() : ";
$authparams = new authparams ($this->htmlMethods);
// Don't ask to the provider if anonymous is known
if ($authparams->email === "anonymous" || $authparams->email === null)
{
if ($this->debug) echo "Anonymous\n";
return array ("email"=>"anonymous", "lastname"=>"Anonymous",
"firstname"=>"", "password"=>"");
}
if ($this->debug)
echo "verifAuth ($authparams->email, $authparams->password)\n";
$res = $this->verifAuth ($authparams->email, $authparams->password);
if (! is_array ($res))
{
// Authentication error
if ($this->debug) echo "Previous session not found";
$msg = dgettext("domframework", "Previous session not found");
$_SESSION["domframework"]["authentication"]["message"] = $msg;
trigger_error ("Previous session not found for '$authparams->email'",
E_USER_WARNING);
$url = $this->route->requestURL();
$this->route->redirect ("/authentication/$url");
}
return $res;
}
/** Do the real authentication process on all the providers defined in the
properties of the class.
@return an array containing the user data if the authentication is
correct,
an exception if noting is found */
private function verifAuth ($email, $password)
{
if (! is_array ($this->authMethods) || count ($this->authMethods) === 0)
throw new Exception ("No authentication method defined", 500);
if (isset ($_SESSION["domframework"]["authentication"]["lastcheck"]) &&
$_SESSION["domframework"]["authentication"]["lastcheck"] + 180 <
time ())
{
// Test the authentication each 3 minutes if there is a session, else
// return the previous values
return $_SESSION["domframework"]["authentication"]["authcache"];
}
foreach ($this->authMethods as $method)
{
if (! is_string ($method))
throw new Exception ("The authentication method is not a string", 500);
$classname = "auth$method";
require_once ("domframework/$classname.php");
if (! array_key_exists ($classname, $this->authServers))
throw new Exception ("No authentication server '$classname' enabled",
500);
// If only one server is defined, the parameters can directely be pushed
// to the classname
if (! is_array (reset ($this->authServers[$classname])))
{
$this->authServers[$classname] = array ($this->authServers[$classname]);
}
if (! is_array ($this->authServers[$classname]) ||
count ($this->authServers[$classname]) === 0)
throw new Exception ("No authentication server defined for method ".
"'$method'", 500);
foreach ($this->authServers[$classname] as $key=>$serversParam)
{
if ($this->debug)
echo "Test auth server $method # $classname # $key\n";
if (! is_array ($serversParam))
throw new Exception ("Auth Server $key configuration error : ".
"not an array", 500);
$authmethod = new $classname ();
foreach ($serversParam as $param=>$value)
{
$authmethod->$param = $value;
}
$authmethod->connect ();
try
{
$authmethod->authentication ($email, $password);
$_SESSION["domframework"]["authentication"]["authcache"] =
$authmethod->getdetails ();
$_SESSION["domframework"]["authentication"]["lastcheck"] = time ();
return $authmethod->getdetails ();
}
catch (Exception $e)
{
trigger_error ("Authentication error for '$email' : ".
"$classname : ".$e->getMessage(), E_USER_WARNING);
}
}
}
trigger_error ("Bad login/password for '$email'", E_USER_WARNING);
return dgettext("domframework", "Bad login/password");
}
/** Add the authentication routes to the routing model */
public function routes ()
{
$authObj = $this;
$this->route->get ("authentication/logout", function () use ($authObj)
{
$authObj->logout ();
});
$this->route->get ("authentication/{url}", function ($url) use ($authObj)
{
$authObj->pageHTML ($url);
});
$this->route->post ("authentication/{url}", function ($url) use ($authObj)
{
$authObj->verifAuthLoginPage ($url);
});
$this->route->get ("authentication", function () use ($authObj)
{
$authObj->pageHTML ();
});
$this->route->post ("authentication", function () use ($authObj)
{
$authObj->verifAuthLoginPage ();
});
}
}