diff --git a/gms/src/main/java/it/inaf/ia2/gms/authn/JWTFilter.java b/gms/src/main/java/it/inaf/ia2/gms/authn/JWTFilter.java
index ed7be0d35da5a9abed52c142cd33b71782d43fac..72d55a11a81e512d12c34f3fd1694bd90d66d753 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/authn/JWTFilter.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/authn/JWTFilter.java
@@ -56,13 +56,14 @@ public class JWTFilter implements Filter {
         Map<String, Object> claims = userManager.parseIdTokenClaims(token);
 
         if (claims.get("sub") == null) {
-            loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Attempt to access API with invalid token", request);
+            loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Attempt to access API with invalid token " + request.getRequestURI(), request);
             response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid access token: missing sub claim");
             return;
         }
 
         ServletRequestWithJWTPrincipal wrappedRequest = new ServletRequestWithJWTPrincipal(request, token, claims);
-        loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "API access from " + wrappedRequest.getUserPrincipal().getName(), request);
+
+        loggingDAO.logAction(ActionType.API_CALL, request.getRequestURI() + " called by " + wrappedRequest.getUserPrincipal().getName(), request);
 
         fc.doFilter(wrappedRequest, res);
     }
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/HomePageController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/HomePageController.java
index d9f18f65b0b612d9c8dc5bc2b0e7a5c051bf7224..6fbf33f971a920b80e76d5f7fd6b217203f98d52 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/HomePageController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/HomePageController.java
@@ -1,18 +1,12 @@
 package it.inaf.ia2.gms.controller;
 
 import it.inaf.ia2.gms.authn.SessionData;
-import it.inaf.ia2.gms.exception.UnauthorizedException;
 import it.inaf.ia2.gms.manager.InvitedRegistrationManager;
-import it.inaf.ia2.gms.model.GroupBreadcrumb;
-import it.inaf.ia2.gms.model.GroupNode;
-import it.inaf.ia2.gms.model.Permission;
 import it.inaf.ia2.gms.model.request.GroupsRequest;
 import it.inaf.ia2.gms.model.response.GroupsTabResponse;
 import it.inaf.ia2.gms.model.response.HomePageResponse;
-import it.inaf.ia2.gms.model.response.PaginatedData;
 import it.inaf.ia2.gms.persistence.model.InvitedRegistration;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import javax.servlet.ServletException;
@@ -48,37 +42,14 @@ public class HomePageController {
 
         response.setUser(session.getUserName());
 
-        try {
-            GroupsTabResponse groupsTabResponse = groupsTabResponseBuilder.getGroupsTab(request);
-            response.setBreadcrumbs(groupsTabResponse.getBreadcrumbs());
-            response.setGroupsPanel(groupsTabResponse.getGroupsPanel());
-            response.setPermission(groupsTabResponse.getPermission());
-        } catch (UnauthorizedException ex) {
-            if ("ROOT".equals(request.getGroupId())) {
-                response.setBreadcrumbs(getRootBreadcrumbs());
-                response.setGroupsPanel(getEmptyGroupsPanel(request));
-                response.setPermission(Permission.TRAVERSE);
-            } else {
-                throw ex;
-            }
-        }
+        GroupsTabResponse groupsTabResponse = groupsTabResponseBuilder.getGroupsTab(request);
+        response.setBreadcrumbs(groupsTabResponse.getBreadcrumbs());
+        response.setGroupsPanel(groupsTabResponse.getGroupsPanel());
+        response.setPermission(groupsTabResponse.getPermission());
 
         return ResponseEntity.ok(response);
     }
 
-    private List<GroupBreadcrumb> getRootBreadcrumbs() {
-        List<GroupBreadcrumb> breadcrumbs = new ArrayList<>();
-        GroupBreadcrumb breadcrumb = new GroupBreadcrumb();
-        breadcrumb.setGroupId("ROOT");
-        breadcrumb.setGroupName("ROOT");
-        breadcrumbs.add(breadcrumb);
-        return breadcrumbs;
-    }
-
-    private PaginatedData<GroupNode> getEmptyGroupsPanel(GroupsRequest request) {
-        return new PaginatedData<>(new ArrayList<>(), 1, request.getPaginatorPageSize());
-    }
-
     @GetMapping(value = "/", produces = MediaType.TEXT_HTML_VALUE)
     public String index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
diff --git a/gms/src/main/java/it/inaf/ia2/gms/manager/GroupsManager.java b/gms/src/main/java/it/inaf/ia2/gms/manager/GroupsManager.java
index dcbadeabd68c98e8d740635505b66a5fee01888a..6a76c6ba2862854f6779c604f3f8f9551c1dbd88 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/manager/GroupsManager.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/manager/GroupsManager.java
@@ -84,6 +84,10 @@ public class GroupsManager extends UserAwareComponent {
     }
 
     public void verifyUserCanReadGroup(GroupEntity group) {
+        if (GroupsService.ROOT.equals(group.getId())) {
+            // Everybody can read the root
+            return;
+        }
         if (permissionsManager.getCurrentUserPermission(group) == null) {
             loggingDAO.logAction(ActionType.UNAUTHORIZED_ACCESS_ATTEMPT, "Unauthorized group management request, group_id=" + group.getId());
             throw new UnauthorizedException("Missing permission to see this group");
diff --git a/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java b/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
index f684d6dd28134cac298402e5671fb8b721243997..eb1271e189584bc718030d261082bd849f9cf426 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
@@ -10,6 +10,7 @@ import it.inaf.ia2.gms.service.PermissionUtils;
 import it.inaf.ia2.gms.service.PermissionsService;
 import it.inaf.ia2.gms.authn.RapClient;
 import it.inaf.ia2.gms.persistence.model.ActionType;
+import it.inaf.ia2.gms.service.GroupsService;
 import it.inaf.ia2.rap.data.RapUser;
 import java.util.ArrayList;
 import java.util.List;
@@ -159,6 +160,8 @@ public class PermissionsManager extends UserAwareComponent {
 
     public Permission getCurrentUserPermission(GroupEntity group) {
         List<PermissionEntity> permissions = permissionsService.findUserPermissions(group, getCurrentUserId());
-        return PermissionUtils.getGroupPermission(group, permissions).orElse(null);
+        return PermissionUtils.getGroupPermission(group, permissions).orElse(
+                GroupsService.ROOT.equals(group.getId()) ? Permission.TRAVERSE : null
+        );
     }
 }
diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/ActionType.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/ActionType.java
index f867604ecfc355ae5d0ff118b432dfe23086713c..99827192322b6be1f9030cc79f715a9e1016d1e2 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/ActionType.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/ActionType.java
@@ -15,5 +15,6 @@ public enum ActionType {
     INVITED_REGISTRATION_OPENED,
     INVITED_REGISTRATION_DELETED,
     INVITED_REGISTRATION_COMPLETED,
+    API_CALL,
     UNAUTHORIZED_ACCESS_ATTEMPT
 }
diff --git a/gms/src/test/java/it/inaf/ia2/gms/manager/GroupsManagerTest.java b/gms/src/test/java/it/inaf/ia2/gms/manager/GroupsManagerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a63a0ce79a98a8cfe79eda7a7d93a00ef4f7c8c
--- /dev/null
+++ b/gms/src/test/java/it/inaf/ia2/gms/manager/GroupsManagerTest.java
@@ -0,0 +1,56 @@
+package it.inaf.ia2.gms.manager;
+
+import it.inaf.ia2.gms.exception.UnauthorizedException;
+import it.inaf.ia2.gms.persistence.LoggingDAO;
+import it.inaf.ia2.gms.persistence.model.GroupEntity;
+import it.inaf.ia2.gms.service.GroupsService;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GroupsManagerTest {
+
+    @Mock
+    private GroupsService groupsService;
+    @Mock
+    private PermissionsManager permissionsManager;
+    @Mock
+    private LoggingDAO loggingDAO;
+
+    @InjectMocks
+    private GroupsManager groupsManager;
+
+    @Test
+    public void testRootAlwaysReadable() {
+
+        GroupEntity root = new GroupEntity();
+        root.setName("ROOT");
+        root.setId(GroupsService.ROOT);
+        root.setPath("");
+
+        groupsManager.verifyUserCanReadGroup(root);
+    }
+
+    @Test
+    public void testVerifyUserCanReadGroupFails() {
+
+        boolean exception = false;
+
+        GroupEntity group = new GroupEntity();
+        group.setName("group_name");
+        group.setId("group_id");
+        group.setPath("group_id");
+
+        try {
+            groupsManager.verifyUserCanReadGroup(group);
+        } catch (UnauthorizedException ex) {
+            exception = true;
+        }
+
+        assertTrue(exception);
+    }
+}
diff --git a/gms/src/test/java/it/inaf/ia2/gms/manager/PermissionsManagerTest.java b/gms/src/test/java/it/inaf/ia2/gms/manager/PermissionsManagerTest.java
index 072a3eea0752df31792df08794120216a3e638be..403268696f3372374e4ed3e85af80b2c3d2a088e 100644
--- a/gms/src/test/java/it/inaf/ia2/gms/manager/PermissionsManagerTest.java
+++ b/gms/src/test/java/it/inaf/ia2/gms/manager/PermissionsManagerTest.java
@@ -5,11 +5,13 @@ import it.inaf.ia2.gms.model.Permission;
 import it.inaf.ia2.gms.persistence.LoggingDAO;
 import it.inaf.ia2.gms.persistence.model.GroupEntity;
 import it.inaf.ia2.gms.persistence.model.PermissionEntity;
+import it.inaf.ia2.gms.service.GroupsService;
 import it.inaf.ia2.gms.service.PermissionsService;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
+import static org.junit.Assert.assertEquals;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -137,6 +139,18 @@ public class PermissionsManagerTest {
         permissionsManager.removePermission(group, TARGET_USER_ID);
     }
 
+    @Test
+    public void testGetCurrentUserPermissionAlwaysTraverseRoot() {
+        when(permissionsService.findUserPermissions(any(), any())).thenReturn(new ArrayList<>());
+
+        GroupEntity root = new GroupEntity();
+        root.setName("ROOT");
+        root.setId(GroupsService.ROOT);
+        root.setPath("");
+
+        assertEquals(Permission.TRAVERSE, permissionsManager.getCurrentUserPermission(root));
+    }
+
     private List<PermissionEntity> getUserPermissions(GroupEntity group, Permission permission) {
         PermissionEntity entity = new PermissionEntity();
         entity.setPermission(permission);