diff --git a/CHANGELOG-3.0.3.md b/CHANGELOG-3.0.3.md new file mode 100644 index 0000000..67d02a2 --- /dev/null +++ b/CHANGELOG-3.0.3.md @@ -0,0 +1,33 @@ +PHP client for Tequila, v. 2.0.4 (Tue Nov 14 10:47:18 CET 2006) +(C) 2004, Lionel Clavien [lionel dot clavien AT epfl dot ch] +This code is released under the GNU GPL v2 terms (see LICENCE file). + +Changelog: + 0.1.0, 2004-06-27: Creation + 0.1.1, 2004-08-29: Changed RSA authentication method to use the new + server certificate in lieu of the server public key + [openssl bug ?] + 0.1.2, 2004-09-04: Configuration options put in tequila_config.inc.php + ...... + + 2.0.3 : I forgot. + 2.0.4 : Fix problem with cookie. Now it is a session cookie. + 2.0.5 : Fix ERROR_SESSION_FILE (replace with ERROR_SESSION_FILE_FORMAT). + Fix bug in fetchAttributes(). + + 3.0.0 : Big rewrite. + Fix session time out + use PHP sessions + hide key attribute in urlaccess. + + 3.0.1 : Fix INFO_PATH & QUERY_STRING test. + 3.0.2 : 2011-08-05 : Include comments from Lucien Chaboudez + Define MIN_SESSION_TIMEOUT + Delete cookie with explicit root path + + 3.0.3 : 2012-04-12 : Patch from Lucien Chaboudez + LoadSession :Check if all the wanted attributes are present + in the $_SESSION. + +TODO: + - implement more documented features (allows, ?) diff --git a/tequila.php b/tequila.php index b3e37e1..b7f817a 100644 --- a/tequila.php +++ b/tequila.php @@ -1,304 +1,267 @@ serverURL = $server . TequilaClient::TEQUILA_BIN; $this->timeout = $timeout; $this->language = $language; $this->applicationURL = $applicationURL; $this->applicationName = $applicationName; $this->stack = GuzzleHttp\HandlerStack::create($handler); // if no application URL was specified, we try to generate it if (empty($this->applicationURL)) { $protocol = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https://" : "http://"; $this->applicationURL = $protocol . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF']; if (!empty($_SERVER['PATH_INFO'])) $this->applicationURL .= $_SERVER['PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) $this->applicationURL .= "?" . $_SERVER['QUERY_STRING']; } } /** * @brief User authentication to server * * @param $wantedAttributes - (optional) List of attributes about the user that the server will return * @param $filters - (optional) Filters that will be applied to the user attributes * @param $authorised - (optional) Tequila server restrictions to lift */ public function authenticate( array $wantedAttributes = array(), string $filters = "", string $authorised = "", string $allowedRequestHosts = "") { // session_start(); if ($this->preExistingSession()) return; // check if a session creation was already started if (!empty($_COOKIE[TequilaClient::COOKIE_NAME])) { $this->key = $_COOKIE[TequilaClient::COOKIE_NAME]; $attributes = $this->fetchAttributes($_COOKIE[TequilaClient::COOKIE_NAME], $allowedRequestHosts); if (!empty($attributes)) { $this->createSession($attributes); return; } } $this->key = $this->createRequest($wantedAttributes, $filters, $authorised); setcookie(TequilaClient::COOKIE_NAME, $this->key, array( 'expires' => TequilaClient::COOKIE_LIFE, 'httponly' => true, "secure" => true, )); header("Location: {$this->serverURL}/requestauth?requestkey={$this->key}"); exit; } /** * @brief Logout from Tequila server * * @param $redirectUrl - (optional) URL to redirect to after logout */ public function logout(string $redirectUrl = "") { session_destroy(); // Delete cookie by setting expiration time in the past with root path setcookie(TequilaClient::COOKIE_NAME, "", time() - 3600); $this->contactServer("logout"); $redirectUrl = empty($redirectUrl) ? $this->applicationURL : urlencode($redirectUrl); header("Location: {$this->serverURL}/logout?urlaccess={$redirectUrl}"); } /** * @brief Sends an authentication request * * @param $wantedAttributes - (optional) List of attributes about the user that the server will return * @param $filters - (optional) Filters that will be applied to the user attributes * @param $authorised - (optional) Tequila server restrictions to lift * * @return Key returned by the Tequila server */ private function createRequest(array $wantedAttributes = array(), string $filters = "", string $authorised = "") : string { $body = array(); $body["urlaccess"] = $this->applicationURL; $body["dontappendkey"] = "1"; $body["language"] = $this->language; $body["service"] = $this->applicationName; $body["request"] = implode(TequilaClient::BODY_GLUE, $wantedAttributes); $body["allows"] = $filters; $body["require"] = $authorised; $res = $this->contactServer('createrequest', $body); // return the key return substr(trim($res), 4); } /** * @brief Retrieve the attributes of an authenticated user * (i.e. the ones requested when establishing an authentication) * * @param $key - the request key * * @return Array containing all the user attributes */ private function fetchAttributes(string $key, string $allowedRequestHosts) : array { $body = array(); $body["key"] = $key; if (!empty($allowedRequestHosts)) $body["allowedrequesthosts"] = preg_split("/\\r\\n|\\r|\\n/", $allowedRequestHosts); $res = $this->contactServer('fetchattributes', $body); $result = array(); $attributes = explode("\n", $res); foreach ($attributes as $attribute) { $attribute = trim($attribute); if (!$attribute) continue; list($key, $val) = explode("=", $attribute, 2); $result[$key] = $val; } return $result; } /** * @brief Sends a POST request to one of the servers endpoints * * @param $endpoint - the server endpoint to contact * @param $fields - (optional) the fields to add to the requests body * * @throws TequilaException if the server returns a code other than 200, that no connection could be established * or that we're trying to acces an unknow endpoint * * @return Body of the server response */ private function contactServer($endpoint, $fields = array()) : string { // check if it's a valid endpoint if (!in_array($endpoint, TequilaClient::SERVER_ENDPOINTS)) { error_log('auth_tequila: Trying to access unknown endpoint: ' . $endpoint); throw new TequilaException("Unknown endpoint"); } try { $client = new GuzzleHttp\Client([ 'base_uri' => $this->serverURL . "/", "handler" => $this->stack ]); /** * Note: First things first, sorry for the horrible code that follows. * So, the Tequila server doesn't understand/use normal POST requests and * only works cleartext body. */ $reqBody = []; if (is_array($fields) && count($fields)) { foreach ($fields as $key => $val) { $reqBody[] = "{$key}={$val}"; } } $response = $client->request("POST", $endpoint, [ "body" => implode("\n", $reqBody) . "\n", ]); return $response->getBody(); } catch (GuzzleHttp\Exception\RequestException $e) { $response = $e->getResponse(); error_log("auth_tequila: Tequila server returned unexpected HTTP code: [{$response->getStatusCode()}] {$response->getReasonPhrase()}"); throw new TequilaException("Unexpected return from server : [{$response->getStatusCode()}] {$response->getReasonPhrase()}", 1, $e); } catch (GuzzleHttp\Exception\ConnectException $e) { error_log("auth/tequila: connection to {$this->serverURL} server failed "); throw new TequilaException("Connection to server failed", 0, $e); } } /** * @brief Check if a session was previously established * * @return True if a session was previously established * @return False if no session was previously established */ private function preExistingSession() : bool { if (empty($_SESSION)) return false; // check if the session hasn't expired if ((time() - $_SESSION["creation"]) > $this->timeout) return false; $this->key = $_SESSION ['key']; return true; } /** * @brief Establish a new session * * @param $attributes - the user attributes returned by the server */ private function createSession(array $attributes) { $_SESSION["creation"] = time(); foreach ($attributes as $key => $val) { echo("{$key} {$val}"); $this->attributes[$key] = $val; $_SESSION[$key] = $val; } } public function getKey() : string { return $this->key; } public function getAttributes() : array { return $this->attributes; } }