From 5829288988bfc8e37d0b85a52debc55000eb6fa1 Mon Sep 17 00:00:00 2001 From: Dominique Fournier Date: Fri, 24 May 2019 11:58:25 +0000 Subject: [PATCH] Add authentication by JSON Web Token git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@5287 bf3deb0d-5f1a-0410-827f-c0cc1f45334c --- authentication.php | 41 +++++++++++++++--------- authjwt.php | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 authjwt.php diff --git a/authentication.php b/authentication.php index 75f3bb9..321f67e 100644 --- a/authentication.php +++ b/authentication.php @@ -28,12 +28,14 @@ class authentication /** Directory to store the ratelimit files */ public $ratelimitDir = "/tmp/ratelimit/"; - /** The rest authentication methods. Can be http, session, post. + /** The rest authentication methods. Can be post, session, http, shibboleth, + * jwt * Attention : session case = CSRF ! */ - public $restMethods = array ("http"); + public $restMethods = array ("http", "jwt"); - /** The html authentication methods. Can be http, session, post + /** The html authentication methods. Can be : post, session, http, shibboleth, + * jwt * The "post" is already used when using verifAuthLoginPage method (usually * only in authentication page) */ @@ -42,15 +44,21 @@ class authentication /** The authentication methods. Can be ldap, sympa...*/ public $authMethods = array (); + /** Add the server key used to create the JSON Web Token. + * Without it, the JWT is not added to the valid authentication page + */ + public $jwtServerKey = null; + /** The name of the JSON Web Token set in localStorage of the client browser * if the authentication is valid. Will be used later by JS on client with * Bearer authentication for REST API. */ - public $jwtName = null; + public $jwtName = "DFKJWT"; - /** Add the server key used to create the JSON Web Token + /** The JST Algorithm used to sign the JWT + * Allowed algorithms : HS256, HS512, HS384 */ - public $jwtServerKey = null; + public $jwtAlgorithm = "HS256"; /** The authentication servers configuration * array ("authXXXX" => array ( @@ -140,15 +148,16 @@ class authentication if (session_id () === "") session_start (); $auth = new auth (); - $pre = new authparams (array ("session")); + $authparams = new authparams (array ("session")); + $authparams->jwtServerKey = $this->jwtServerKey; 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 ($authparams->email !== "anonymous") + $alreadyAuth = $authparams->email; if ($this->appName !== null) $auth->appName = $this->appName; @header ('X-Frame-Options: SAMEORIGIN'); @@ -229,16 +238,16 @@ class authentication $session = new authsession (); $session->savedata ($authparams->email, $authparams->password, $res["lastname"], $res["firstname"]); - if ($this->jwtName !== null) + if ($this->jwtServerKey !== null) { // Set the JSON Web Token as the authentication is valid - if ($this->jwtServerKey === null) - throw new \Exception ("No authentication::jwtServerKey provided", 500); require_once ("domframework/jwt.php"); $payloadArray = array(); - $payloadArray['nbf'] = date ("Y-m-d H:i:s"); - $payloadArray['exp'] = date ("Y-m-d H:i:s", time () + 86400); - $token = jwt::encode ($payloadArray, $this->jwtServerKey); + $payloadArray['nbf'] = gmdate ("Y-m-d H:i:s"); + $payloadArray["email"] = $authparams->email; + $jwt = new jwt (); + $token = $jwt->encode ($payloadArray, $this->jwtServerKey, + $this->jwtAlgorithm); if ($this->route->debug) echo "Set the JSON Web Token '$this->jwtName' with value '$token'". "
\n"; @@ -261,6 +270,7 @@ class authentication echo "=== entering verifAuthREST (restMethods=". print_r ($this->restMethods, true).")\n"; $authparams = new authparams ($this->restMethods); + $authparams->jwtServerKey = $this->jwtServerKey; $res = array ("email"=>"anonymous", "password"=>"anonymous"); if ($authparams->email !== "anonymous" && $authparams->password !== "anonymous") @@ -291,6 +301,7 @@ class authentication echo "=== entering verifAuthHTML (htmlMethods=". print_r ($this->htmlMethods, true).")\n"; $authparams = new authparams ($this->htmlMethods); + $authparams->jwtServerKey = $this->jwtServerKey; // Don't ask to the provider if anonymous is known if ($authparams->email === "anonymous" || $authparams->email === null) { diff --git a/authjwt.php b/authjwt.php new file mode 100644 index 0000000..821be63 --- /dev/null +++ b/authjwt.php @@ -0,0 +1,77 @@ + + */ + +/** User authentication against JSON Web Token */ +class authjwt extends auth +{ + /** If the user is valid, return the email in details + */ + private $email = null; + /** No connection to JWT */ + public function connect () + // {{{ + { + return TRUE; + } + // }}} + + /** Try to authenticate the email/password of the user + * @param string $email Email to authenticate + * @param string $password Password to authenticate + */ + public function authentication ($email, $password) + { + if (! isset ($_SERVER["HTTP_AUTHENTICATION"])) + throw new \Exception ("No Authentication available", 401); + if (substr ($_SERVER["HTTP_AUTHENTICATION"], 0, 7) !== "Bearer") + throw new \Exception ("No Bearer Authentication available", 401); + // The JWT was tested in authparams. End of process + $this->email = $email; + } + + /** Return all the parameters recorded for the authenticate user */ + public function getdetails () + { + if ($email === null) + return array ("lastname" => "anonymous", + "firstname" => "", + "email" => "anonymous"); + return array ("email" => $this->email); + } + + /** Method to change the password : unavailable in SESSION auth + * @param string $oldpassword The old password (to check if the user have the + * rights to change the password) + * @param string $newpassword The new password to be recorded + */ + public function changepassword ($oldpassword, $newpassword) + { + throw new \Exception (dgettext ("domframework", + "The password can't be change for JWT users"), + 405); + } + + /** Method to overwrite the password (without oldpassword check) + * Must be reserved to the administrators. For the users, use changepassword + * method + * @param string $email the user identifier to select + * @param string $newpassword The new password to be recorded + */ + public function overwritepassword ($email, $newpassword) + { + throw new \Exception (dgettext ("domframework", + "The password can't be overwrite for JWT users"), + 405); + } + + /** Remove the information from the session */ + public function logout () + { + throw new \Exception (dgettext ("domframework", + "The logout is not available for JWT users"), + 405); + } +}