From 8fd32b5f1e8de06e6646c4082c243a16d08a05bf Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Fri, 5 Aug 2016 15:03:28 +0000
Subject: [PATCH] Bug 17050: Do not kick the session out when accessing the
 REST API

Mojolicious does not set $ENV{REMOTE_ADDR} (neither $ENV{HTTP_*}) as
it may share ENV between different requests.
Fortunately for us, Plack does not!

This is a dirty patch to fix this issue but it seems that there is not
lot of solutions. It adds a remote_addr parameter to
C4::Auth::check_cookie_authin order to send it from
Koha::Rest::V1::startup reading the headers sent by Mojolicious.

Test plan:
Hit /cgi-bin/koha/mainpage.pl
Hit /api/v1/patrons/42
Hit /cgi-bin/koha/mainpage.pl

With this patch applied, everything will be fine and you won't be
logged out.

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
---
 C4/Auth.pm      | 7 ++++++-
 Koha/REST/V1.pm | 4 +++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/C4/Auth.pm b/C4/Auth.pm
index 582eefc..7bef5f6 100644
--- a/C4/Auth.pm
+++ b/C4/Auth.pm
@@ -814,6 +814,7 @@ sub checkauth {
             C4::Context::set_shelves_userenv( 'tot', $session->param('totshelves') );
             $debug and printf STDERR "AUTH_SESSION: (%s)\t%s %s - %s\n", map { $session->param($_) } qw(cardnumber firstname surname branch);
             $ip          = $session->param('ip');
+
             $lasttime    = $session->param('lasttime');
             $userid      = $s_userid;
             $sessiontype = $session->param('sessiontype') || '';
@@ -1614,7 +1615,9 @@ Possible return values in C<$status> are:
 sub check_cookie_auth {
     my $cookie        = shift;
     my $flagsrequired = shift;
+    my $params        = shift;
 
+    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
     my $dbh     = C4::Context->dbh;
     my $timeout = _timeout_syspref();
 
@@ -1650,6 +1653,7 @@ sub check_cookie_auth {
     my $sessionID = $cookie;
     my $session   = get_session($sessionID);
     C4::Context->_new_userenv($sessionID);
+
     if ($session) {
         C4::Context->set_userenv(
             $session->param('number'),       $session->param('id'),
@@ -1660,6 +1664,7 @@ sub check_cookie_auth {
         );
 
         my $ip       = $session->param('ip');
+
         my $lasttime = $session->param('lasttime');
         my $userid   = $session->param('id');
         if ( $lasttime < time() - $timeout ) {
@@ -1671,7 +1676,7 @@ sub check_cookie_auth {
             $userid    = undef;
             $sessionID = undef;
             return ("expired", undef);
-        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $ENV{'REMOTE_ADDR'} ) {
+        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $remote_addr ) {
 
             # IP address changed
             $session->delete();
diff --git a/Koha/REST/V1.pm b/Koha/REST/V1.pm
index b692a38..b16e1e3 100644
--- a/Koha/REST/V1.pm
+++ b/Koha/REST/V1.pm
@@ -29,7 +29,9 @@ sub startup {
         cb => sub {
             my $c = shift;
 
-            my ($status, $sessionID) = check_cookie_auth($c->cookie('CGISESSID'));
+            # ENV{REMOTE_ADDR} is not set here, we need to read the headers
+            my $remote_addr = $c->req->headers->header('x-forwarded-for');
+            my ($status, $sessionID) = check_cookie_auth($c->cookie('CGISESSID'), undef, { remote_addr => $remote_addr });
             if ($status eq "ok") {
                 my $session = get_session($sessionID);
                 my $user = Koha::Patrons->find($session->param('number'));
-- 
2.9.2