diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index bf22c361b5958763eec9a40c6e3e9b2a35e415a9..33983975f21ee34e3e30546ffdb9a614fe79b395 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -98,6 +98,13 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermWithStats
  */
 public interface ICommonClientService extends IClientService
 {
+    /**
+     * Keeps the logged in user session alive.
+     * 
+     * @return 'true' if session was successfully prolonged, 'false' otherwise
+     */
+    public Boolean keepSessionAlive() throws UserFailureException;
+
     /**
      * Returns a list of all groups.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index 6395491a79e5fe45399a541c072cdfc2ca8fc1bb..b075a2abc2b3a7d46a8d09f6a6d5d616a716c052 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -95,6 +95,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermWithStats
  */
 public interface ICommonClientServiceAsync extends IClientServiceAsync
 {
+    /** @see ICommonClientService#keepSessionAlive() */
+    public void keepSessionAlive(final AsyncCallback<Boolean> asyncCallback);
+
     /** @see ICommonClientService#listGroups(DefaultResultSetConfig) */
     public void listGroups(DefaultResultSetConfig<String, Group> criteria,
             final AsyncCallback<ResultSet<Group>> asyncCallback);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
index cd74ed1c3aab902202e32c4be4fa69832aacd78a..1d204b88ff10cb39b43d8d3f5b4ed6d682978e7a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/LoginWidget.java
@@ -28,6 +28,8 @@ import com.extjs.gxt.ui.client.widget.button.Button;
 import com.extjs.gxt.ui.client.widget.form.Field;
 import com.extjs.gxt.ui.client.widget.form.FormPanel;
 import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.rpc.AsyncCallback;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
@@ -193,6 +195,8 @@ public class LoginWidget extends VerticalPanel
 
     public final class LoginCallback extends AbstractAsyncCallback<SessionContext>
     {
+        private static final int TIMER_PERIOD = 30 * 60 * 1000; // 30min
+
         private LoginCallback(final IViewContext<ICommonClientServiceAsync> viewContext)
         {
             super(viewContext);
@@ -237,7 +241,40 @@ public class LoginWidget extends VerticalPanel
                                 }
                             });
                 viewContext.getPageController().reload(false);
+                keepSessionAlive();
             }
         }
+
+        /** tries to keep session alive until user logs out or closes browser */
+        private void keepSessionAlive()
+        {
+            Timer t = new Timer()
+                {
+                    @Override
+                    public void run()
+                    {
+                        // callback will cancel keeping session alive if something went wrong
+                        // or user logged out
+                        AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>()
+                            {
+
+                                public void onSuccess(Boolean result)
+                                {
+                                    if (result == false)
+                                    {
+                                        cancel();
+                                    }
+                                }
+
+                                public void onFailure(Throwable caught)
+                                {
+                                    cancel();
+                                }
+                            };
+                        viewContext.getCommonService().keepSessionAlive(callback);
+                    }
+                };
+            t.scheduleRepeating(TIMER_PERIOD);
+        }
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index b74c38e92d8de70139d8d29e0a8cdd2689c3730f..5fb62638db08b1338c769519c7bade9f75a1d031 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -2284,4 +2284,24 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    // --
+
+    public Boolean keepSessionAlive()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            commonServer.keepSessionAlive(getSessionToken());
+            return true;
+        } catch (final InvalidSessionException e)
+        {
+            // most probable cause - user logged out
+            return false;
+        } catch (final UserFailureException e)
+        {
+            // should not happen
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 01860125fd9219a378b8d403534e7eff7bac4308..023528a78f16ba1d360d3bc22f51b77bc681da70 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -1829,4 +1829,11 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         createGridCustomColumnBO(sessionToken).update(updates);
     }
 
+    // --
+
+    public void keepSessionAlive(String sessionToken) throws UserFailureException
+    {
+        checkSession(sessionToken);
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index 5cdf223a56e4152e7285c9a791dec661aaf986fa..755b253bede0957c47a44a06806e7f5532a2c1e5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -800,4 +800,9 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 updates.getName());
     }
 
+    public void keepSessionAlive(String sessionToken)
+    {
+        logTracking(sessionToken, "keepSessionAlive", "TOKEN(%s)", sessionToken);
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 08b8eba3e68fb7c71c18952ec717ff11a3b718c2..64b51f327378b80a8d951dfe2e9fcc6c6f681b33 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -110,6 +110,9 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
  */
 public interface ICommonServer extends IServer
 {
+    /** Keeps the session with specified token alive. */
+    public void keepSessionAlive(String sessionToken);
+
     /**
      * Returns all groups which belong to the specified database instance. *
      *