Repository: owncloud/ocis
Pull request #3925 (2022-06-07 10:47:08)

add memberOf to /users endpoint and members to /groups endpoint
This PR adds a members slice to the `/groups` endpoint and
a members slice to the `/users` endpoint.

refs #3837 

update-docs[bot]: Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a [changelog](https://github.com/owncloud/ocis/blob/master/changelog/README.md) item based on your changes.

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![2.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '2.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [2.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


ownclouders: :boom: Acceptance test [<strong>Core-API-Tests-ocis-storage-4</strong>](https://drone.owncloud.com/owncloud/ocis/12351/42/1) failed. Further test are cancelled...
<!-- id: pr-3925 -->

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![2.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '2.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [2.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![2.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '2.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [2.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![2.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '2.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [2.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [10 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![39.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/25-16px.png '39.4%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [39.4% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![16.2%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/20-16px.png '16.2%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [16.2% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [10 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![39.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/25-16px.png '39.4%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [39.4% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![16.2%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/20-16px.png '16.2%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [16.2% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3925)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3925&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL) [10 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3925&resolved=false&types=CODE_SMELL)

[![39.1%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/25-16px.png '39.1%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list) [39.1% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_coverage&view=list)  
[![16.6%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/20-16px.png '16.6%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list) [16.6% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3925&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/.drone.star b/.drone.star
index e21e8cb6d6b..72e4e848a3f 100644
--- a/.drone.star
+++ b/.drone.star
@@ -13,7 +13,7 @@ OC_CI_BAZEL_BUILDIFIER = "owncloudci/bazel-buildifier:latest"
 OC_CI_DRONE_ANSIBLE = "owncloudci/drone-ansible:latest"
 OC_CI_DRONE_CANCEL_PREVIOUS_BUILDS = "owncloudci/drone-cancel-previous-builds"
 OC_CI_DRONE_SKIP_PIPELINE = "owncloudci/drone-skip-pipeline"
-OC_CI_GOLANG = "owncloudci/golang:1.17"
+OC_CI_GOLANG = "owncloudci/golang:1.18"
 OC_CI_NODEJS = "owncloudci/nodejs:%s"
 OC_CI_PHP = "owncloudci/php:%s"
 OC_CI_WAIT_FOR = "owncloudci/wait-for:latest"
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 89918e30a9e..32492d9cab7 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -22,7 +22,7 @@
                 // demo users
                 "IDM_CREATE_DEMO_USERS": "true",
                 // OCIS_RUN_EXTENSIONS allows to start a subset of extensions even in the supervised mode
-                //"OCIS_RUN_EXTENSIONS": "settings,storage-system,graph,graph-explorer,idp,idm,ocs,store,thumbnails,web,webdav,frontend,gateway,users,groups,auth-basic,auth-bearer,storage-authmachine,storage-users,storage-shares,storage-publiclink,app-provider,sharing,proxy,ocdav",
+                //"OCIS_RUN_EXTENSIONS": "settings,storage-system,graph,graph-explorer,idp,idm,ocs,store,thumbnails,web,webdav,frontend,gateway,users,groups,auth-basic,auth-bearer,storage-authmachine,storage-users,storage-shares,storage-publiclink,storage-system,app-provider,sharing,proxy,ocdav",
 
                 /*
                  * Keep secrets and passwords in one block to allow easy uncommenting
diff --git a/changelog/unreleased/fix-default-role-assign.md b/changelog/unreleased/fix-default-role-assign.md
deleted file mode 100644
index 1697166bafe..00000000000
--- a/changelog/unreleased/fix-default-role-assign.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Bugfix: Rework default role provisioning
-
-We fixed a race condition in the default role assignment code that could lead to
-users loosing privileges. When authenticating before the settings service was fully
-running.
-
-https://github.com/owncloud/ocis/issues/3900
diff --git a/changelog/unreleased/improve-graph.md b/changelog/unreleased/improve-graph.md
new file mode 100644
index 00000000000..68ba0f08330
--- /dev/null
+++ b/changelog/unreleased/improve-graph.md
@@ -0,0 +1,6 @@
+Bugfix: Fix graph endpoint
+
+We have added the memberOf slice to the /users endpoint
+and the member slice to the /group endpoint
+
+https://github.com/owncloud/ocis/issues/3925
diff --git a/docs/extensions/graph/groups.md b/docs/extensions/graph/groups.md
index 145ff82b554..c32e1c93569 100644
--- a/docs/extensions/graph/groups.md
+++ b/docs/extensions/graph/groups.md
@@ -59,6 +59,57 @@ Response:
 }
 ```
 
+
+#### `GET /groups?$expand=members`
+
+Returns a list of all groups including its members
+
+Example:
+
+```
+curl -k 'https://localhost:9200/graph/v1.0/groups?$expand=members' -u user:password
+
+```
+
+Response:
+
+```
+{
+    "value": [
+        {
+            "displayName": "group",
+            "id": "38580a2e-7018-42ed-aff6-b2af0b4e9790",
+            "members": [
+                {
+                    "displayName": "user1",
+                    "id": "2e7b7e23-6c42-4d34-81b0-2bed34e51983",
+                    "mail": "user1@example.org",
+                    "onPremisesSamAccountName": "user1"
+                },
+                {
+                    "displayName": "user2",
+                    "id": "b45c9e35-0d95-4165-96bc-68bff4a316ed",
+                    "mail": "user2@example.org",
+                    "onPremisesSamAccountName": "user2"
+                }
+            ]
+        },
+        {
+            "displayName": "Example Users",
+            "id": "7a20f238-8a22-4458-902d-47674c317e5f",
+            "members": [
+                {
+                    "displayName": "user3",
+                    "id": "026fbfef-79ef-4f5d-887b-9eaf42777239",
+                    "mail": "user3@example.org",
+                    "onPremisesSamAccountName": "user3"
+                }
+            ]
+        }
+    ]
+}
+```
+
 #### `GET /groups/{groupid}`
 
 Example:
@@ -75,6 +126,31 @@ Response:
     "id": "7a20f238-8a22-4458-902d-47674c317e5f"
 }
 ```
+
+#### `GET /groups/{groupid}?$expand=members`
+
+Example:
+
+```
+curl -k 'https://localhost:9200/graph/v1.0/groups/7a20f238-8a22-4458-902d-47674c317e5f?$expand=members' -u user:password
+```
+
+Response:
+
+```
+{
+    "displayName": "Example Users",
+    "id": "7a20f238-8a22-4458-902d-47674c317e5f",
+    "members": [
+        {
+            "displayName": "user3",
+            "id": "026fbfef-79ef-4f5d-887b-9eaf42777239",
+            "mail": "user3@example.org",
+            "onPremisesSamAccountName": "user3"
+        }
+    ]
+}
+```
 ### Getting Group Members
 
 #### `GET /groups/{groupid}/members`
diff --git a/docs/extensions/graph/users.md b/docs/extensions/graph/users.md
index d8715d7b792..fe4dadfeffd 100644
--- a/docs/extensions/graph/users.md
+++ b/docs/extensions/graph/users.md
@@ -87,6 +87,62 @@ Response:
 }
 ```
 
+#### `GET /users?$expand=memberOf`
+
+Returns a list of all users
+
+Example:
+
+```
+curl -k 'https://localhost:9200/graph/v1.0/users?$expand=memberOf' -u user:password
+
+```
+
+Response:
+
+```
+{
+    "value": [
+        {
+            "displayName": "Albert Einstein",
+            "id": "4c510ada-c86b-4815-8820-42cdf82c3d51",
+            "mail": "einstein@example.org",
+            "onPremisesSamAccountName": "einstein",
+            "memberOf": [
+                {
+                    "displayName": "users",
+                    "id": "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"
+                },
+                {
+                    "displayName": "sailing-lovers",
+                    "id": "6040aa17-9c64-4fef-9bd0-77234d71bad0"
+                },
+                {
+                    "displayName": "violin-haters",
+                    "id": "dd58e5ec-842e-498b-8800-61f2ec6f911f"
+                },
+                {
+                    "displayName": "physics-lovers",
+                    "id": "262982c1-2362-4afa-bfdf-8cbfef64a06e"
+                }
+            ],
+        },
+        {
+            "displayName": "Maurice Moss",
+            "id": "058bff95-6708-4fe5-91e4-9ea3d377588b",
+            "mail": "moss@example.org",
+            "onPremisesSamAccountName": "moss",
+            "memberOf": [
+                {
+                    "displayName": "users",
+                    "id": "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"
+                }
+            ],
+        }
+    ]
+}
+```
+
 #### `GET /users/{userid or accountname}`
 
 Example:
@@ -106,6 +162,31 @@ Response:
 }
 ```
 
+#### `GET /users/{userid or accountname}?$expand=memberOf`
+
+Example:
+
+```
+curl -k 'https://localhost:9200/graph/v1.0/users/058bff95-6708-4fe5-91e4-9ea3d377588b?$expand=memberOf' -u user:password
+```
+
+Response:
+
+```
+{
+    "displayName": "Maurice Moss",
+    "id": "058bff95-6708-4fe5-91e4-9ea3d377588b",
+    "mail": "moss@example.org",
+    "onPremisesSamAccountName": "moss",
+            "memberOf": [
+                {
+                    "displayName": "users",
+                    "id": "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"
+                }
+            ],
+}
+```
+
 ### Creating / Updating Users
 
 #### `POST /users`
diff --git a/extensions/graph/pkg/identity/backend.go b/extensions/graph/pkg/identity/backend.go
index 49e71709b25..db003922e2f 100644
--- a/extensions/graph/pkg/identity/backend.go
+++ b/extensions/graph/pkg/identity/backend.go
@@ -15,14 +15,14 @@ type Backend interface {
 	DeleteUser(ctx context.Context, nameOrID string) error
 	// UpdateUser applies changes to given user, identified by username or id
 	UpdateUser(ctx context.Context, nameOrID string, user libregraph.User) (*libregraph.User, error)
-	GetUser(ctx context.Context, nameOrID string) (*libregraph.User, error)
+	GetUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.User, error)
 	GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error)
 
 	// CreateGroup creates the supplied group in the identity backend.
 	CreateGroup(ctx context.Context, group libregraph.Group) (*libregraph.Group, error)
 	// DeleteGroup deletes a given group, identified by id
 	DeleteGroup(ctx context.Context, id string) error
-	GetGroup(ctx context.Context, nameOrID string) (*libregraph.Group, error)
+	GetGroup(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.Group, error)
 	GetGroups(ctx context.Context, queryParam url.Values) ([]*libregraph.Group, error)
 	GetGroupMembers(ctx context.Context, id string) ([]*libregraph.User, error)
 	// AddMembersToGroup adds new members (reference by a slice of IDs) to supplied group in the identity backend.
diff --git a/extensions/graph/pkg/identity/cs3.go b/extensions/graph/pkg/identity/cs3.go
index 7a6cb282ca9..8c2dd73c61a 100644
--- a/extensions/graph/pkg/identity/cs3.go
+++ b/extensions/graph/pkg/identity/cs3.go
@@ -39,7 +39,7 @@ func (i *CS3) UpdateUser(ctx context.Context, nameOrID string, user libregraph.U
 	return nil, errNotImplemented
 }
 
-func (i *CS3) GetUser(ctx context.Context, userID string) (*libregraph.User, error) {
+func (i *CS3) GetUser(ctx context.Context, userID string, queryParam url.Values) (*libregraph.User, error) {
 	client, err := pool.GetGatewayServiceClient(i.Config.Address)
 	if err != nil {
 		i.Logger.Error().Err(err).Msg("could not get client")
@@ -147,7 +147,7 @@ func (i *CS3) CreateGroup(ctx context.Context, group libregraph.Group) (*libregr
 	return nil, errorcode.New(errorcode.NotSupported, "not implemented")
 }
 
-func (i *CS3) GetGroup(ctx context.Context, groupID string) (*libregraph.Group, error) {
+func (i *CS3) GetGroup(ctx context.Context, groupID string, queryParam url.Values) (*libregraph.Group, error) {
 	client, err := pool.GetGatewayServiceClient(i.Config.Address)
 	if err != nil {
 		i.Logger.Error().Err(err).Msg("could not get client")
diff --git a/extensions/graph/pkg/identity/ldap.go b/extensions/graph/pkg/identity/ldap.go
index c9083061f42..db666f81568 100644
--- a/extensions/graph/pkg/identity/ldap.go
+++ b/extensions/graph/pkg/identity/ldap.go
@@ -5,15 +5,16 @@ import (
 	"errors"
 	"fmt"
 	"net/url"
+	"strings"
 
 	"github.com/go-ldap/ldap/v3"
 	"github.com/gofrs/uuid"
 	ldapdn "github.com/libregraph/idm/pkg/ldapdn"
 	libregraph "github.com/owncloud/libre-graph-api-go"
-
 	"github.com/owncloud/ocis/v2/extensions/graph/pkg/config"
 	"github.com/owncloud/ocis/v2/extensions/graph/pkg/service/v0/errorcode"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
+	"golang.org/x/exp/slices"
 )
 
 var (
@@ -352,13 +353,29 @@ func (i *LDAP) getLDAPUserByFilter(filter string) (*ldap.Entry, error) {
 	return res.Entries[0], nil
 }
 
-func (i *LDAP) GetUser(ctx context.Context, nameOrID string) (*libregraph.User, error) {
+func (i *LDAP) GetUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.User, error) {
 	i.logger.Debug().Str("backend", "ldap").Msg("GetUser")
 	e, err := i.getLDAPUserByNameOrID(nameOrID)
 	if err != nil {
 		return nil, err
 	}
-	return i.createUserModelFromLDAP(e), nil
+	sel := strings.Split(queryParam.Get("$select"), ",")
+	exp := strings.Split(queryParam.Get("$expand"), ",")
+	u := i.createUserModelFromLDAP(e)
+	if slices.Contains(sel, "memberOf") || slices.Contains(exp, "memberOf") {
+		userGroups, err := i.getGroupsForUser(e.DN)
+		if err != nil {
+			return nil, err
+		}
+		if len(userGroups) > 0 {
+			groups := make([]libregraph.Group, 0, len(userGroups))
+			for _, g := range userGroups {
+				groups = append(groups, *i.createGroupModelFromLDAP(g))
+			}
+			u.MemberOf = groups
+		}
+	}
+	return u, nil
 }
 
 func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error) {
@@ -399,18 +416,66 @@ func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregra
 	users := make([]*libregraph.User, 0, len(res.Entries))
 
 	for _, e := range res.Entries {
-		users = append(users, i.createUserModelFromLDAP(e))
+		sel := strings.Split(queryParam.Get("$select"), ",")
+		exp := strings.Split(queryParam.Get("$expand"), ",")
+		u := i.createUserModelFromLDAP(e)
+		if slices.Contains(sel, "memberOf") || slices.Contains(exp, "memberOf") {
+			userGroups, err := i.getGroupsForUser(e.DN)
+			if err != nil {
+				return nil, err
+			}
+			if len(userGroups) > 0 {
+				expand := ldap.EscapeFilter(queryParam.Get("expand"))
+				if expand == "" {
+					expand = "false"
+				}
+				groups := make([]libregraph.Group, 0, len(userGroups))
+				for _, g := range userGroups {
+					groups = append(groups, *i.createGroupModelFromLDAP(g))
+				}
+				u.MemberOf = groups
+			}
+		}
+		users = append(users, u)
 	}
 	return users, nil
 }
 
-func (i *LDAP) GetGroup(ctx context.Context, nameOrID string) (*libregraph.Group, error) {
+func (i *LDAP) getGroupsForUser(dn string) ([]*ldap.Entry, error) {
+	groupFilter := fmt.Sprintf(
+		"(%s=%s)",
+		i.groupAttributeMap.member, dn,
+	)
+	userGroups, err := i.getLDAPGroupsByFilter(groupFilter, false, false)
+	if err != nil {
+		return nil, err
+	}
+	return userGroups, nil
+}
+
+func (i *LDAP) GetGroup(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.Group, error) {
 	i.logger.Debug().Str("backend", "ldap").Msg("GetGroup")
-	e, err := i.getLDAPGroupByNameOrID(nameOrID, false)
+	e, err := i.getLDAPGroupByNameOrID(nameOrID, true)
 	if err != nil {
 		return nil, err
 	}
-	return i.createGroupModelFromLDAP(e), nil
+	sel := strings.Split(queryParam.Get("$select"), ",")
+	exp := strings.Split(queryParam.Get("$expand"), ",")
+	g := i.createGroupModelFromLDAP(e)
+	if slices.Contains(sel, "members") || slices.Contains(exp, "members") {
+		members, err := i.GetGroupMembers(ctx, *g.Id)
+		if err != nil {
+			return nil, err
+		}
+		if len(members) > 1 {
+			m := make([]libregraph.User, 0, len(members))
+			for _, u := range members {
+				m = append(m, *u)
+			}
+			g.Members = m
+		}
+	}
+	return g, nil
 }
 
 func (i *LDAP) getLDAPGroupByID(id string, requestMembers bool) (*ldap.Entry, error) {
@@ -550,7 +615,23 @@ func (i *LDAP) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregr
 	groups := make([]*libregraph.Group, 0, len(res.Entries))
 
 	for _, e := range res.Entries {
-		groups = append(groups, i.createGroupModelFromLDAP(e))
+		sel := strings.Split(queryParam.Get("$select"), ",")
+		exp := strings.Split(queryParam.Get("$expand"), ",")
+		g := i.createGroupModelFromLDAP(e)
+		if slices.Contains(sel, "members") || slices.Contains(exp, "members") {
+			members, err := i.GetGroupMembers(ctx, *g.Id)
+			if err != nil {
+				return nil, err
+			}
+			if len(members) > 1 {
+				m := make([]libregraph.User, 0, len(members))
+				for _, u := range members {
+					m = append(m, *u)
+				}
+				g.Members = m
+			}
+		}
+		groups = append(groups, g)
 	}
 	return groups, nil
 }
diff --git a/extensions/graph/pkg/service/v0/groups.go b/extensions/graph/pkg/service/v0/groups.go
index 14a6e9461f6..3fef37505ee 100644
--- a/extensions/graph/pkg/service/v0/groups.go
+++ b/extensions/graph/pkg/service/v0/groups.go
@@ -162,7 +162,7 @@ func (g Graph) GetGroup(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	group, err := g.identityBackend.GetGroup(r.Context(), groupID)
+	group, err := g.identityBackend.GetGroup(r.Context(), groupID, r.URL.Query())
 	if err != nil {
 		var errcode errorcode.Error
 		if errors.As(err, &errcode) {
diff --git a/extensions/graph/pkg/service/v0/users.go b/extensions/graph/pkg/service/v0/users.go
index e272bdf4226..7e280201944 100644
--- a/extensions/graph/pkg/service/v0/users.go
+++ b/extensions/graph/pkg/service/v0/users.go
@@ -159,7 +159,7 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	user, err := g.identityBackend.GetUser(r.Context(), userID)
+	user, err := g.identityBackend.GetUser(r.Context(), userID, r.URL.Query())
 
 	if err != nil {
 		var errcode errorcode.Error
diff --git a/extensions/proxy/pkg/user/backend/cs3.go b/extensions/proxy/pkg/user/backend/cs3.go
index 57fbb552b59..683aa7e8ef3 100644
--- a/extensions/proxy/pkg/user/backend/cs3.go
+++ b/extensions/proxy/pkg/user/backend/cs3.go
@@ -3,7 +3,6 @@ package backend
 import (
 	"context"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"io"
 	"net/http"
@@ -22,7 +21,6 @@ import (
 	"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
 	"github.com/owncloud/ocis/v2/ocis-pkg/registry"
 	settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
-	merrors "go-micro.dev/v4/errors"
 	"go-micro.dev/v4/selector"
 )
 
@@ -78,27 +76,24 @@ func (c *cs3backend) GetUserByClaims(ctx context.Context, claim, value string, w
 	if user.Id.Type != cs3.UserType_USER_TYPE_LIGHTWEIGHT {
 		roleIDs, err = loadRolesIDs(ctx, user.Id.OpaqueId, c.settingsRoleService)
 		if err != nil {
-			var merr *merrors.Error
-			if errors.As(err, &merr) && merr.Code == http.StatusNotFound {
-				// This user doesn't have a role assignment yet. Assign a
-				// default user role. At least until proper roles are provided. See
-				// https://github.com/owncloud/ocis/v2/issues/1825 for more context.
-				if user.Id.Type == cs3.UserType_USER_TYPE_PRIMARY {
-					c.logger.Info().Str("userid", user.Id.OpaqueId).Msg("user has no role assigned, assigning default user role")
-					_, err := c.settingsRoleService.AssignRoleToUser(ctx, &settingssvc.AssignRoleToUserRequest{
-						AccountUuid: user.Id.OpaqueId,
-						RoleId:      settingsService.BundleUUIDRoleUser,
-					})
-					if err != nil {
-						c.logger.Error().Err(err).Msg("Could not add default role")
-						return nil, "", err
-					}
-					roleIDs = append(roleIDs, settingsService.BundleUUIDRoleUser)
-				}
-			} else {
-				c.logger.Error().Err(err).Msgf("Could not load roles")
-				return nil, "", err
+			c.logger.Error().Err(err).Msgf("Could not load roles")
+		}
+	}
+
+	// if roles are empty, assume we haven't seen the user before and assign a
+	// default user role. At least until proper roles are provided. See
+	// https://github.com/owncloud/ocis/v2/issues/1825 for more context.
+	if len(roleIDs) == 0 {
+		if user.Id.Type == cs3.UserType_USER_TYPE_PRIMARY {
+			c.logger.Info().Str("userid", user.Id.OpaqueId).Msg("user has no role assigned, assigning default user role")
+			_, err := c.settingsRoleService.AssignRoleToUser(ctx, &settingssvc.AssignRoleToUserRequest{
+				AccountUuid: user.Id.OpaqueId,
+				RoleId:      settingsService.BundleUUIDRoleUser,
+			})
+			if err != nil {
+				c.logger.Warn().Err(err).Msg("Could not add default role")
 			}
+			roleIDs = append(roleIDs, settingsService.BundleUUIDRoleUser)
 		}
 	}
 
diff --git a/extensions/settings/pkg/store/metadata/assignments.go b/extensions/settings/pkg/store/metadata/assignments.go
index 36f2adc44c4..8570ca9b1e6 100644
--- a/extensions/settings/pkg/store/metadata/assignments.go
+++ b/extensions/settings/pkg/store/metadata/assignments.go
@@ -7,11 +7,15 @@ import (
 	"fmt"
 
 	"github.com/gofrs/uuid"
+	"github.com/owncloud/ocis/v2/extensions/settings/pkg/store/defaults"
 	settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
 )
 
 // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier.
 func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) {
+	if s.mdc == nil {
+		return s.defaultRoleAssignments(accountUUID), nil
+	}
 	s.Init()
 	ctx := context.TODO()
 	assIDs, err := s.mdc.ReadDir(ctx, accountPath(accountUUID))
@@ -88,6 +92,16 @@ func (s *Store) RemoveRoleAssignment(assignmentID string) error {
 	return fmt.Errorf("assignmentID '%s' not found", assignmentID)
 }
 
+func (s *Store) defaultRoleAssignments(accID string) []*settingsmsg.UserRoleAssignment {
+	var assmnts []*settingsmsg.UserRoleAssignment
+	for _, r := range defaults.DefaultRoleAssignments(s.cfg) {
+		if r.AccountUuid == accID {
+			assmnts = append(assmnts, r)
+		}
+	}
+	return assmnts
+}
+
 func accountPath(accountUUID string) string {
 	return fmt.Sprintf("%s/%s", accountsFolderLocation, accountUUID)
 }
diff --git a/go.mod b/go.mod
index 821200dc52f..d418b307b1f 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/owncloud/ocis/v2
 
-go 1.17
+go 1.18
 
 require (
 	github.com/CiscoM31/godata v1.0.5
@@ -49,7 +49,7 @@ require (
 	github.com/onsi/ginkgo/v2 v2.1.4
 	github.com/onsi/gomega v1.19.0
 	github.com/orcaman/concurrent-map v1.0.0
-	github.com/owncloud/libre-graph-api-go v0.14.2
+	github.com/owncloud/libre-graph-api-go v0.14.3
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.12.2
 	github.com/rs/zerolog v1.27.0
@@ -67,6 +67,7 @@ require (
 	go.opentelemetry.io/otel/sdk v1.7.0
 	go.opentelemetry.io/otel/trace v1.7.0
 	golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29
+	golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf
 	golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
 	golang.org/x/net v0.0.0-20220516155154-20f960328961
 	golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
diff --git a/go.sum b/go.sum
index a3ee162d609..e6335635ef9 100644
--- a/go.sum
+++ b/go.sum
@@ -228,7 +228,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/ceph/go-ceph v0.15.0 h1:ILB3NaLWOtt4u/2d8I8HZTC4Ycm1PsOYVar3IFU1xlo=
 github.com/ceph/go-ceph v0.15.0/go.mod h1:mafFpf5Vg8Ai8Bd+FAMvKBHLmtdpTXdRP/TNq8XWegY=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -274,7 +273,6 @@ github.com/coreos/go-oidc/v3 v3.2.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpA
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -284,7 +282,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
 github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
 github.com/couchbase/moss v0.2.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
 github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
-github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
 github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -447,7 +444,6 @@ github.com/go-micro/plugins/v4/server/grpc v1.0.1/go.mod h1:+eiInCaAvLiDSY4QGwIr
 github.com/go-micro/plugins/v4/server/http v1.0.0 h1:cuSp4F8uS7sWjvmsJ8M4k18rZF3AxA2qdLA6kFxPktM=
 github.com/go-micro/plugins/v4/server/http v1.0.0/go.mod h1:E8eoUONK91jcMpvkcFUsqbgDyKyri3x7ty2GuM5SsI0=
 github.com/go-micro/plugins/v4/transport/grpc v1.0.0 h1:QbwEGFo9tiDwqJWZ37FJ8gK5xnApy47EnKcmQWRRSJs=
-github.com/go-micro/plugins/v4/transport/grpc v1.0.0/go.mod h1:yW7+92O0bHZLusf3dboKymHWucRTUtingtQEeIaVhMg=
 github.com/go-micro/plugins/v4/wrapper/breaker/gobreaker v1.0.0 h1:0+UUCB9b6yIB+7rm4gde6L7itnpTbIpLPGF28l5rjc4=
 github.com/go-micro/plugins/v4/wrapper/breaker/gobreaker v1.0.0/go.mod h1:2knc5FNrVz7k1ZJWNJPrN68RPis6i0gyjCgIKi++R2s=
 github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus v1.0.0 h1:8zCLSM8tFNX52XkmM0w7btkRjxPLxWqq12J89c98R1g=
@@ -664,13 +660,11 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3 h1:BGNSrTRW4rwfhJiFwvwF4XQ0Y72Jj9YEgxVrtovbD5o=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3/go.mod h1:VHn7KgNsRriXa4mcgtkpR00OXyQY6g67JWMvn+R27A4=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
 github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/api v1.9.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
 github.com/hashicorp/consul/api v1.11.0 h1:Hw/G8TtRvOElqxVIhBzXciiSTbapq8hZ2XKZsXk5ZCE=
 github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
 github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -800,7 +794,6 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
 github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
 github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
 github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -955,24 +948,17 @@ github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOl
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/jwt v1.1.0 h1:+vOlgtM0ZsF46GbmUoadq0/2rChNS45gtxHEa3H1gqM=
-github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M=
 github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
 github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I=
 github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
-github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU=
 github.com/nats-io/nats-server/v2 v2.7.4/go.mod h1:1vZ2Nijh8tcyNe8BDVyTviCd9NYzRbubQYiEHsvOQWc=
 github.com/nats-io/nats-server/v2 v2.8.0/go.mod h1:5vic7C58BFEVltiZhs7Kq81q2WcEPhJPsmNv1FOrdv0=
 github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4=
 github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4=
-github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
 github.com/nats-io/nats.go v1.13.1-0.20220308171302-2f2f6968e98d/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nats.go v1.14.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nats.go v1.15.0 h1:3IXNBolWrwIUf2soxh6Rla8gPzYWEZQBUBK6RV21s+o=
 github.com/nats-io/nats.go v1.15.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -1023,8 +1009,8 @@ github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk
 github.com/orcaman/concurrent-map v1.0.0 h1:I/2A2XPCb4IuQWcQhBhSwGfiuybl/J0ev9HDbW65HOY=
 github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
 github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
-github.com/owncloud/libre-graph-api-go v0.14.2 h1:JiI32eDp7JZmiVv4aUpC4yaPpv6gK4xxM9MOe/0cXpE=
-github.com/owncloud/libre-graph-api-go v0.14.2/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U=
+github.com/owncloud/libre-graph-api-go v0.14.3 h1:+lkIkLHjrLfazANYfg2MYEhaJsMXzfOjtIY1hF3PbU4=
+github.com/owncloud/libre-graph-api-go v0.14.3/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U=
 github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
 github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -1131,7 +1117,6 @@ github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
 github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
 github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM=
 github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
-github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -1173,7 +1158,6 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:s
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/smartystreets/gunit v1.0.4/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
 github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
 github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
 github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 h1:0jjO3HdJfOn6gYHD/ZNZh0LLMxEAqkYX7xoDPQReEgs=
@@ -1238,7 +1222,6 @@ github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
 github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
 github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4=
@@ -1284,8 +1267,6 @@ github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q
 github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
 github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
 github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
-go-micro.dev/v4 v4.3.0/go.mod h1:tw47Xfg2YywfPUnglZgXQsSf7p0ST6mQL3v0JooGmSY=
-go-micro.dev/v4 v4.4.0/go.mod h1:hSBUne6gtYTfYmnNxGQmaNmRQ6z8LqGrAVNmL/ae0lY=
 go-micro.dev/v4 v4.6.0/go.mod h1:7UY87mLE6T4zHKsNS5D+VWZcXGTEvU1rbA90PezzlWM=
 go-micro.dev/v4 v4.7.0 h1:vjvZ94JNBMXb7MrbpSIf2zMmj8oVMmOnJRDJLnGGGaE=
 go-micro.dev/v4 v4.7.0/go.mod h1:7UY87mLE6T4zHKsNS5D+VWZcXGTEvU1rbA90PezzlWM=
@@ -1299,7 +1280,6 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.2 h1:4hzqQ6hIb3blLyQ8usCU4h3NghkqcsohEQ3o3Vet
 go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v3 v3.5.2 h1:WdnejrUtQC4nCxK0/dLTMqKOB+U5TP/2Ya0BJL+1otA=
 go.etcd.io/etcd/client/v3 v3.5.2/go.mod h1:kOOaWFFgHygyT0WlSmL8TJiXmMysO/nNUlEsSsN6W4o=
-go.m3o.com v0.1.0/go.mod h1:p8FdLqZH3R9a0y04qiMNT+clw69d3SxyQPFzCNbDRtk=
 go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
 go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
 go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
@@ -1367,7 +1347,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -1380,13 +1359,11 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
 golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@@ -1403,6 +1380,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf h1:oXVg4h2qJDd9htKxb5SCpFBHLipW6hXmL3qpUixS2jw=
+golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf/go.mod h1:yh0Ynu2b5ZUe3MQfp2nM0ecK7wsgouWTDN0FNeJuIys=
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1496,7 +1475,6 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -1647,7 +1625,6 @@ golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1836,7 +1813,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
 google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1866,7 +1842,6 @@ google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEc
 google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
 google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
@@ -1900,7 +1875,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
 google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
@@ -1908,7 +1882,6 @@ google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
 google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU=
-google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/ocis/pkg/init/init.go b/ocis/pkg/init/init.go
index a4411ac2db5..8fd77b7a670 100644
--- a/ocis/pkg/init/init.go
+++ b/ocis/pkg/init/init.go
@@ -28,15 +28,15 @@ type InsecureExtension struct {
 }
 
 type InsecureProxyExtension struct {
-	Insecure_backends bool
+	InsecureBackends bool `yaml:"insecure_backends"`
 }
 
 type DataProviderInsecureSettings struct {
-	Data_provider_insecure bool
+	DataProviderInsecure bool `yaml:"data_provider_insecure"`
 }
 
 type LdapSettings struct {
-	Bind_password string
+	BindPassword string `yaml:"bind_password"`
 }
 type LdapBasedExtension struct {
 	Ldap LdapSettings
@@ -100,7 +100,7 @@ type ThumbnailExtension struct {
 // - marshal it to yaml
 type OcisConfig struct {
 	TokenManager      TokenManager `yaml:"token_manager"`
-	MachineAuthApiKey string       `yaml:"machine_auth_api_key"`
+	MachineAuthAPIKey string       `yaml:"machine_auth_api_key"`
 	SystemUserAPIKey  string       `yaml:"system_user_api_key"`
 	TransferSecret    string       `yaml:"transfer_secret"`
 	SystemUserID      string       `yaml:"system_user_id"`
@@ -193,11 +193,11 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
 	if err != nil {
 		return fmt.Errorf("could not generate random password for tokenmanager: %s", err)
 	}
-	machineAuthApiKey, err := generators.GenerateRandomPassword(passwordLength)
+	machineAuthAPIKey, err := generators.GenerateRandomPassword(passwordLength)
 	if err != nil {
 		return fmt.Errorf("could not generate random password for machineauthsecret: %s", err)
 	}
-	systemUserApiKey, err := generators.GenerateRandomPassword(passwordLength)
+	systemUserAPIKey, err := generators.GenerateRandomPassword(passwordLength)
 	if err != nil {
 		return fmt.Errorf("could not generate random system user API key: %s", err)
 	}
@@ -214,8 +214,8 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
 		TokenManager: TokenManager{
 			JWTSecret: tokenManagerJwtSecret,
 		},
-		MachineAuthApiKey: machineAuthApiKey,
-		SystemUserAPIKey:  systemUserApiKey,
+		MachineAuthAPIKey: machineAuthAPIKey,
+		SystemUserAPIKey:  systemUserAPIKey,
 		TransferSecret:    revaTransferSecret,
 		SystemUserID:      systemUserID,
 		AdminUserID:       adminUserID,
@@ -229,34 +229,34 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
 		},
 		Idp: LdapBasedExtension{
 			Ldap: LdapSettings{
-				Bind_password: idpServicePassword,
+				BindPassword: idpServicePassword,
 			},
 		},
 		AuthBasic: AuthbasicExtension{
 			AuthProviders: LdapBasedExtension{
 				Ldap: LdapSettings{
-					Bind_password: revaServicePassword,
+					BindPassword: revaServicePassword,
 				},
 			},
 		},
 		Groups: UsersAndGroupsExtension{
 			Drivers: LdapBasedExtension{
 				Ldap: LdapSettings{
-					Bind_password: revaServicePassword,
+					BindPassword: revaServicePassword,
 				},
 			},
 		},
 		Users: UsersAndGroupsExtension{
 			Drivers: LdapBasedExtension{
 				Ldap: LdapSettings{
-					Bind_password: revaServicePassword,
+					BindPassword: revaServicePassword,
 				},
 			},
 		},
 		Graph: GraphExtension{
 			Identity: LdapBasedExtension{
 				Ldap: LdapSettings{
-					Bind_password: idmServicePassword,
+					BindPassword: idmServicePassword,
 				},
 			},
 		},
@@ -287,13 +287,13 @@ func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword strin
 			Insecure: true,
 		}
 		cfg.Proxy = InsecureProxyExtension{
-			Insecure_backends: true,
+			InsecureBackends: true,
 		}
 		cfg.StorageSystem = DataProviderInsecureSettings{
-			Data_provider_insecure: true,
+			DataProviderInsecure: true,
 		}
 		cfg.StorageUsers = DataProviderInsecureSettings{
-			Data_provider_insecure: true,
+			DataProviderInsecure: true,
 		}
 
 		cfg.Thumbnails.Thumbnail.WebdavAllowInsecure = true


Test patch:
diff --git a/extensions/graph/pkg/identity/ldap_test.go b/extensions/graph/pkg/identity/ldap_test.go
index d272eb6e36d..aac54eca444 100644
--- a/extensions/graph/pkg/identity/ldap_test.go
+++ b/extensions/graph/pkg/identity/ldap_test.go
@@ -125,7 +125,24 @@ func TestGetUser(t *testing.T) {
 		return nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock"))
 	}
 	b, _ := getMockedBackend(&sf, lconfig, &logger)
-	_, err := b.GetUser(context.Background(), "fred")
+
+	queryParamExpand := url.Values{
+		"$expand": []string{"memberOf"},
+	}
+	queryParamSelect := url.Values{
+		"$select": []string{"memberOf"},
+	}
+	_, err := b.GetUser(context.Background(), "fred", nil)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+
+	_, err = b.GetUser(context.Background(), "fred", queryParamExpand)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+
+	_, err = b.GetUser(context.Background(), "fred", queryParamSelect)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
@@ -135,7 +152,17 @@ func TestGetUser(t *testing.T) {
 		return &ldap.SearchResult{}, nil
 	}
 	b, _ = getMockedBackend(&sf, lconfig, &logger)
-	_, err = b.GetUser(context.Background(), "fred")
+	_, err = b.GetUser(context.Background(), "fred", nil)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+
+	_, err = b.GetUser(context.Background(), "fred", queryParamExpand)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+
+	_, err = b.GetUser(context.Background(), "fred", queryParamSelect)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
@@ -147,7 +174,21 @@ func TestGetUser(t *testing.T) {
 		}, nil
 	}
 	b, _ = getMockedBackend(&sf, lconfig, &logger)
-	u, err := b.GetUser(context.Background(), "user")
+	u, err := b.GetUser(context.Background(), "user", nil)
+	if err != nil {
+		t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
+	} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
+		t.Errorf("Expected GetUser to return a valid user")
+	}
+
+	u, err = b.GetUser(context.Background(), "user", queryParamExpand)
+	if err != nil {
+		t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
+	} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
+		t.Errorf("Expected GetUser to return a valid user")
+	}
+
+	u, err = b.GetUser(context.Background(), "user", queryParamSelect)
 	if err != nil {
 		t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
 	} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
@@ -182,8 +223,22 @@ func TestGetGroup(t *testing.T) {
 	var sf searchFunc = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
 		return nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock"))
 	}
+	queryParamExpand := url.Values{
+		"$expand": []string{"memberOf"},
+	}
+	queryParamSelect := url.Values{
+		"$select": []string{"memberOf"},
+	}
 	b, _ := getMockedBackend(&sf, lconfig, &logger)
-	_, err := b.GetGroup(context.Background(), "group")
+	_, err := b.GetGroup(context.Background(), "group", nil)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+	_, err = b.GetGroup(context.Background(), "group", queryParamExpand)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+	_, err = b.GetGroup(context.Background(), "group", queryParamSelect)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
@@ -193,7 +248,15 @@ func TestGetGroup(t *testing.T) {
 		return &ldap.SearchResult{}, nil
 	}
 	b, _ = getMockedBackend(&sf, lconfig, &logger)
-	_, err = b.GetGroup(context.Background(), "group")
+	_, err = b.GetGroup(context.Background(), "group", nil)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+	_, err = b.GetGroup(context.Background(), "group", queryParamExpand)
+	if err == nil || err.Error() != "itemNotFound" {
+		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
+	}
+	_, err = b.GetGroup(context.Background(), "group", queryParamSelect)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
@@ -205,7 +268,19 @@ func TestGetGroup(t *testing.T) {
 		}, nil
 	}
 	b, _ = getMockedBackend(&sf, lconfig, &logger)
-	g, err := b.GetGroup(context.Background(), "group")
+	g, err := b.GetGroup(context.Background(), "group", nil)
+	if err != nil {
+		t.Errorf("Expected GetGroup to succeed. Got %s", err.Error())
+	} else if *g.Id != groupEntry.GetEqualFoldAttributeValue(b.groupAttributeMap.id) {
+		t.Errorf("Expected GetGroup to return a valid group")
+	}
+	g, err = b.GetGroup(context.Background(), "group", queryParamExpand)
+	if err != nil {
+		t.Errorf("Expected GetGroup to succeed. Got %s", err.Error())
+	} else if *g.Id != groupEntry.GetEqualFoldAttributeValue(b.groupAttributeMap.id) {
+		t.Errorf("Expected GetGroup to return a valid group")
+	}
+	g, err = b.GetGroup(context.Background(), "group", queryParamSelect)
 	if err != nil {
 		t.Errorf("Expected GetGroup to succeed. Got %s", err.Error())
 	} else if *g.Id != groupEntry.GetEqualFoldAttributeValue(b.groupAttributeMap.id) {