Access plugin redirect woes

113 views
Skip to first unread message

v.

unread,
Dec 7, 2018, 3:50:19 PM12/7/18
to f3-fra...@googlegroups.com
hi,
I am trying to redirect people that are not logged in to the login page using the very excellent access plugin.
Unfortunately it seems to collide with my csrf protection for reasons I don't understand.
I have a controller that is inherited bu all others. The before route handles the access and csrf.

For some reason my csrf token is different after a redirect.
My code:
    function beforeroute() {
        $csrf_page
= $this->f3->get('PARAMS.0'); //URL route with preceding slash, set a csrf for every page in case other pages are opened in tabs
       
       
if ($this->f3->VERB==='POST')
       
{
           
if(  strcmp($this->f3->get('POST.session_csrf'), $this->f3->get('SESSION.'.$csrf_page.'.csrf'))===0 ) // Things check out
           
{  
                $this
->f3->set('CSRF', $this->f3->session->csrf()); // Reset csrf token for next post request
                $this
->f3->copy('CSRF','SESSION.'.$csrf_page.'.csrf');
           
}
           
else{  // DANGER: CSRF attack!
                $this
->f3->error(403);
           
}
       
}
        else //get request: set token
        {
            $this->f3->CSRF = $this->f3->session->csrf();
            $this->f3->copy('CSRF','SESSION.'.$csrf_page.'.csrf');
        }
//the next if statement causes the problem:
       
if (!$this->f3->exists('SESSION.type') && strcmp($csrf_page,"/login")!=0) { //if no user type (not logged in), redirect to login, accept if already on login page (otherwise infinite loop)
            $this
->f3->reroute('/login');
       
}

        $access
=Access::instance();
        $access
->authorize($this->f3->get('SESSION.type') ); //this handles the access defined in an ini-file
       
   
}

If the problematic if statement with the redirect to the login page is deleted, everything works as expected.
Otherwise I get a 403 because of a non-corresponding csrf token, even when I went to the login page directly and no redirect was needed

Also: while trying to figure out what was wrong I came across something very weird: when I add the following in my before route:
        if(null===$this->f3->get('SESSION.i')){
            $this->f3->set('SESSION.i',0);
        }
        $session_i=1+$this->f3->get('SESSION.i');
        $this->f3->set('SESSION.i',$session_i);

        echo 'session.i: '.$session_i.'<br>';
Reloading the page will add not 1 but 3 or 4 to session.i !
If the redirect is added it will add 1 additional unit compared to without the redirect to login (even if the login page is simply reloaded)

I am not sure if this is related or if this is something the framework is expected to do?

ikkez

unread,
Dec 9, 2018, 6:21:43 AM12/9/18
to Fat-Free Framework
where do you set SESSION.type?
a redirect typically ends up in 2 request.. one for the request where you decide that a redirect is needed and the second one for the redirected request.. so you have probably called the controller twice in that case. using the SESSION for a counter is also not the best idea. when that beforeroute is called for every page, it could also mean that it's called when things happen that you might cannot control, i.e. like browser preload behavious that sends extra requests. It can also depend on your controller and routing setup. i.e. when your browser tries to load a non existing favicon or you have broken links on your page, each 404 could maybe call your controller once more... or in case you handle OPTIONS requests yourself, it can also add more calls to your controller, making it pretty much unpredictable what your session counter might end up.

v.

unread,
Dec 10, 2018, 9:39:07 AM12/10/18
to f3-fra...@googlegroups.com
Hi,

SESSION.type gets set in a usercontroller that extends the controller.
Both my post and get login route point to usercontroller->login.
On post and with correct credentials it will set the session.type.

edit:
If I understand correctly, the session.type should not matter, since I am on the login page when logging in so the if statement gets ignored


And to be clear: the session count was only for debugging reasons. I was trying to understand what was going on, and thought this would help (which it did not, but it raised new questions...).

v.

unread,
Dec 12, 2018, 9:19:42 AM12/12/18
to Fat-Free Framework
I am seriously at a loss here. No matter what I try, either the redirect does not work or the login throws a 403 because of non-corresponging csrf tokens.
I have tried to make every 401 error redirect to the login page, right at the start of my index file, but it gives the exact same problem.
I have tried to check if authorize returns true or false and redirect to the login page on false, but the same thing happens.

I just don't understand why the CSRF token gets reset between being displayed and being posted if the redirect is set.

ikkez

unread,
Dec 12, 2018, 12:09:31 PM12/12/18
to Fat-Free Framework
have you debugged it with xdebug or something? Or checked the network activity? I bet when you'll inspect every request that's going in and you probably find the missing puzzle piece.

ved

unread,
Dec 12, 2018, 4:48:39 PM12/12/18
to Fat-Free Framework
Hi, 
Can you show us more of the initialization code?
For instance, where does "$this->f3->session" come from ?

arava

unread,
Dec 12, 2018, 9:12:41 PM12/12/18
to Fat-Free Framework
let`s change != 0 TO !== 0 :
  if (!$this->f3->exists('SESSION.type') && strcmp($csrf_page,"/login") !== 0) {
...

if it still doesn`t work, do the next please and show us the result :
     var_dump($csrf_page);exit
  if (!$this->f3->exists('SESSION.type') && strcmp($csrf_page,"/login")!=0) {

v.

unread,
Dec 18, 2018, 3:21:52 AM12/18/18
to Fat-Free Framework
I don't understand anything anymore: this problem seems to have gone away on its own...
I have repeatedly empties the tmp folder, so this can not be it.
Thanks for trying to help everybody, if it comes back I will try to find out why and how and post it here
Reply all
Reply to author
Forward
0 new messages