The Slim Framework support forum has moved to http://discourse.slimframework.com. This Tender forum is no longer maintained or monitored.

Login/Logout with redirect

sakaye87's Avatar

sakaye87

09 Aug, 2012 07:00 PM

I have a login/logout function for my web app. I'm trying to figure out how to allow the user to login or logout and redirect them back to the same page they were viewing before that. How would I go about doing that? I am new to web programming so an example would be greatly appreciated. Thanks.

Bryun

  1. Support Staff 1 Posted by Brian Nesbitt on 10 Aug, 2012 03:09 AM

    Brian Nesbitt's Avatar

    The most common case for this is when you have a secure area and the user hits a page that requires login and you want to direct them to login and back to that page. All you have to do is before the redirect on the login check save the request url in the session or flash and upon successful login see if that exists and redirect them to that url, otherwise to your default logged in user page.

    If you can login/logout from any page (public or private) it becomes a little tougher since they can be on any page and click login. This can be solved using a client side or server side solution.

    Server side... Persist the request URI in a flash or session variable all the time so whenever they login or logout you can check the page they came from. This adds additional overhead for all requests when most of the time it won't actually be used.
    Client side... when login or logout is clicked use javascript to capture the current url and submit it along with the url as part of the querystring. Upon successful login/logout direct them to the url. If the login requires reloads on errors then persist in via flash or session. This saves having to persist it on the server with each request.

    If you provide which type you are attempting to build I can probably whip up something quick as an example.

  2. 2 Posted by sakaye87 on 10 Aug, 2012 05:51 PM

    sakaye87's Avatar

    Thanks for your reply Brian. The private pages I have will only show (in navigation or sub-menu pages) to a user who is logged in. They will stil have the ability to get 2 levels deep into the site before finding a private page. This is when they realize I need to login and do so. I currently have a redirect back to the home page but would like it go back to the page they were on before the login page shows. I think saving the URL to a session before loading the login page is what I was looking for. As for the logout I think I will make a "You have logged out page". Hopefully you understand what I mean. Thank you again.

  3. Support Staff 3 Posted by Brian Nesbitt on 11 Aug, 2012 02:55 AM

    Brian Nesbitt's Avatar

    I created a sample application for you:
    https://github.com/briannesbitt/Slim-ContextSensitiveLoginLogout

    Its could be refactored to separate out the routes, authentication credentials, css, js etc. etc. but I think it more than gives you what you are looking for.

  4. 4 Posted by sakaye87 on 15 Aug, 2012 06:12 PM

    sakaye87's Avatar

    Thanks again for such a quick response Brian. Upon reading through your index I clearly don't understand how to use Slim very well. This is a link to the app I'm working on:
    https://github.com/sakaye/AmbPrac2

    Could you take a look at what I have? Maybe that will give you a better idea of what I'm trying to do.

  5. 5 Posted by electricbonfire on 16 Sep, 2012 10:43 PM

    electricbonfire's Avatar

    Thanks Brian! I have pulled apart some of your code to make a login for my application.

    I have added:

     $path =  explode("/", $app->request()->getPathInfo());
        if($path[1] == "admin"){
            authenticate($app);
        }
    

    to the slim.before.dispatch and altered the
    $authenticate = function... to:

    function authenticate($app){
        if (!isset($_SESSION['user'])) {
            $_SESSION['urlRedirect'] = $app->request()->getPathInfo();
            $app->flash('error', 'Login required');
            $app->redirect('/login');
        }
    }
    

    This triggers the auth on any route starting with /admin

    One thing I don't fully understand is this syntax:

    $authenticate = function ($app) {
        return function () use ($app) {....
    

    Is there any advantage to this? I was uncertain how to call the $auth function outside of using it as middleware. Thats why I changed it to function auth()...

    Thanks Again!

  6. Support Staff 6 Posted by Brian Nesbitt on 17 Sep, 2012 01:55 PM

    Brian Nesbitt's Avatar

    You basically are moving the authentication from the route middleware to the slim.before.dispatch hook. Which is ok but just know it will run for all routes now not just the ones that need protection so you need to confirm the URI as you added. There was no need to do that before since the $authenticate route middleware is only attached to routes that need to be protected. You can see in my example that /private/about and /private/goodstuff are the only ones that have the route middleware protection so no need to check if the routes start with /private (or in your case /admin). But since you moved to only using hook, which runs on all routes, you need to confirm the request URI.

    In that case I would just put it all there since you can get rid of the $authenticate stuff as you are no longer need to use the route middleware and just use the hook. I also changed your explode to a strpos which I think would be faster but either way is more explicit.

    $app->hook('slim.before.dispatch', function() use ($app) { 
        //$path =  explode("/", $app->request()->getPathInfo());
        //if($path[1] == "admin") {
        if (strpos($app->request()->getPathInfo(), '/admin') === 0)
            if (!isset($_SESSION['user'])) {
                $_SESSION['urlRedirect'] = $app->request()->getPathInfo();
                $app->flash('error', 'Login required');
                $app->redirect('/login');
            } else {
                $app->view()->setData('user', $_SESSION['user']);
            }
        }
    });
    

    The following is setting a variable $authenticate to a function that returns a function that will authenticate. The route middleware parameter needs to be a callable so hence why its a function returning a function.

    $authenticate = function ($app) {
        return function () use ($app) {
            if (!isset($_SESSION['user'])) {
                $_SESSION['urlRedirect'] = $app->request()->getPathInfo();
                $app->flash('error', 'Login required');
                $app->redirect('/login');
            }
        };
    };
    

    If you really wanted to call this function yourself directly you can do this:

    $authCallable = $authenticate($app);
    $authCallallbe();                                         // <== calling the returned method
    
    // you can also call it with
    call_user_func($authCallable);
    

    ... now you don't need any of that though!

  7. 7 Posted by sakaye87 on 02 Oct, 2012 09:27 PM

    sakaye87's Avatar

    Thanks for the help. I will try and apply this to my app.

  8. Support Staff 8 Posted by Brian Nesbitt on 03 Oct, 2012 03:03 AM

    Brian Nesbitt's Avatar

    Sounds good.

  9. Brian Nesbitt closed this discussion on 03 Oct, 2012 03:03 AM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac