From b530e933e5699d513de7922bc7a8a1fbff13386a Mon Sep 17 00:00:00 2001 From: nik2208 Date: Sun, 15 Oct 2023 18:54:28 +0200 Subject: [PATCH 1/2] Update auth.php improvements to be discussed --- auth.php | 127 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 108 insertions(+), 19 deletions(-) diff --git a/auth.php b/auth.php index ba417f1..5211e3b 100644 --- a/auth.php +++ b/auth.php @@ -1,6 +1,6 @@ 'sha256', @@ -16,6 +16,8 @@ function generateToken($subject, $audience, $issuer, $time, $ttl, $algorithm, $s $token = array(); $token[0] = rtrim(strtr(base64_encode(json_encode((object) $header)), '+/', '-_'), '='); $claims['sub'] = $subject; + $claims['email'] = $user->email; // added email to claims + $claims['role'] = $user->role; // added role to claims $claims['aud'] = $audience; $claims['iss'] = $issuer; $claims['iat'] = $time; @@ -48,10 +50,13 @@ function serve($file) echo file_get_contents($file); } -function handleGet($config, $session) +function handleGet($config, $session, $logout, $error) { - if (empty($session)) { - serve($config['login']); + if ($error) { + redirect($config['loginError']); // redirect (instead of serving an html page) to login application with error parameter set to=1 in case of failed login (used to display error message) + } + if (empty($session) || $logout ) { + redirect($config['login']); // redirect (instead of serving an html page) to login application in case of missing token } else { redirect(generateTokenUrl($config, $session)); } @@ -62,6 +67,11 @@ function getSecure() return isset($_SERVER['HTTPS']) && !in_array(strtolower($_SERVER['HTTPS']), array('off', 'no')); } +function getHost() // get host name, used to set the instance server name as issuer +{ + return $_SERVER['HTTP_HOST']; +} + function getFullUrl() { return (getSecure() ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; @@ -70,26 +80,29 @@ function getFullUrl() function generateTokenUrl($config, $session) { $time = getConfig($config, 'time', time()); - $ttl = getConfig($config, 'ttl', 5); + $ttl = getConfig($config, 'ttl', 3600); $algorithm = getConfig($config, 'algorithm', 'HS256'); $secret = getConfig($config, 'secret', ''); - $subject = $session['username']; + $subject = $session['user']->uuid; + $user = $session['user']; $audience = $config['audience']; - $issuer = getFullUrl(); - $token = generateToken($subject, $audience, $issuer, $time, $ttl, $algorithm, $secret); + $issuer = getHost(); + $token = generateToken($subject, $user, $audience, $issuer, $time, $ttl, $algorithm, $secret); $redirectUri = getConfig($config, 'redirectUri', ''); return $redirectUri . '#access_token=' . $token; } function handlePost($config, &$session, $username, $password) { - $validate = getConfig($config, 'validate', function ($username, $password) {return false;}); + $validate = getConfig($config, 'validate', function ($username, $password) { + return false; + }); $valid = call_user_func($validate, $username, $password); - if (!$valid) { - serve($config['login']); + if (!$valid['success']) { + redirect($config['loginError']); // added redirect to login page with error parameter set to=1 in case of failed login (used to display error message) } else { session_regenerate_id(); - $session['username'] = $username; + $session['user'] = $valid['payload']; redirect(generateTokenUrl($config, $session)); } } @@ -107,9 +120,14 @@ function getConfig($config, $key, $default) function main($config) { session_start(); + $logout = isset($_GET['logout']) ? $_GET['logout'] : '0'; // added logout parameter as logout flag to unset the php session + $error = isset($_GET['error']) ? $_GET['error'] : '0'; // added error parameter as error flag to enter in error state $clientId = isset($_GET['client_id']) ? $_GET['client_id'] : 'default'; $audience = isset($_GET['audience']) ? $_GET['audience'] : 'default'; $redirectUri = isset($_GET['redirect_uri']) ? $_GET['redirect_uri'] : ''; + if ($logout) { + session_unset(); // unset the php session + } if (isset($config[$clientId][$audience])) { $config = $config[$clientId][$audience]; $config['clientId'] = $clientId; @@ -121,7 +139,7 @@ function main($config) if (isset($config['redirectUri'])) { switch ($_SERVER['REQUEST_METHOD']) { case 'GET': - handleGet($config, $_SESSION); + handleGet($config, $_SESSION, $logout, $error); //added logout and error parameters break; case 'POST': handlePost($config, $_SESSION, $_POST['username'], $_POST['password']); @@ -135,15 +153,86 @@ function main($config) } } +//implementation examples main([ - 'default' => [ - 'api.php' => [ + 'default' => [ // client_id + 'example1' => [ // audience1 'secret' => 'someVeryLongPassPhraseChangeMe', - 'login' => 'login.html', - 'redirects' => 'http://localhost/vanilla.html', - 'validate' => function ($username, $password) { - return $username == 'admin' && $password == 'admin'; + 'login' => 'https://login.example1.com/', // redirection to login application in case of missing token + 'loginError' => 'https://login.example1.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) + 'redirects' => 'https://app.example1.com', // redirects to application in case of successful login + 'validate' => function ($username, $password) { // validation of username and password, this example uses api.php and dbauth middleware + $url = "api.example1.com/authapi.php/login"; // this instance of api.php is configured to use dbauth middleware + $data = array('username' => $username, 'password' => $password); + $options = array( + 'http' => array( + 'header' => "Content-type: application/x-www-form-urlencoded", + 'method' => 'POST', + 'content' => http_build_query($data) + ) + ); + $context = stream_context_create($options); + $resp = file_get_contents($url, false, $context); // retreived user data from authapi.php + preg_match('/([0-9])\d+/', $http_response_header[0], $matches); // response code from authapi.php + $responsecode = intval($matches[0]); + return array('success' => ($responsecode == 200), 'payload' => $resp); // return success status and user data, user data will be used to generate the jwt token }, ], + 'example2' => [ // audience2 + 'secret' => 'someVeryLongPassPhraseChangeMe', + 'login' => 'https://login.example2.com/', // redirection to login application in case of missing token + 'loginError' => 'https://login.example2.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) + 'redirects' => 'https://app.example2.com', // redirects to application in case of successful login + 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload + $valid = $username == 'company_admin_account' && $password == 'password'; + $response = array( + 'success' => ($valid == true), + 'payload' => json_decode('{ + "uuid": "admin@example2.com", + "email": "admin@example2.com", + "role": "admin" + }') + ); + return $response; + } + ] ], + 'development_team_example' => [ // client_id + 'developer1' => [ // audience1 - developer1 + 'secret' => 'someVeryLongPassPhraseChangeMe', + 'login' => 'https://login.devel.example1.com/', // redirection to login application in case of missing token + 'loginError' => 'https://login.devel.example1.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) + 'redirects' => 'http://localhost:8080/', // redirects to localhost development environment + 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload + $valid = $username == 'developer1' && $password == 'password'; + $response = array( + 'success' => ($valid == true), + 'payload' => json_decode('{ + "uuid": "developer1", + "email": "devel1@developerteam.com", + "role": "developer" + }') + ); + return $response; + } + ], + 'developer2' => [ // audience2 - developer2 + 'secret' => 'someVeryLongPassPhraseChangeMe', + 'login' => 'https://login.devel.example2.com/', // redirection to login application in case of missing token + 'loginError' => 'https://login.devel.example2.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) + 'redirects' => 'http://localhost:8081/', // redirects to application in case of successful login + 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload + $valid = $username == 'developer2' && $password == 'password'; + $response = array( + 'success' => ($valid == true), + 'payload' => json_decode('{ + "uuid": "developer2", + "email": "devel2@developerteam.com", + "role": "developer" + }') + ); + return $response; + } + ] + ] ]); From f008dfddd97cda5f381c26f3ba36e46407c581cb Mon Sep 17 00:00:00 2001 From: nik2208 Date: Sun, 15 Oct 2023 19:46:22 +0200 Subject: [PATCH 2/2] added index and login pages --- auth.php | 14 +++++------ index.html | 31 +++++++++++++++++++++++ login.html | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 index.html diff --git a/auth.php b/auth.php index 5211e3b..d3516ad 100644 --- a/auth.php +++ b/auth.php @@ -1,5 +1,5 @@ 'https://login.example2.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) 'redirects' => 'https://app.example2.com', // redirects to application in case of successful login 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload - $valid = $username == 'company_admin_account' && $password == 'password'; + $valid = $username == 'company_admin_account' && $password == 'password'; $response = array( 'success' => ($valid == true), 'payload' => json_decode('{ @@ -204,7 +204,7 @@ function main($config) 'loginError' => 'https://login.devel.example1.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) 'redirects' => 'http://localhost:8080/', // redirects to localhost development environment 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload - $valid = $username == 'developer1' && $password == 'password'; + $valid = $username == 'developer1' && $password == 'password'; $response = array( 'success' => ($valid == true), 'payload' => json_decode('{ @@ -215,14 +215,14 @@ function main($config) ); return $response; } - ], + ], 'developer2' => [ // audience2 - developer2 'secret' => 'someVeryLongPassPhraseChangeMe', 'login' => 'https://login.devel.example2.com/', // redirection to login application in case of missing token 'loginError' => 'https://login.devel.example2.com?error=1', // redirection to login application with error parameter set to=1 in case of failed login (used to display error message) 'redirects' => 'http://localhost:8081/', // redirects to application in case of successful login 'validate' => function ($username, $password) { // validation of static username and password, with fixed payload - $valid = $username == 'developer2' && $password == 'password'; + $valid = $username == 'developer2' && $password == 'password'; $response = array( 'success' => ($valid == true), 'payload' => json_decode('{ diff --git a/index.html b/index.html new file mode 100644 index 0000000..b35a8cc --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + JWT EXAMPLE APP + + + + + + + \ No newline at end of file diff --git a/login.html b/login.html index 72dae86..8c2a0fc 100644 --- a/login.html +++ b/login.html @@ -1,5 +1,68 @@ -
- - - -
+ + + + + + Login + + + + + +

Login

+
+ +

+ +

+ +
+

+ + + + + +authUrl: "https://jwt.devel.tourismapp.it/", +auth: { +seg1: 'https://jwt.devel.tourismapp.it?audience=', +seg2: '&response_type=token&client_id=', +seg3: '&redirect_uri=https://', +seg4: '.tourismapp.it/' +}, \ No newline at end of file