8

Now my app.psgi contains (simplified):

builder {
      enable 'Session', store => 'File'; #default uses Plack::Session::State::Cookie
      $app;
};

Later, in the $app I'm using:

my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";

It works ok, e.g.:

  • when the user logged in, I store his name in the server-side stored session-file, and the Plack::Middleware::Session sets an simple session-state-cookie,
  • and when the user closing the browser, the cookie is automatically cleared (because the Plack::Session::State::Cookie by default didn't set any expiration for the cookie).

Now, I want implement the "Remember me" feature in my login-panel. In this case, the sesion-state-cookie should-not be removed automatically from the browser. This can be done, by using the expires method from the Plack::Session::State::Cookie.

The question:

How I can change the cookie expiration (managed by the Session middleware) from my $app. With other words, how to call the expire method somewhat here:

my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";
my $cookie_state = WHAT_TO_DO_HERE_TO_GET; #the current Plack::Session::State::Cookie object
$cookie_state->expire(86400*14); #expire in two weeks

If someone needs, here is an working example.

use strict;
use warnings;
use Plack::Request;
use Plack::Response;
use Plack::Builder;
use Data::Dumper;

my $app = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;
    my $res = Plack::Response->new(200);
    $res->content_type('text/html');
    my $link = $session->{user}
            ? q{ <a href="/logout">logout</a>}
            : q{ <a href="/login">login</a>}
            ;
    $res->body(["Session user:", $session->{user}, "<br>$link"]);
    return $res->finalize;
};

my $login = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;

    $session->{user} = "some";
    #how to set here the session-state-cookie expiration?

    my $res = Plack::Response->new();
    $res->redirect("/", 302);
    return $res->finalize;
};

my $logout = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $session = $req->session;
    delete $session->{user};
    my $res = Plack::Response->new();
    $res->redirect("/", 302);
    return $res->finalize;
};

builder {
    enable 'Session', store => 'File';
    mount "/login" => $login; 
    mount "/logout" => $logout; 
    mount "/favicon.ico" => sub { return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ] };
    mount "/" => $app; 
};
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
kobame
  • 5,766
  • 3
  • 31
  • 62

1 Answers1

6

You can't change the expiration date directly, but you can force the session middleware to create a new session with a new expiration date like this:

$env->{'psgix.session.options'}{change_id} = 1;
$env->{'psgix.session.options'}{expires}   = $my_expires;

If a user logs in, you should change the ID anyway to prevent session fixation attacks. See Cookie::Baker for supported expiration date formats.

EDIT: If you want to set the default expiration timeout globally, you can build the state object manually and pass the expires parameter to the constructor:

builder {
    enable 'Session',
        state => Plack::Session::State->new(
            expires => $timeout_in_seconds,
        );
    $app;
};
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
  • 1
    Although I expected some method calls, it **works**. My question is, where is this documented? Because in the Plack::Middleware::Session [are documented some subkeys](https://metacpan.org/pod/Plack::Middleware::Session#PLACK-REQUEST-OPTIONS) for the `psgix.session.options` but the `expires` is missing. (Here only the `expire` /without the plural (s)/what is for invalidating the session). So really wondering from where do you know this. By digging in the module sources? Anyway **thank you** very much. – kobame Mar 22 '15 at 17:47
  • 2
    @kobame Yeah, I know this from looking at the source code. I opened a [GitHub issue](https://github.com/plack/Plack-Middleware-Session/issues/33) regarding the missing documentation. – nwellnhof Mar 22 '15 at 18:32
  • I wanted to say thanks for the reply; going to give this a try in my app. The github issue hasn't had any activity and the framework I've been using (Kelp) doesn't seem to have any options around this. – saberworks Nov 03 '16 at 03:50