Guide Home
POD Home

Session Management

A standard way of tracking web site users is via cookies; this may just be to allow them to log in with a specific account. At the lowest level, you can manipulate and handle cookies yourself via HTTP headers, or you can use slightly higher level methods such as Sloop::Client::Request::findCookieValue() and the cookie parameter to Sloop::Client::reply().

If keeping someone logged in is the goal, Sloop::Client::TokenAuth may be useful. This is a simple module that "provides a random base 62 token for each client to be used as the cookie value", keeps a timestamped record for each token, and can then validate subsequent connections. To add a new login:

my $auth = Sloop::Client::TokenAuth->new (
    cookieName => 'e.g.Token',
    duration => 60
);

[...]

# A handler...
sub {
    my $client = shift;
    my $userID = $client->{request}->query('user');
    # Fail if the request was not structured properly.
    if (!$userID) {
        $client->generic(403);
        return;
    }

    my $token = $auth->add;
    my $cookie = $auth->cookie($token, $userID);
    my $page = ...
    $client->reply(\$page, cookies => [ $cookie ]);
}

The purpose here of the userID, presumably part of a query string, is to allow for multiple logins using different accounts on the same browser. It is not necessary, but without that, multiple such logins will cause the cookie to be overwritten. See the API POD for the second argument to Sloop::Client::TokenAuth::cookie() regarding this.

In places where you want to subsequently validate a client:

# Another handler...
sub {
    my $client = shift;
    my $userID = $client->{request}->query('user');
    if (!$userID) {
        $client->generic(403);
        return;
    }

    my $token = $auth->validate($client, $userID);
    if (!$token) { 
        $client->generic(403);
        return;
    }

    # Update cookie timestamp.
    my $cookie = $auth->update($token, $userID);
    my $page = ...
    $client->reply(\$page, cookies => [ $cookie ]);
}

Note the point about updating the cookie (again with a unique per user suffix). This is because cookies have a static timestamp, but you probably don't want a login session to end arbitrarily an hour after the user logs in; you want it to end after a fixed period of inactivity. While the duration could be updated on the server automatically with the validate() call, you still need to update the time remaining on the client side by returning a new cookie (which will replace the old one). You can also associate data with each client via the optional second argument to $auth->add(), retrievable with $auth->fetch($token).

Keep in mind that unless the connections are HTTPS, using such tokens is no form of security since the cookie header will be transmitted in plain text.