diff --git a/gms-ui/src/api/server/index.js b/gms-ui/src/api/server/index.js
index cfb352e6cf78c9b814732462a06512e1fbbcc1ab..b73e02220319d8c4a7689bfa9cad65261831d35d 100644
--- a/gms-ui/src/api/server/index.js
+++ b/gms-ui/src/api/server/index.js
@@ -325,7 +325,9 @@ export default {
   },
   search(input) {
     let url = BASE_API_URL + 'search?query=' + input.genericSearch.filter +
-      '&page=' + input.genericSearch.paginatorPage + '&pageSize=' + input.genericSearch.paginatorPageSize;
+      '&paginatorPage=' + input.genericSearch.paginatorPage +
+      '&paginatorPageSize=' + input.genericSearch.paginatorPageSize +
+      '&users=' + input.genericSearch.users + "&groups=" + input.genericSearch.groups;
 
     return apiRequest({
       method: 'GET',
diff --git a/gms-ui/src/components/GenericSearchResults.vue b/gms-ui/src/components/GenericSearchResults.vue
index ea163ca4b3ced10e2d33fa9d1ddff5162ba78381..781de5b59740c198454f7dadce5204f358581ff1 100644
--- a/gms-ui/src/components/GenericSearchResults.vue
+++ b/gms-ui/src/components/GenericSearchResults.vue
@@ -1,5 +1,10 @@
 <template>
 <div class="mt-sm-3">
+  <b-form inline>
+    Includes:
+    <b-form-checkbox class="ml-4" v-model="input.genericSearch.users" @input="updateTypeFilter">users</b-form-checkbox>
+    <b-form-checkbox class="ml-4" v-model="input.genericSearch.groups" @input="updateTypeFilter">groups</b-form-checkbox>
+  </b-form>
   <div>
     <div v-if="model.genericSearchResults.items && model.genericSearchResults.items.length > 0">
       <p>Search results:</p>
@@ -40,7 +45,7 @@ export default {
     '$route': 'updateSearchResults'
   },
   methods: {
-    openSearchResult: function(result) {
+    openSearchResult(result) {
       switch (result.type) {
         case 'GROUP':
           this.$store.dispatch('openGroup', result.id);
@@ -50,7 +55,11 @@ export default {
           break;
       }
     },
-    updateSearchResults: function() {
+    updateTypeFilter() {
+      this.input.genericSearch.paginatorPage = 1;
+      this.updateSearchResults();
+    },
+    updateSearchResults() {
       this.$store.dispatch('search', this.$route.query.q);
     }
   }
diff --git a/gms-ui/src/components/TopMenu.vue b/gms-ui/src/components/TopMenu.vue
index 1d92647b143783247a86d2e6bc14f8db81ad99f6..71ad85afc939d2012a46b51e272da1884e1c221c 100644
--- a/gms-ui/src/components/TopMenu.vue
+++ b/gms-ui/src/components/TopMenu.vue
@@ -12,7 +12,7 @@
         <b-nav-item href="help/index.html" target="blank_" class="mr-4">Help</b-nav-item>
         <b-nav-form>
           <b-form-input size="sm" class="mr-sm-2" placeholder="Search" v-model.trim="input.genericSearch.filter" @keydown.native.enter.prevent="genericSearch"></b-form-input>
-          <b-button size="sm" class="my-2 my-sm-0" type="button" v-on:click="genericSearch()">Search</b-button>
+          <b-button size="sm" type="button" v-on:click="genericSearch()">Search</b-button>
         </b-nav-form>
         <b-nav-item-dropdown :text="user" right v-if="user">
           <b-dropdown-item href="logout">Logout</b-dropdown-item>
@@ -39,10 +39,8 @@ export default {
       this.$router.push('/', () => {});
     },
     genericSearch() {
-      this.input.genericSearch.page = 1;
-      this.input.genericSearch.pageSize = 20;
       this.$router.push({ path: '/search', query: { q: this.input.genericSearch.filter } }, () => {});
-      this.$store.dispatch('search', this.input.genericSearch.filter);
+      this.$store.commit('setGenericSearchFilter', this.input.genericSearch.filter);
     }
   }
 }
diff --git a/gms-ui/src/store.js b/gms-ui/src/store.js
index d4026005be31b2064fc94f8f165287f3980b4b23..9d8ffa828db3dde6d36cae49dfe779466b2e2e6c 100644
--- a/gms-ui/src/store.js
+++ b/gms-ui/src/store.js
@@ -36,7 +36,9 @@ export default new Vuex.Store({
       genericSearch: {
         filter: '',
         paginatorPage: 1,
-        paginatorPageSize: 20
+        paginatorPageSize: 20,
+        users: true,
+        groups: true
       }
     },
     loading: false
@@ -97,6 +99,10 @@ export default new Vuex.Store({
     },
     setGenericSearchFilter(state, filter) {
       state.input.genericSearch.filter = filter;
+      state.input.genericSearch.paginatorPage = 1;
+      state.input.genericSearch.paginatorPageSize = 20;
+      state.input.genericSearch.users = true;
+      state.input.genericSearch.groups = true;
     },
     removeInvitedRegistration(state, regId) {
       let index = -1;
@@ -117,7 +123,9 @@ export default new Vuex.Store({
         .then(model => commit('updateHomePageModel', model));
     },
     search({ commit, state }, filter) {
-      commit('setGenericSearchFilter', filter);
+      if (state.input.genericSearch.filter !== filter) {
+        commit('setGenericSearchFilter', filter);
+      }
       client.search(state.input)
         .then(results => commit('displaySearchResults', results));
     },
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/SearchController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/SearchController.java
index a7fcc04bd49d13e89763ad95920004261b1d32b6..20c18fc56c5be28c617b3f937368204ede895dc2 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/SearchController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/SearchController.java
@@ -1,16 +1,17 @@
 package it.inaf.ia2.gms.controller;
 
+import it.inaf.ia2.gms.model.request.GenericSearchRequest;
 import it.inaf.ia2.gms.model.response.PaginatedData;
 import it.inaf.ia2.gms.model.response.SearchResponseItem;
 import it.inaf.ia2.gms.model.response.UserSearchResponse;
 import it.inaf.ia2.gms.service.SearchService;
 import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController
@@ -23,10 +24,8 @@ public class SearchController {
     private SearchService searchService;
 
     @GetMapping(value = "/search", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<PaginatedData<SearchResponseItem>> getSearchResults(@RequestParam("query") String query,
-            @RequestParam("page") int page, @RequestParam("pageSize") int pageSize) {
-
-        PaginatedData<SearchResponseItem> response = searchService.search(query, servletRequest.getUserPrincipal().getName(), page, pageSize);
+    public ResponseEntity<PaginatedData<SearchResponseItem>> getSearchResults(@Valid GenericSearchRequest searchRequest) {
+        PaginatedData<SearchResponseItem> response = searchService.search(searchRequest, servletRequest.getUserPrincipal().getName());
         return ResponseEntity.ok(response);
     }
 
diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/request/GenericSearchRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/request/GenericSearchRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..da973b458c471c5a7676f7cebb9f2a4848b8cfd9
--- /dev/null
+++ b/gms/src/main/java/it/inaf/ia2/gms/model/request/GenericSearchRequest.java
@@ -0,0 +1,37 @@
+package it.inaf.ia2.gms.model.request;
+
+public class GenericSearchRequest extends PaginatedModelRequest {
+
+    private String query;
+    private boolean users;
+    private boolean groups;
+
+    public GenericSearchRequest() {
+        this.users = true;
+        this.groups = true;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    public boolean isUsers() {
+        return users;
+    }
+
+    public void setUsers(boolean users) {
+        this.users = users;
+    }
+
+    public boolean isGroups() {
+        return groups;
+    }
+
+    public void setGroups(boolean groups) {
+        this.groups = groups;
+    }
+}
diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/request/PaginatedModelRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/request/PaginatedModelRequest.java
index 7910d69f1f50bd9d2bc1855902c073ebc35134bb..5c64c250a81759b472580f5a3dd92e378a7e1377 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/model/request/PaginatedModelRequest.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/model/request/PaginatedModelRequest.java
@@ -8,6 +8,11 @@ public class PaginatedModelRequest {
     private int paginatorPage;
     private int paginatorPageSize;
 
+    public PaginatedModelRequest() {
+        this.paginatorPage = 1;
+        this.paginatorPageSize = 20;
+    }
+
     public int getPaginatorPage() {
         return paginatorPage;
     }
diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/SearchService.java b/gms/src/main/java/it/inaf/ia2/gms/service/SearchService.java
index 9cd5d43e8f88e099e69b2e7ed85ab99dc2cc889e..47f45d814b58ddcb551e810947543f8a031b4c78 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/service/SearchService.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/service/SearchService.java
@@ -14,6 +14,7 @@ import it.inaf.ia2.gms.persistence.PermissionsDAO;
 import it.inaf.ia2.gms.persistence.model.GroupEntity;
 import it.inaf.ia2.gms.persistence.model.PermissionEntity;
 import it.inaf.ia2.gms.authn.RapClient;
+import it.inaf.ia2.gms.model.request.GenericSearchRequest;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -46,15 +47,21 @@ public class SearchService {
     /**
      * Generic search (both groups and users).
      */
-    public PaginatedData<SearchResponseItem> search(String query, String userId, int page, int pageSize) {
+    public PaginatedData<SearchResponseItem> search(GenericSearchRequest searchRequest, String userId) {
 
-        List<SearchResponseItem> items = searchUsers(query);
-        items.addAll(searchGroups(query, userId));
+        List<SearchResponseItem> items = new ArrayList<>();
+
+        if (searchRequest.isUsers()) {
+            items.addAll(searchUsers(searchRequest.getQuery()));
+        }
+        if (searchRequest.isGroups()) {
+            items.addAll(searchGroups(searchRequest.getQuery(), userId));
+        }
 
         // sort by label
         items.sort((i1, i2) -> i1.getLabel().compareTo(i2.getLabel()));
 
-        return new PaginatedData<>(items, page, pageSize);
+        return new PaginatedData<>(items, searchRequest.getPaginatorPage(), searchRequest.getPaginatorPageSize());
     }
 
     private List<SearchResponseItem> searchUsers(String query) {
diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/SearchControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/SearchControllerTest.java
index bfe0b1a1bb7b81ff65c4010b430779c011d2d1f5..4c98a67d48a48ac6b28df19edb294eb5a055a021 100644
--- a/gms/src/test/java/it/inaf/ia2/gms/controller/SearchControllerTest.java
+++ b/gms/src/test/java/it/inaf/ia2/gms/controller/SearchControllerTest.java
@@ -8,11 +8,14 @@ import it.inaf.ia2.gms.model.response.UserSearchResponse;
 import it.inaf.ia2.gms.service.SearchService;
 import java.util.ArrayList;
 import javax.servlet.http.HttpServletRequest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
@@ -53,13 +56,20 @@ public class SearchControllerTest {
 
         PaginatedData<SearchResponseItem> response = new PaginatedData<>(new ArrayList<>(), 1, 10);
 
-        when(searchService.search(any(), any(), anyInt(), anyInt())).thenReturn(response);
+        when(searchService.search(any(), any())).thenReturn(response);
 
-        mockMvc.perform(get("/search?query=searchText&page=1&pageSize=10")
+        mockMvc.perform(get("/search?query=searchText&paginatorPage=1&paginatorPageSize=10&groups=false")
                 .contentType(MediaType.APPLICATION_JSON_VALUE))
                 .andExpect(status().isOk());
 
-        verify(searchService, times(1)).search(eq("searchText"), eq("admin_id"), eq(1), eq(10));
+        verify(searchService, times(1)).search(argThat(req -> {
+            assertEquals("searchText", req.getQuery());
+            assertEquals(1, req.getPaginatorPage());
+            assertEquals(10, req.getPaginatorPageSize());
+            assertTrue(req.isUsers());
+            assertFalse(req.isGroups());
+            return true;
+        }), eq("admin_id"));
     }
 
     @Test
diff --git a/gms/src/test/java/it/inaf/ia2/gms/service/SearchServiceTest.java b/gms/src/test/java/it/inaf/ia2/gms/service/SearchServiceTest.java
index 8cd002411bc75be3d45a482c9e28eb87770cb64e..1ed36a442c5e5b8b5853af588d5179d8d09851ec 100644
--- a/gms/src/test/java/it/inaf/ia2/gms/service/SearchServiceTest.java
+++ b/gms/src/test/java/it/inaf/ia2/gms/service/SearchServiceTest.java
@@ -12,6 +12,7 @@ import it.inaf.ia2.gms.persistence.PermissionsDAO;
 import it.inaf.ia2.gms.persistence.model.GroupEntity;
 import it.inaf.ia2.gms.persistence.model.PermissionEntity;
 import it.inaf.ia2.gms.authn.RapClient;
+import it.inaf.ia2.gms.model.request.GenericSearchRequest;
 import it.inaf.ia2.rap.data.Identity;
 import it.inaf.ia2.rap.data.IdentityType;
 import it.inaf.ia2.rap.data.RapUser;
@@ -118,7 +119,10 @@ public class SearchServiceTest {
         when(permissionsDAO.findUserPermissions(any())).thenReturn(
                 Collections.singletonList(permission));
 
-        PaginatedData<SearchResponseItem> response = searchService.search("foo", "manager_id", 1, 10);
+        GenericSearchRequest searchRequest = new GenericSearchRequest();
+        searchRequest.setQuery("foo");
+
+        PaginatedData<SearchResponseItem> response = searchService.search(searchRequest, "manager_id");
 
         assertEquals(2, response.getTotalItems());