Mojolicious session does not expire
Asked Answered
V

2

6

I'm building a web application using mojolicious. The logout functionality works only while running the app on local machines. When I try to logout on the app running on the server, the session does not expire and I remain logged in.

This started to happen when we changed logout to be done via POST request instead of get.

The way we call logout is as an AJAX call from the frontend:

function do_logout() {
   $.post( "<%= url_for('on_logout') %>", function() {});
}

Logout route:

$if_login->post('/logout')->name('on_logout')->to('user#on_logout');

Logout controller:

sub on_logout {
  my $self = shift;
  $self->session(expires => 1);
  return $self->redirect_to('home');
}

Line which sets the session to expire is called, but after the redirect, session still contains the username which was logged in.

Vern answered 9/8, 2017 at 12:27 Comment(0)
M
1

We finally found the error, the request was made using an

<a href="" onclick="do_logout()"></a>

which was basically doing 2 actions at once and creating a race condition. Here is the relevant code snippet

# Relevant routes
my $if_login = $r->under('/')->to('user#is_logged_in');
$if_login->post('/logout')->name('on_logout')->to('user#on_logout');

# Controller functions
sub on_logout {
  my $self = shift;
  $self->session(expires => 1);

  return $self->render(json => '{success: "true"}');
}

sub is_logged_in {
  my $self = shift;

  say $self->session('username');  # Sometimes after on_logout this is still
                                   # defined and equal to the username.
  return 1 if($self->session('username'));

  $self->render(
    template => 'permission/not_logged_in',
    status => 403
  );
  return;
}

# Front end
<a href="" onclick='do_logout();'>
 <%= l('Log out') %>
</a>

<script>
function do_logout() {
  $.post( "<%= url_for('on_logout') %>", function() {
}).fail(function() {
  alert( "error logging out" );
}).done(function( data ) {
  alert( "Data: " + data );
}).always(function() {
  alert( "finished" );
});
}
</script>

Thanks for helping!

Millstone answered 29/8, 2017 at 18:30 Comment(0)
B
1

Do you know the Mojolicious::Plugin::Authentication plugin? It's a nice module, I'm using that since I discovered Mojolicious. The documentation states, that you need to set the 'expires' attribute to the past to delete the session, but this module takes another method.

$app->helper(logout => sub {
    # omitted
    delete $c->session->{$session_key};
});

You may want to try not just setting the 'expires' attribute but also delete-ing the session key.

You said the problem appeared after you changed localhost to a domain name. You can try to set the session cookie's domain too.

Backman answered 10/8, 2017 at 7:21 Comment(1)
Did this help you resolving the problem?Pasty
M
1

We finally found the error, the request was made using an

<a href="" onclick="do_logout()"></a>

which was basically doing 2 actions at once and creating a race condition. Here is the relevant code snippet

# Relevant routes
my $if_login = $r->under('/')->to('user#is_logged_in');
$if_login->post('/logout')->name('on_logout')->to('user#on_logout');

# Controller functions
sub on_logout {
  my $self = shift;
  $self->session(expires => 1);

  return $self->render(json => '{success: "true"}');
}

sub is_logged_in {
  my $self = shift;

  say $self->session('username');  # Sometimes after on_logout this is still
                                   # defined and equal to the username.
  return 1 if($self->session('username'));

  $self->render(
    template => 'permission/not_logged_in',
    status => 403
  );
  return;
}

# Front end
<a href="" onclick='do_logout();'>
 <%= l('Log out') %>
</a>

<script>
function do_logout() {
  $.post( "<%= url_for('on_logout') %>", function() {
}).fail(function() {
  alert( "error logging out" );
}).done(function( data ) {
  alert( "Data: " + data );
}).always(function() {
  alert( "finished" );
});
}
</script>

Thanks for helping!

Millstone answered 29/8, 2017 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.