diff --git a/authentication.php b/authentication.php new file mode 100644 index 0000000..a7398ec --- /dev/null +++ b/authentication.php @@ -0,0 +1,293 @@ + */ + +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 (); + + 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"] =
+ _("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;
+ 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"] =
+ _("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-> savedatas ($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 = _("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 datas if the authentication is
+ correct,
+ an exception if noting is found */
+ private function verifAuth ($email, $password)
+ {
+ 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)
+ {
+ $classname = "auth$method";
+ require_once ("domframework/$classname.php");
+
+ // If only one server is defined, the parameters can directely be pushed
+ // to the classname
+ if (! is_array ($this->authServers[$classname]))
+ {
+ $this->authServers[$classname] = array ($this->authServers[$classname]);
+ }
+ foreach ($this->authServers[$classname] as $key=>$serversParam)
+ {
+ if ($this->debug)
+ echo "Test auth server $method # $classname # $key\n";
+ $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 _("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 ();
+ });
+ }
+}