diff --git a/openbis_ng_ui/src/js/common/consts/ids.js b/openbis_ng_ui/src/js/common/consts/ids.js
index 5a7846afc1fcc11bccce0fb49bf44223e9d3349b..7b561933fb27356e12f9dd64f2dd8a7cf693078f 100644
--- a/openbis_ng_ui/src/js/common/consts/ids.js
+++ b/openbis_ng_ui/src/js/common/consts/ids.js
@@ -5,11 +5,13 @@ const DATA_SET_TYPES_GRID_ID = 'data_set_types_grid'
 const MATERIAL_TYPES_GRID_ID = 'material_types_grid'
 const VOCABULARY_TYPES_GRID_ID = 'vocabulary_types_grid'
 const USERS_GRID_ID = 'users_grid'
-const USER_GROUPS_GRID_ID = 'user_groups_grid'
-const USER_USER_GROUPS_GRID_ID = 'user_user_groups_grid'
-const USER_ROLES_GRID_ID = 'user_roles_grid'
-const USER_GROUP_USERS_GRID_ID = 'user_group_users_grid'
-const USER_GROUP_ROLES_GRID_ID = 'user_group_roles_grid'
+const USERS_OF_GROUP_GRID_ID = 'users_of_group_grid'
+const GROUPS_GRID_ID = 'groups_grid'
+const GROUPS_OF_USER_GRID_ID = 'groups_of_user_grid'
+const ROLES_OF_USER_GRID_ID = 'roles_of_user_grid'
+const ROLES_OF_USERS_GRID_ID = 'roles_of_users_grid'
+const ROLES_OF_GROUP_GRID_ID = 'roles_of_group_grid'
+const ROLES_OF_GROUPS_GRID_ID = 'roles_of_groups_grid'
 const VOCABULARY_TERMS_GRID_ID = 'vocabulary_terms_grid'
 const DYNAMIC_PROPERTY_PLUGINS_GRID_ID = 'dynamic_property_plugins_grid'
 const ENTITY_VALIDATION_PLUGINS_GRID_ID = 'entity_validation_plugins_grid'
@@ -23,11 +25,13 @@ export default {
   MATERIAL_TYPES_GRID_ID,
   VOCABULARY_TYPES_GRID_ID,
   USERS_GRID_ID,
-  USER_GROUPS_GRID_ID,
-  USER_USER_GROUPS_GRID_ID,
-  USER_ROLES_GRID_ID,
-  USER_GROUP_USERS_GRID_ID,
-  USER_GROUP_ROLES_GRID_ID,
+  USERS_OF_GROUP_GRID_ID,
+  GROUPS_GRID_ID,
+  GROUPS_OF_USER_GRID_ID,
+  ROLES_OF_USER_GRID_ID,
+  ROLES_OF_USERS_GRID_ID,
+  ROLES_OF_GROUP_GRID_ID,
+  ROLES_OF_GROUPS_GRID_ID,
   VOCABULARY_TERMS_GRID_ID,
   DYNAMIC_PROPERTY_PLUGINS_GRID_ID,
   ENTITY_VALIDATION_PLUGINS_GRID_ID,
diff --git a/openbis_ng_ui/src/js/common/messages.js b/openbis_ng_ui/src/js/common/messages.js
index 077d021d6eb21ad3f5b22bc6906e3af26618b700..945a0d822344dc195ec76cc678ef59233243a34a 100644
--- a/openbis_ng_ui/src/js/common/messages.js
+++ b/openbis_ng_ui/src/js/common/messages.js
@@ -125,6 +125,8 @@ const keys = {
   RESULTS: 'RESULTS',
   ROLE: 'ROLE',
   ROLES: 'ROLES',
+  ROLES_OF_GROUPS: 'ROLES_OF_GROUPS',
+  ROLES_OF_USERS: 'ROLES_OF_USERS',
   ROLE_IS_INHERITED: 'ROLE_IS_INHERITED',
   ROLE_IS_INSTANCE_ADMIN: 'ROLE_IS_INSTANCE_ADMIN',
   ROWS_PER_PAGE: 'ROWS_PER_PAGE',
@@ -293,6 +295,8 @@ const messages_en = {
   [keys.RESULTS]: 'Results',
   [keys.ROLE]: 'Role',
   [keys.ROLES]: 'Roles',
+  [keys.ROLES_OF_GROUPS]: 'Groups\' Roles',
+  [keys.ROLES_OF_USERS]: 'Users\' Roles',
   [keys.ROLE_IS_INHERITED]: 'This role is inherited from ${0} group.',
   [keys.ROLE_IS_INSTANCE_ADMIN]: 'This is an instance admin role. It gives an access to the user and master data management functionality.',
   [keys.ROWS_PER_PAGE]: 'Rows per page: ',
diff --git a/openbis_ng_ui/src/js/components/users/common/RolesGrid.jsx b/openbis_ng_ui/src/js/components/users/common/RolesGrid.jsx
index 7e07039c291960d4b01d1e37ec889d46532f4e1d..23b3edb2345571f5857851ccbcbf61886861c78b 100644
--- a/openbis_ng_ui/src/js/components/users/common/RolesGrid.jsx
+++ b/openbis_ng_ui/src/js/components/users/common/RolesGrid.jsx
@@ -3,6 +3,7 @@ import React from 'react'
 import autoBind from 'auto-bind'
 import { withStyles } from '@material-ui/core/styles'
 import Grid from '@src/js/components/common/grid/Grid.jsx'
+import UserLink from '@src/js/components/common/link/UserLink.jsx'
 import UserGroupLink from '@src/js/components/common/link/UserGroupLink.jsx'
 import openbis from '@src/js/services/openbis.js'
 import ids from '@src/js/common/consts/ids.js'
@@ -34,12 +35,16 @@ class RolesGrid extends React.PureComponent {
       controllerRef
     } = this.props
 
-    let columnNames
+    let columnNames = ['level', 'space', 'project', 'role']
 
-    if (id === ids.USER_ROLES_GRID_ID) {
-      columnNames = ['inheritedFrom', 'level', 'space', 'project', 'role']
-    } else if (id === ids.USER_GROUP_ROLES_GRID_ID) {
-      columnNames = ['level', 'space', 'project', 'role']
+    if (id === ids.ROLES_OF_USER_GRID_ID) {
+      columnNames = ['inheritedFrom', ...columnNames]
+    } else if (id === ids.ROLES_OF_USERS_GRID_ID) {
+      columnNames = ['user', 'inheritedFrom', ...columnNames]
+    } else if (id === ids.ROLES_OF_GROUP_GRID_ID) {
+      columnNames = [...columnNames]
+    } else if (id === ids.ROLES_OF_GROUPS_GRID_ID) {
+      columnNames = ['group', ...columnNames]
     } else {
       throw 'Unsupported id: ' + id
     }
@@ -52,7 +57,7 @@ class RolesGrid extends React.PureComponent {
       <Grid
         id={id}
         controllerRef={controllerRef}
-        header={messages.get(messages.ROLES)}
+        header={this.getHeader()}
         columns={columns}
         rows={rows}
         selectedRowId={selectedRowId}
@@ -61,14 +66,63 @@ class RolesGrid extends React.PureComponent {
     )
   }
 
+  getHeader() {
+    const { id } = this.props
+
+    let message = null
+    if (id === ids.ROLES_OF_USER_GRID_ID || id === ids.ROLES_OF_GROUP_GRID_ID) {
+      message = messages.ROLES
+    } else if (id === ids.ROLES_OF_USERS_GRID_ID) {
+      message = messages.ROLES_OF_USERS
+    } else if (id === ids.ROLES_OF_GROUPS_GRID_ID) {
+      message = messages.ROLES_OF_GROUPS
+    }
+
+    return messages.get(message)
+  }
+
   getColumns() {
     const { id } = this.props
 
     return [
+      {
+        name: 'user',
+        label: messages.get(messages.USER),
+        sort: id === ids.ROLES_OF_USERS_GRID_ID ? 'asc' : null,
+        getValue: this.getUserValue,
+        renderValue: this.renderUserValue,
+        compareValue: params => {
+          return (
+            100000 * this.compareUserValue(params) +
+            10000 * this.compareInheritedFromValue(params) +
+            1000 * this.compareLevelValue(params) +
+            100 * this.compareSpaceValue(params) +
+            10 * this.compareProjectValue(params) +
+            this.compareRoleValue(params)
+          )
+        }
+      },
+      {
+        name: 'group',
+        label: messages.get(messages.GROUP),
+        sort: id === ids.ROLES_OF_GROUPS_GRID_ID ? 'asc' : null,
+        getValue: this.getGroupValue,
+        renderValue: this.renderGroupValue,
+        compareValue: params => {
+          return (
+            100000 * this.compareGroupValue(params) +
+            10000 * this.compareInheritedFromValue(params) +
+            1000 * this.compareLevelValue(params) +
+            100 * this.compareSpaceValue(params) +
+            10 * this.compareProjectValue(params) +
+            this.compareRoleValue(params)
+          )
+        }
+      },
       {
         name: 'inheritedFrom',
         label: messages.get(messages.INHERITED_FROM),
-        sort: id === ids.USER_ROLES_GRID_ID ? 'asc' : null,
+        sort: id === ids.ROLES_OF_USER_GRID_ID ? 'asc' : null,
         getValue: this.getInheritedFromValue,
         renderValue: this.renderInheritedFromValue,
         compareValue: params => {
@@ -84,12 +138,13 @@ class RolesGrid extends React.PureComponent {
       {
         name: 'level',
         label: messages.get(messages.LEVEL),
-        sort: id === ids.USER_GROUP_ROLES_GRID_ID ? 'asc' : null,
+        sort: id === ids.ROLES_OF_GROUP_GRID_ID ? 'asc' : null,
         getValue: this.getLevelValue,
         renderValue: this.renderLevelValue,
         compareValue: params => {
           return (
-            1000 * this.compareLevelValue(params) +
+            10000 * this.compareLevelValue(params) +
+            1000 * this.compareInheritedFromValue(params) +
             100 * this.compareSpaceValue(params) +
             10 * this.compareProjectValue(params) +
             this.compareRoleValue(params)
@@ -103,8 +158,9 @@ class RolesGrid extends React.PureComponent {
         renderValue: this.renderSpaceValue,
         compareValue: params => {
           return (
-            1000 * this.compareSpaceValue(params) +
-            100 * this.compareLevelValue(params) +
+            10000 * this.compareSpaceValue(params) +
+            1000 * this.compareLevelValue(params) +
+            100 * this.compareInheritedFromValue(params) +
             10 * this.compareProjectValue(params) +
             this.compareRoleValue(params)
           )
@@ -117,8 +173,9 @@ class RolesGrid extends React.PureComponent {
         renderValue: this.renderProjectValue,
         compareValue: params => {
           return (
-            1000 * this.compareProjectValue(params) +
-            100 * this.compareLevelValue(params) +
+            10000 * this.compareProjectValue(params) +
+            1000 * this.compareLevelValue(params) +
+            100 * this.compareInheritedFromValue(params) +
             10 * this.compareSpaceValue(params) +
             this.compareRoleValue(params)
           )
@@ -131,8 +188,9 @@ class RolesGrid extends React.PureComponent {
         renderValue: this.renderRoleValue,
         compareValue: params => {
           return (
-            1000 * this.compareRoleValue(params) +
-            100 * this.compareLevelValue(params) +
+            10000 * this.compareRoleValue(params) +
+            1000 * this.compareLevelValue(params) +
+            100 * this.compareInheritedFromValue(params) +
             10 * this.compareSpaceValue(params) +
             this.compareProjectValue(params)
           )
@@ -141,34 +199,50 @@ class RolesGrid extends React.PureComponent {
     ]
   }
 
+  getUserValue({ row }) {
+    return _.get(row, 'user.value')
+  }
+
+  getGroupValue({ row }) {
+    return _.get(row, 'group.value')
+  }
+
   getInheritedFromValue({ row }) {
-    return row.inheritedFrom.value
+    return _.get(row, 'inheritedFrom.value')
   }
 
   getLevelValue({ row }) {
-    return row.level.value
+    return _.get(row, 'level.value')
   }
 
   getSpaceValue({ row }) {
-    if (row.level.value === openbis.RoleLevel.INSTANCE) {
+    if (this.getLevelValue({ row }) === openbis.RoleLevel.INSTANCE) {
       return ALL_VALUE
     } else {
-      return row.space.value
+      return _.get(row, 'space.value')
     }
   }
 
   getProjectValue({ row }) {
-    if (row.level.value === openbis.RoleLevel.INSTANCE) {
+    if (this.getLevelValue({ row }) === openbis.RoleLevel.INSTANCE) {
       return ALL_VALUE
-    } else if (row.level.value === openbis.RoleLevel.SPACE) {
-      return row.space.value ? ALL_VALUE : null
+    } else if (this.getLevelValue({ row }) === openbis.RoleLevel.SPACE) {
+      return this.getSpaceValue({ row }) ? ALL_VALUE : null
     } else {
-      return row.project.value
+      return _.get(row, 'project.value')
     }
   }
 
   getRoleValue({ row }) {
-    return row.role.value
+    return _.get(row, 'role.value')
+  }
+
+  renderUserValue({ value }) {
+    return <UserLink userId={value} />
+  }
+
+  renderGroupValue({ value }) {
+    return <UserGroupLink groupCode={value} />
   }
 
   renderInheritedFromValue({ value }) {
@@ -194,13 +268,25 @@ class RolesGrid extends React.PureComponent {
   renderDefault({ value, row }) {
     const { classes } = this.props
 
-    if (row.inheritedFrom && row.inheritedFrom.value) {
+    if (this.getInheritedFromValue({ row })) {
       return <div className={classes.inherited}>{value}</div>
     } else {
       return value
     }
   }
 
+  compareUserValue({ row1, row2, defaultCompare }) {
+    const user1 = this.getUserValue({ row: row1 })
+    const user2 = this.getUserValue({ row: row2 })
+    return defaultCompare(user1, user2)
+  }
+
+  compareGroupValue({ row1, row2, defaultCompare }) {
+    const group1 = this.getGroupValue({ row: row1 })
+    const group2 = this.getGroupValue({ row: row2 })
+    return defaultCompare(group1, group2)
+  }
+
   compareInheritedFromValue({ row1, row2, defaultCompare }) {
     const inheritedFrom1 = this.getInheritedFromValue({ row: row1 })
     const inheritedFrom2 = this.getInheritedFromValue({ row: row2 })
diff --git a/openbis_ng_ui/src/js/components/users/form/UserFormGridGroups.jsx b/openbis_ng_ui/src/js/components/users/form/UserFormGridGroups.jsx
index 5d666968c9d37ad83a51d92b0469562692ea248d..6d03a516e23913c830ff7dac3da1f4264f018dd5 100644
--- a/openbis_ng_ui/src/js/components/users/form/UserFormGridGroups.jsx
+++ b/openbis_ng_ui/src/js/components/users/form/UserFormGridGroups.jsx
@@ -7,6 +7,6 @@ export default class UserFormGridGroups extends React.PureComponent {
   render() {
     logger.log(logger.DEBUG, 'UserFormGridGroups.render')
 
-    return <UserGroupsGrid {...this.props} id={ids.USER_USER_GROUPS_GRID_ID} />
+    return <UserGroupsGrid {...this.props} id={ids.GROUPS_OF_USER_GRID_ID} />
   }
 }
diff --git a/openbis_ng_ui/src/js/components/users/form/UserFormGridRoles.jsx b/openbis_ng_ui/src/js/components/users/form/UserFormGridRoles.jsx
index b835064ef1c6eaa4be5ea3bdd5c6d9256720f576..bc7b7faca2ee60d51d99e35e807f9a7ef9a814db 100644
--- a/openbis_ng_ui/src/js/components/users/form/UserFormGridRoles.jsx
+++ b/openbis_ng_ui/src/js/components/users/form/UserFormGridRoles.jsx
@@ -7,7 +7,7 @@ class UserFormGridRoles extends React.PureComponent {
   render() {
     logger.log(logger.DEBUG, 'UserFormGridRoles.render')
 
-    return <RolesGrid {...this.props} id={ids.USER_ROLES_GRID_ID} />
+    return <RolesGrid {...this.props} id={ids.ROLES_OF_USER_GRID_ID} />
   }
 }
 
diff --git a/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridRoles.jsx b/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridRoles.jsx
index 28b836a9c7189d09439f5d2e90fb47ef1e61a3a1..2eb60f2e0f9f86e1887fd68b81aabfc6b3ad2960 100644
--- a/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridRoles.jsx
+++ b/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridRoles.jsx
@@ -7,7 +7,7 @@ class UserGroupFormGridRoles extends React.PureComponent {
   render() {
     logger.log(logger.DEBUG, 'UserGroupFormGridRoles.render')
 
-    return <RolesGrid {...this.props} id={ids.USER_GROUP_ROLES_GRID_ID} />
+    return <RolesGrid {...this.props} id={ids.ROLES_OF_GROUP_GRID_ID} />
   }
 }
 
diff --git a/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridUsers.jsx b/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridUsers.jsx
index 0eb9715b093e29d250eedba0804cbd2fda5f387e..56b7440109d08bfacc4877e4dbe0c7ce0c8bfbbd 100644
--- a/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridUsers.jsx
+++ b/openbis_ng_ui/src/js/components/users/form/UserGroupFormGridUsers.jsx
@@ -7,6 +7,6 @@ export default class UserGroupFormGridUsers extends React.PureComponent {
   render() {
     logger.log(logger.DEBUG, 'UserGroupFormGridUsers.render')
 
-    return <UsersGrid {...this.props} id={ids.USER_GROUP_USERS_GRID_ID} />
+    return <UsersGrid {...this.props} id={ids.USERS_OF_GROUP_GRID_ID} />
   }
 }
diff --git a/openbis_ng_ui/src/js/components/users/search/UserSearch.jsx b/openbis_ng_ui/src/js/components/users/search/UserSearch.jsx
index 5c80ff46b4b02b873519cc3733ffd7b9c51b0d17..d2a4705b4b7d897a7c1849a59651c5f3b14b2ba0 100644
--- a/openbis_ng_ui/src/js/components/users/search/UserSearch.jsx
+++ b/openbis_ng_ui/src/js/components/users/search/UserSearch.jsx
@@ -4,6 +4,7 @@ import React from 'react'
 import GridContainer from '@src/js/components/common/grid/GridContainer.jsx'
 import UsersGrid from '@src/js/components/users/common/UsersGrid.jsx'
 import UserGroupsGrid from '@src/js/components/users/common/UserGroupsGrid.jsx'
+import RolesGrid from '@src/js/components/users/common/RolesGrid.jsx'
 import Message from '@src/js/components/common/form/Message.jsx'
 import FormUtil from '@src/js/components/common/form/FormUtil.js'
 import ids from '@src/js/common/consts/ids.js'
@@ -15,6 +16,9 @@ import util from '@src/js/common/util.js'
 import messages from '@src/js/common/messages.js'
 import logger from '@src/js/common/logger.js'
 
+const USER_FILTERED_FIELDS = ['userId', 'firstName', 'lastName']
+const USER_GROUP_FILTERED_FIELDS = ['code', 'description']
+
 class UserSearch extends React.Component {
   constructor(props) {
     super(props)
@@ -32,7 +36,12 @@ class UserSearch extends React.Component {
 
   async load() {
     try {
-      await Promise.all([this.loadUsers(), this.loadUserGroups()])
+      await Promise.all([
+        this.loadUsers(),
+        this.loadUsersRoles(),
+        this.loadUserGroups(),
+        this.loadUserGroupsRoles()
+      ])
       this.setState(() => ({
         loaded: true
       }))
@@ -55,13 +64,9 @@ class UserSearch extends React.Component {
     )
 
     const users = util
-      .filter(result.objects, this.props.searchText, [
-        'userId',
-        'firstName',
-        'lastName'
-      ])
+      .filter(result.objects, this.props.searchText, USER_FILTERED_FIELDS)
       .map(object => ({
-        id: _.get(object, 'userId'),
+        id: _.uniqueId('user-'),
         userId: FormUtil.createField({ value: _.get(object, 'userId') }),
         firstName: FormUtil.createField({ value: _.get(object, 'firstName') }),
         lastName: FormUtil.createField({ value: _.get(object, 'lastName') }),
@@ -75,6 +80,113 @@ class UserSearch extends React.Component {
     })
   }
 
+  async loadUsersRoles() {
+    if (!this.shouldLoad(objectTypes.USER)) {
+      return
+    }
+
+    const userFo = new openbis.PersonFetchOptions()
+    userFo.withRoleAssignments().withSpace()
+    userFo.withRoleAssignments().withProject().withSpace()
+
+    const groupFo = new openbis.AuthorizationGroupFetchOptions()
+    groupFo.withUsers()
+    groupFo.withRoleAssignments().withSpace()
+    groupFo.withRoleAssignments().withProject().withSpace()
+
+    const [userResult, groupResult] = await Promise.all([
+      openbis.searchPersons(new openbis.PersonSearchCriteria(), userFo),
+      openbis.searchAuthorizationGroups(
+        new openbis.AuthorizationGroupSearchCriteria(),
+        groupFo
+      )
+    ])
+
+    const usersRoles = []
+
+    util
+      .filter(userResult.objects, this.props.searchText, USER_FILTERED_FIELDS)
+      .forEach(user => {
+        const userAssignments = user.roleAssignments || []
+
+        userAssignments.forEach(userAssignment => {
+          const level = _.get(userAssignment, 'roleLevel', null)
+
+          let space = null
+          let project = null
+
+          if (level === openbis.RoleLevel.SPACE) {
+            space = _.get(userAssignment, 'space.code')
+          } else if (level === openbis.RoleLevel.PROJECT) {
+            space = _.get(userAssignment, 'project.space.code')
+            project = _.get(userAssignment, 'project.code')
+          }
+
+          usersRoles.push({
+            id: _.uniqueId('user-role-'),
+            user: FormUtil.createField({
+              value: _.get(user, 'userId', null)
+            }),
+            inheritedFrom: FormUtil.createField({
+              value: null
+            }),
+            level: FormUtil.createField({ value: level }),
+            space: FormUtil.createField({ value: space }),
+            project: FormUtil.createField({ value: project }),
+            role: FormUtil.createField({
+              value: _.get(userAssignment, 'role', null)
+            })
+          })
+        })
+      })
+
+    groupResult.objects.forEach(group => {
+      const groupUsers = util.filter(
+        group.users || [],
+        this.props.searchText,
+        USER_FILTERED_FIELDS
+      )
+
+      const groupAssignments = group.roleAssignments || []
+
+      groupUsers.forEach(groupUser => {
+        groupAssignments.forEach(groupAssignment => {
+          const level = _.get(groupAssignment, 'roleLevel', null)
+
+          let space = null
+          let project = null
+
+          if (level === openbis.RoleLevel.SPACE) {
+            space = _.get(groupAssignment, 'space.code')
+          } else if (level === openbis.RoleLevel.PROJECT) {
+            space = _.get(groupAssignment, 'project.space.code')
+            project = _.get(groupAssignment, 'project.code')
+          }
+
+          usersRoles.push({
+            id: _.uniqueId('user-role-'),
+            user: FormUtil.createField({
+              value: _.get(groupUser, 'userId', null)
+            }),
+            inheritedFrom: FormUtil.createField({
+              value: _.get(group, 'code')
+            }),
+            level: FormUtil.createField({ value: level }),
+            space: FormUtil.createField({ value: space }),
+            project: FormUtil.createField({ value: project }),
+            role: FormUtil.createField({
+              value: _.get(groupAssignment, 'role', null)
+            })
+          })
+        })
+      })
+    })
+
+    this.setState({
+      usersRoles
+    })
+  }
+
   async loadUserGroups() {
     if (!this.shouldLoad(objectTypes.USER_GROUP)) {
       return
@@ -86,9 +198,9 @@ class UserSearch extends React.Component {
     )
 
     const userGroups = util
-      .filter(result.objects, this.props.searchText, ['code', 'description'])
+      .filter(result.objects, this.props.searchText, USER_GROUP_FILTERED_FIELDS)
       .map(object => ({
-        id: _.get(object, 'code'),
+        id: _.uniqueId('group-'),
         code: FormUtil.createField({ value: _.get(object, 'code') }),
         description: FormUtil.createField({
           value: _.get(object, 'description')
@@ -100,6 +212,62 @@ class UserSearch extends React.Component {
     })
   }
 
+  async loadUserGroupsRoles() {
+    if (!this.shouldLoad(objectTypes.USER_GROUP)) {
+      return
+    }
+
+    const fo = new openbis.AuthorizationGroupFetchOptions()
+    fo.withRoleAssignments().withSpace()
+    fo.withRoleAssignments().withProject().withSpace()
+
+    const result = await openbis.searchAuthorizationGroups(
+      new openbis.AuthorizationGroupSearchCriteria(),
+      fo
+    )
+
+    const userGroups = util.filter(
+      result.objects,
+      this.props.searchText,
+      USER_GROUP_FILTERED_FIELDS
+    )
+
+    const userGroupsRoles = []
+    userGroups.forEach(userGroup => {
+      const roleAssignments = userGroup.roleAssignments || []
+      roleAssignments.forEach(roleAssignment => {
+        const level = _.get(roleAssignment, 'roleLevel', null)
+
+        let space = null
+        let project = null
+
+        if (level === openbis.RoleLevel.SPACE) {
+          space = _.get(roleAssignment, 'space.code')
+        } else if (level === openbis.RoleLevel.PROJECT) {
+          space = _.get(roleAssignment, 'project.space.code')
+          project = _.get(roleAssignment, 'project.code')
+        }
+
+        userGroupsRoles.push({
+          id: _.uniqueId('group-role-'),
+          group: FormUtil.createField({
+            value: _.get(userGroup, 'code', null)
+          }),
+          level: FormUtil.createField({ value: level }),
+          space: FormUtil.createField({ value: space }),
+          project: FormUtil.createField({ value: project }),
+          role: FormUtil.createField({
+            value: _.get(roleAssignment, 'role', null)
+          })
+        })
+      })
+    })
+
+    this.setState({
+      userGroupsRoles
+    })
+  }
+
   shouldLoad(objectType) {
     return this.props.objectType === objectType || !this.props.objectType
   }
@@ -139,16 +307,29 @@ class UserSearch extends React.Component {
       <GridContainer onClick={this.handleClickContainer}>
         {this.renderNoResultsFoundMessage()}
         {this.renderUsers()}
+        {this.renderUsersRoles()}
         {this.renderUserGroups()}
+        {this.renderUserGroupsRoles()}
       </GridContainer>
     )
   }
 
   renderNoResultsFoundMessage() {
     const { objectType } = this.props
-    const { users = [], userGroups = [] } = this.state
+    const {
+      users = [],
+      usersRoles = [],
+      userGroups = [],
+      userGroupsRoles = []
+    } = this.state
 
-    if (!objectType && users.length === 0 && userGroups.length === 0) {
+    if (
+      !objectType &&
+      users.length === 0 &&
+      usersRoles.length === 0 &&
+      userGroups.length === 0 &&
+      userGroupsRoles.length === 0
+    ) {
       return (
         <Message type='info'>{messages.get(messages.NO_RESULTS_FOUND)}</Message>
       )
@@ -172,11 +353,28 @@ class UserSearch extends React.Component {
     }
   }
 
+  renderUsersRoles() {
+    if (this.shouldRender(objectTypes.USER, this.state.usersRoles)) {
+      return (
+        <RolesGrid
+          id={ids.ROLES_OF_USERS_GRID_ID}
+          rows={this.state.usersRoles}
+          onSelectedRowChange={this.handleSelectedRowChange(
+            objectTypes.USER + '-role'
+          )}
+          selectedRowId={this.getSelectedRowId(objectTypes.USER + '-role')}
+        />
+      )
+    } else {
+      return null
+    }
+  }
+
   renderUserGroups() {
     if (this.shouldRender(objectTypes.USER_GROUP, this.state.userGroups)) {
       return (
         <UserGroupsGrid
-          id={ids.USER_GROUPS_GRID_ID}
+          id={ids.GROUPS_GRID_ID}
           rows={this.state.userGroups}
           onSelectedRowChange={this.handleSelectedRowChange(
             objectTypes.USER_GROUP
@@ -189,6 +387,25 @@ class UserSearch extends React.Component {
     }
   }
 
+  renderUserGroupsRoles() {
+    if (this.shouldRender(objectTypes.USER_GROUP, this.state.userGroupsRoles)) {
+      return (
+        <RolesGrid
+          id={ids.ROLES_OF_GROUPS_GRID_ID}
+          rows={this.state.userGroupsRoles}
+          onSelectedRowChange={this.handleSelectedRowChange(
+            objectTypes.USER_GROUP + '-role'
+          )}
+          selectedRowId={this.getSelectedRowId(
+            objectTypes.USER_GROUP + '-role'
+          )}
+        />
+      )
+    } else {
+      return null
+    }
+  }
+
   shouldRender(objectType, types) {
     return this.props.objectType === objectType || (types && types.length > 0)
   }
diff --git a/openbis_ng_ui/srcTest/js/components/users/form/UserFormComponentSortRoles.test.js b/openbis_ng_ui/srcTest/js/components/users/form/UserFormComponentSortRoles.test.js
index 87bb4c04c817ae5dd6758eda1ef80aa44e602631..a13ec4cd1cece4cd0e81b4748bc3bbb617faffbc 100644
--- a/openbis_ng_ui/srcTest/js/components/users/form/UserFormComponentSortRoles.test.js
+++ b/openbis_ng_ui/srcTest/js/components/users/form/UserFormComponentSortRoles.test.js
@@ -167,12 +167,12 @@ async function testSortRoles() {
         }
       ],
       rows: [
-        instanceAdminAssignmentRow,
         instanceObserverGroupRow,
-        mySpaceAdminAssignmentRow,
+        instanceAdminAssignmentRow,
         testSpacePowerUserGroupRow,
-        myProjectAdminAssignmentRow,
-        testProjectAdminGroupRow
+        mySpaceAdminAssignmentRow,
+        testProjectAdminGroupRow,
+        myProjectAdminAssignmentRow
       ]
     }
   })
@@ -205,8 +205,8 @@ async function testSortRoles() {
         }
       ],
       rows: [
-        instanceAdminAssignmentRow,
         instanceObserverGroupRow,
+        instanceAdminAssignmentRow,
         mySpaceAdminAssignmentRow,
         myProjectAdminAssignmentRow,
         testSpacePowerUserGroupRow,
@@ -243,10 +243,10 @@ async function testSortRoles() {
         }
       ],
       rows: [
-        instanceAdminAssignmentRow,
         instanceObserverGroupRow,
-        mySpaceAdminAssignmentRow,
+        instanceAdminAssignmentRow,
         testSpacePowerUserGroupRow,
+        mySpaceAdminAssignmentRow,
         myProjectAdminAssignmentRow,
         testProjectAdminGroupRow
       ]
@@ -283,8 +283,8 @@ async function testSortRoles() {
       rows: [
         instanceAdminAssignmentRow,
         mySpaceAdminAssignmentRow,
-        myProjectAdminAssignmentRow,
         testProjectAdminGroupRow,
+        myProjectAdminAssignmentRow,
         testSpacePowerUserGroupRow,
         instanceObserverGroupRow
       ]
diff --git a/openbis_ng_ui/srcTest/js/components/users/search/UserSearchComponentLoad.test.js b/openbis_ng_ui/srcTest/js/components/users/search/UserSearchComponentLoad.test.js
index ac1e7d5cf035505b3ade8461863588ad85210620..225935997412ec0d429b865a345379df43c26324 100644
--- a/openbis_ng_ui/srcTest/js/components/users/search/UserSearchComponentLoad.test.js
+++ b/openbis_ng_ui/srcTest/js/components/users/search/UserSearchComponentLoad.test.js
@@ -133,6 +133,7 @@ async function testLoadWithObjectType(resultsFound) {
   openbis.mockSearchPersons(
     resultsFound ? [testUser, testUser2, anotherUser] : []
   )
+  openbis.mockSearchGroups([])
 
   const form = await common.mount({
     objectType: objectTypes.USER
diff --git a/openbis_ng_ui/srcTest/js/components/users/search/wrapper/UserSearchWrapper.js b/openbis_ng_ui/srcTest/js/components/users/search/wrapper/UserSearchWrapper.js
index 8dc1ed417979a8cd82cba472b782b897f1501915..b985a277989bac1f502e9712ae9f9413e22243df 100644
--- a/openbis_ng_ui/srcTest/js/components/users/search/wrapper/UserSearchWrapper.js
+++ b/openbis_ng_ui/srcTest/js/components/users/search/wrapper/UserSearchWrapper.js
@@ -25,7 +25,7 @@ export default class UserSearchWrapper extends BaseWrapper {
   getUserGroups() {
     return new GridWrapper(
       this.findComponent(Grid).filter({
-        id: ids.USER_GROUPS_GRID_ID
+        id: ids.GROUPS_GRID_ID
       })
     )
   }