From ecce4d93427d55b92f29b8c2343deb7337c991d5 Mon Sep 17 00:00:00 2001 From: Danny Bessems Date: Fri, 22 Feb 2019 14:07:38 +0100 Subject: [PATCH 1/2] Redid formatting of README.md, taking into account Gitea's limited markdown rendering --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index bc1ffe7..c8c5c49 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,31 @@ [![](https://img.shields.io/badge/status-in%20production-%23003399.svg)](#) [![](https://img.shields.io/badge/contributors-1-green.svg) ](#) Forward Authentication for use with proxies (caddy, nginx, traefik, etc) + +## Usage +- Create a new folder, navigate to it in a commandprompt and run the following command: + `git clone https://code.spamasaurus.com/djpbessems/lucidAuth.git` +- Edit `include/lucidAuth.config.php.example` to reflect your configuration and save as `include/lucidAuth.config.php` +- Create a new website (within any php-capable webserver) and make sure that the documentroot points to the `public` folder +- Check if you are able to browse to `https:///lucidAuth.login.php` (where `` is the actual domain -or IP address- your webserver is listening on) +- Edit your proxy's configuration to use the new website as forward proxy: + - #### ~~in Caddy/nginx~~ (planned for a later stage) + + - #### in Traefik + Add the following lines (change to reflect your existing configuration): + ``` + [frontends.server1] + entrypoints = ["https"] + backend = "server1" + [frontends.server1.auth.forward] + address = "https:///lucidAuth.validateRequest.php" + [frontends.server1.routes] + [frontends.server1.routes.ext] + rule = "Host:" + ``` + +- #### Important! + The domainname of the website made in step 3, needs to match the domainname (*ignoring subdomains, if any*) of the resource utilizing this authentication proxy. + +## Questions or bugs +Feel free to open issues in this repository (or in its mirror on [GitHub](#)). \ No newline at end of file From 2f5b0e263ab03a44fa41231d44e31a070f05477d Mon Sep 17 00:00:00 2001 From: djpbessems Date: Mon, 25 Feb 2019 14:27:25 +0100 Subject: [PATCH 2/2] Restored vanished code & partially refactored returning json --- include/lucidAuth.functions.php | 9 ++++++ include/lucidAuth.template.php | 43 +++++++++++++-------------- public/lucidAuth.login.php | 35 +++++++++++++++++----- public/lucidAuth.setXDomainCookie.php | 24 +++++++++------ public/lucidAuth.validateRequest.php | 2 +- public/misc/script.index.js | 21 +++++-------- public/misc/style.css | 7 +++-- 7 files changed, 86 insertions(+), 55 deletions(-) diff --git a/include/lucidAuth.functions.php b/include/lucidAuth.functions.php index fcc7e36..55a626a 100644 --- a/include/lucidAuth.functions.php +++ b/include/lucidAuth.functions.php @@ -98,11 +98,17 @@ function validateToken (string $secureToken) { $jwtPayload = JWT::decode($secureToken, base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']); } catch (Exception $e) { // Invalid token + if ($settings->Debug['LogToFile']) { + file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token could not be decoded' . PHP_EOL, FILE_APPEND); + } return ['status' => 'Fail', 'reason' => '1']; } if ((int)$jwtPayload->iat < (time() - (int)$settings->Session['Duration'])) { // Expired token + if ($settings->Debug['LogToFile']) { + file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token has expired' . PHP_EOL, FILE_APPEND); + } return ['status' => 'Fail', 'reason' => '3']; } @@ -131,6 +137,9 @@ function validateToken (string $secureToken) { })) === 1) { return ['status' => 'Success']; } else { + if ($settings->Debug['LogToFile']) { + file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- No matching token in database' . PHP_EOL, FILE_APPEND); + } return ['status' => 'Fail', 'reason' => '2']; } } diff --git a/include/lucidAuth.template.php b/include/lucidAuth.template.php index 95bddc7..f0ce42a 100644 --- a/include/lucidAuth.template.php +++ b/include/lucidAuth.template.php @@ -2,7 +2,7 @@ error_reporting(E_ALL & ~E_NOTICE); -$pageLayout = << @@ -19,40 +19,38 @@ $pageLayout = << -
-
+
- -
-
-
-PAGE; +FULL; + +$pageLayout['bare'] = <<<'BARE' + + + + + lucidAuth + + + + + + %1$s + + +BARE; $contentLayout['login'] = << @@ -121,4 +119,5 @@ $contentLayout['dialog'] = << DIALOG; + ?> \ No newline at end of file diff --git a/public/lucidAuth.login.php b/public/lucidAuth.login.php index 43e15b1..062394b 100644 --- a/public/lucidAuth.login.php +++ b/public/lucidAuth.login.php @@ -8,8 +8,33 @@ if ($_POST['do'] == 'login') { $result = authenticateLDAP($_POST['username'], $_POST['password']); if ($result['status'] == 'Success') { + // Store authentication token; in database serverside & in cookie clientside + if (storeToken($result['token'], $settings->LDAP['Domain'] . '\\' . $_POST['username'], $_SERVER['HTTP_HOST'])['status'] !== 'Success') { + // Since this action is only ever called through an AJAX-request; return JSON object + echo '{"Result":"Fail","Reason":"Failed storing authentication token in database and/or cookie"}' . PHP_EOL; + exit; + } + + // Convert base64 encoded string back from JSON; + // forcing it into an associative array (instead of javascript's default StdClass object) + try { + $proxyHeaders = json_decode(base64_decode($_POST['ref']), JSON_OBJECT_AS_ARRAY); + } + catch (Exception $e) { + // Since this action is only ever called through an AJAX-request; return JSON object + echo '{"Result":"Fail","Reason":"Original request URI lost in transition"}' . PHP_EOL; + exit; + } + $originalUri = !empty($proxyHeaders) ? $proxyHeaders['XForwardedProto'] . '://' . $proxyHeaders['XForwardedHost'] . $proxyHeaders['XForwardedUri'] : 'lucidAuth.manage.php'; + // Since this request is only ever called through an AJAX-request; return JSON object - echo sprintf('{"Result":"Success","Location":"%1$s","CrossDomainLogin":%2$s}', $originalUri, $settings->Session['CrossDomainLogin'] ? 'True' : 'False') . PHP_EOL; + header('Content-Type: application/json'); + echo json_encode([ + "Result" => "Success", + "Location" => $originalUri, + "CrossDomainLogin" => $settings->Session['CrossDomainLogin'] + ]); +# echo sprintf('{"Result":"Success","Location":"%1$s","CrossDomainLogin":%2$s}', $originalUri, $settings->Session['CrossDomainLogin'] ? 'True' : 'False') . PHP_EOL; } else { switch ($result['reason']) { case '1': @@ -20,15 +45,9 @@ } } } else { - $stylevar['content']['top'] = '-125px'; - $stylevar['content']['margin-left'] = '-225px'; - $stylevar['content']['height'] = '220px'; - $stylevar['content']['width'] = '450px'; - include_once('../include/lucidAuth.template.php'); - $pageLayout = str_replace('', $contentLayout['login'], $pageLayout); - echo $pageLayout; + echo sprintf($pageLayout['full'], $contentLayout['login']); } ?> \ No newline at end of file diff --git a/public/lucidAuth.setXDomainCookie.php b/public/lucidAuth.setXDomainCookie.php index c951e24..ba423c0 100644 --- a/public/lucidAuth.setXDomainCookie.php +++ b/public/lucidAuth.setXDomainCookie.php @@ -2,17 +2,23 @@ error_reporting(E_ALL ^ E_NOTICE); include_once('../include/lucidAuth.functions.php'); + - // Start with checking $_REQUEST['ref'] - // What do we need? - // token again? + // Start with checking $_REQUEST['ref'] + // What do we need? + // token again? - // approach 1: - // origin domain, so we can intersect with $settings->Session['CookieDomains'] and iterate through the remaining domains, serving them in one page (which contains iframes already) - // this might be slower because it means one additional roundtrip between client and server + // approach 1: + // origin domain, so we can intersect with $settings->Session['CookieDomains'] and iterate through the remaining domains, serving them in one page (which contains iframes already) + // this might be slower because it means one additional roundtrip between client and server - // approach 2: - // let the client setup multiple iframes for all domains other than origin domains - // this requires passing an array of domains to the client in asynchronous reply; which feels insecure + // approach 2: + // let the client setup multiple iframes for all domains other than origin domains + // this requires passing an array of domains to the client in asynchronous reply; which feels insecure + include_once('../include/lucidAuth.template.php'); + + echo sprintf($pageLayout['bare', + '// iFrames go here' + ); ?> \ No newline at end of file diff --git a/public/lucidAuth.validateRequest.php b/public/lucidAuth.validateRequest.php index ee300df..0075d4d 100644 --- a/public/lucidAuth.validateRequest.php +++ b/public/lucidAuth.validateRequest.php @@ -26,7 +26,7 @@ exit; } - if (!empty($_COOKIE['JWT']) && validateToken($_COOKIE['JWT'])['status'] == "Success") { + if (!empty($_COOKIE['JWT']) && validateToken($_COOKIE['JWT'])['status'] === "Success") { // Valid authentication token found header("HTTP/1.1 202 Accepted"); exit; diff --git a/public/misc/script.index.js b/public/misc/script.index.js index d62d6d3..782dcd2 100644 --- a/public/misc/script.index.js +++ b/public/misc/script.index.js @@ -20,27 +20,22 @@ $(document).ready(function(){ ref: $('#ref').val() }) .done(function(data,status) { - try { - var ajaxData = JSON.parse(data); - } - catch (e) { - console.log(data); - } - if (ajaxData.Result === 'Success') { + if (data.Result === 'Success') { $('#btnlogin').css({ 'background': 'green url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAaklEQVQ4jeXOMQ5AQBBG4T2BC4i76EWich7ncAKbqCRuodTqnMNTkFgJs3ZU4tXz/Rlj/hUQv8EpMAClFk9sjUAiHVcCnoFMwhZYgPYG575Xe46aIOyMdJx7ji9GwrEzUgOFCu8DkRp/qxU2BKCUyZR6ygAAAABJRU5ErkJggg==) no-repeat center', 'transform': 'rotateX(0deg)' }); setTimeout(function() { $('#btnlogin').prop('disabled', false).css({ - 'background': '#B50000 linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.25) 51%) no-repeat center', + 'background': '#003399 linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.25) 51%) no-repeat center', 'color': '#FFF' }); - if (ajaxData.CrossDomainLogin) { + if (data.CrossDomainLogin) { // Create iframes for other domains console.log('CrossDomainLogin initiated'); } - window.location.replace(ajaxData.Location); +console.log("Navigating to :" + data.Location); + window.location.replace(data.Location); }, 2250); } else { $('#btnlogin').css({ @@ -49,12 +44,12 @@ console.log('CrossDomainLogin initiated'); }); setTimeout(function() { $('#btnlogin').prop('disabled', false).css({ - 'background': '#B50000 linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.25) 51%) no-repeat center', + 'background': '#003399 linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.25) 51%) no-repeat center', 'color': '#FFF' }); - // TODO: Add feedback (based on ajaxData.Reason) + // TODO: Add feedback (based on data.Reason) // Is the redirect needed? - window.location.replace('lucidAuth.login.php'/*+ '?reason=' + ajaxData.Reason*/); + window.location.replace('lucidAuth.login.php'/*+ '?reason=' + data.Reason*/); }, 2250); } }); diff --git a/public/misc/style.css b/public/misc/style.css index 5de8498..186b31d 100644 --- a/public/misc/style.css +++ b/public/misc/style.css @@ -20,8 +20,7 @@ body { visibility: visible; display: block; } -#content, -#error { +#content { background: url(/images/bg_main_bottom.gif) repeat-x bottom left; font-family: Tahoma, sans-serif; border: 3px solid #CCCCCC; @@ -30,6 +29,10 @@ body { left: 50%; visibility: visible; border-radius: 5px; + top: -125px; + margin-left: -225px; + height: 220px; + width: 450px; } #error .main { padding: 0 10px;