Redirect Confusion - [SOLVED]

Hey y’all…

As the subject states, I’ve got a bit of confusion in regards to implementing reroutes. After the ‘lights turned on’ following a question or two here, I had a pretty good idea of what routing was doing - or so I thought. I have all the UI routes configured and serving, and the POST route AJAX call for employee logins - work great; My issue is now that I’d like to ensure any request for a route (with the exception of the login ui and ajax service routes) that’s not authenticated get’s rerouted to the login interface.

if(empty($_SESSION) || $_SESSION['authenticated'] !== 'true') {
    error_log('needs redirection');
    // $app->redirect('?', '/login', 301);
}

$app->get(
    '/login', 
    Infraweb\LoginUI::class.':login'
)->setName('ui-login');

$user = $_SESSION['eid'];

$app->get(
    '/', 
    Infraweb\IndexUI::class.':home'
)->setName('ui-home');

$app->post(
    '/employees/login',
    Infraweb\Toolkit\Services\Authentication::class.':login'
)->setName('svc-login');

This small snippet subset outputs the ‘needs redirection’ message to the error log - bueno (I think). The UI class definitions extend the \Slim\Views\Smarty smarty class (“mathmarques/smarty-view”) and I gave thought to performing the redirect check in the class callable method(s) used for resolving the request. Couldn’t quite get that working as I’d like as of yet, so I moved to the above and kicked that around for a bit. I’ve looked at various posts here regarding this subject, and I’ve been able to muddle thru stuff to this point. I’m not doing things quite like most examples (at least what I’ve seen to date) so I thought it would be best to quickly throw this out into the collective to get some direction or advice. I get the idea, the implementation details just escape me at the moment as I familiarize myself with the libs in play…

Thanx in advance for the time, and apologies if I’ve wasted anyone’s bandwidth here…

They typical way to do this would be to apply a middleware to all of the routes that need authorization. That middleware would then check to see if the user is logged in, and if not redirect them. You can see a quick example of what that middleware might look like here:

Wow, thx @tflight… that was my first inclination when I encountered the login workflow - I started down the closure path and got a bit jammed up. That’s when I got involved with the above. This pretty much is a logical boilerplate I was driving towards, give or take a few small changes due to implementation. This definitely is something I’m going to kick the tires with. Much thanx in advance for the helpful direction!

OK, I’m addled determining just what the *#@! is going on with this.

Smarty template form snippet, this submits the employee login tokens from a Bootstrap 3 front end
(works as advertised).

<form class="form-inline" id="employee_login_form" method="POST" **action="{$site_virtual_path|cat:'employees/login'}">
    <div class="form-group">
        <label class="sr-only" for="employee_username">Username</label>
        <input type='email' class="form-control" id="employee_username" placeholder="Username">
     </div>
     <div class="form-group">
        <label class="sr-only" for="employee_password">Password</label>
        <input type="password" class="form-control" id="employee_password" placeholder="Password">
    </div>

    <div class="visible-sm clearfix mt-sm mb-sm"></div>

    <div class="checkbox-custom checkbox-default checkbox-inline mt-sm ml-md mr-md">
        <input type="checkbox" checked="" id="remember_me">
        <label for="remember_me">Remember my account</label>
    </div>
    <div class="clearfix visible-xs mb-sm"></div>

    <button type="submit" class="btn btn-primary">Login</button>
    <button type="reset" class="btn btn-default">Cancel</button>
</form>

The route definition is as follows (also works as advertised):

$app->post(
    '/employees/login', 
    Infraweb\Toolkit\Services\Authentication::class.':login')
->setName('svc-login');

Snippet from the controller function handling the route request and subsequent response. This works, to a point:

/**
 * validate an employees login request
 * 
 * @access public
 * @param ContainerInterface $container
 * @return redirect to url
 */
public function login($request, $response, $args) 
{
    if(session_status() !== PHP_SESSION_ACTIVE) {
        session_start();
    }
    $tokens = $request->getParsedBody();
    echo('<pre>'.var_dump($tokens).'<pre>'); exit();

I exectute this in a browser on the server, and the $tokens don’t appear anywhere; dumping the $request, $response or $args variables and no dice. The confusing part here is that when I execute this from Postman or the <RESTED> Chrome extension the login $tokens are magically THERE. WTF?!? Anyone with any kind of insight relative to this?

FWIW @tflight, the redirect middleware logic above works like a f’n CHAMP! I just gotta get passed the logic of this piece above to continue forward…

Thanx in advance for any/all input and constructive criticism - greatly appreciated and encouraged!

This the output from the Browser site access

/srv/www/workspace/infraweb/src/Toolkit/Services/Authentication.php:49:
    array (size=0)
    empty

RESTED chrome extension screenie:

:neutral_face:

You say the $token values are not there, can you verify that when using the browser you are actually hitting the login method? Do you see the empty <pre></pre> in the source?

That line is from the login method of the controller per the 3rd snippet of my last post above.

/srv/www/workspace/infraweb/src/Toolkit/Services/Authentication.php:49:
array (size=0)
empty

This is pretty damn weird - I fail to see how this code can execute properly from Postman/RESTED and fail with the actual execution on the site itself; everything is using the same code… if you notice, all output is being dumped with this line:

echo('<pre>'.var_dump($tokens).'<pre>'); exit();

Thanx for the input tho… \m/

My post may have not been clear. What I meant is can you verify the response was indeed hitting the login method and not failing elsewhere.

Regardless, is looks like your form elements do not have a name attribute on them.

<input type="password" class="form-control" id="employee_password" placeholder="Password">
<input type="password" class="form-control" id="employee_password" name="employee_password" placeholder="Password">

Bingo!

Thanx @tflight… oversight on my behalf - I’ve always just relied on the form’s ‘id’ param, and I’ve noticed now in the api that ‘name’ attribute is key…

Thanx again, man!

\m/

Asking another question regarding redirects that I’m encountering - I’ve looked at some examples of how individual developers have solved this particular issue. Some of this is relatively new from the obvious perspective of absorbing api’s and the implementation details. It’s actually quite enjoyable from a learning perspective, but I digress…

This mornings ‘rub’ is I’m getting the 302 redirect, but obviously the client browser ain’t having any of it. I’m just a bit confused on the sequence of events, and how to interpret the headers:

{ Redirect -> [302] - http://infraweb.devserver.com/employees/login RESTED browser plugin}
Server: nginx
Date: Fri, 08 Mar 2019 14:39:26 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.2.15
Set-Cookie: PHPSESSID=814t49e2tme0pfgg202khglo7t; path=/
Location: /
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer-when-downgrade
Content-Security-Policy: default-src * data: 'unsafe-eval' 'unsafe-inline'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

{ Redirect -> [302] - http://infraweb.devserver.com/ RESTED browser plugin}
Server: nginx
Date: Fri, 08 Mar 2019 14:39:27 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.2.15
Location: /login
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer-when-downgrade
Content-Security-Policy: default-src * data: 'unsafe-eval' 'unsafe-inline'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

{ Response -> [200] - http://infraweb.devserver.com/login RESTED browser plugin}
Server: nginx
Date: Fri, 08 Mar 2019 14:44:22 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/7.2.15
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer-when-downgrade
Content-Security-Policy: default-src * data: 'unsafe-eval' 'unsafe-inline'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Encoding: gzip

It apparently looks as if everything is working as it should, per se, I’m just a bit confused as to how to implement the correct logic. I’ve started looking at Slim\Flash as there was some nice examples of similar circumstances, but I don’t know if that’s correct approach or not. I think some of the stuff involves a secure site of some sorts sitting behind a public web interface/site requiring access. What I’m doing really doesn’t have a default public site in terms of service. The logic is visit the site, redirect to the /login page. From there sign in for the secure content or get returned to the login interface. This is probably a good bit simpler than I seem to think it is, but I just don’t know - that’s why I’m posting back the above so I can get a logical understanding of the sequence. Fishing for a bit of direction…

Thanx in advance to anyone piling on, greatly appreciated!

Marked as ‘solved’.

This ultimately is has manifested itself as a $_SESSION problem. The redirection is now a non-issue, thanx for all the replies - grateful!

:metal: :nerd_face: