Repository: owncloud/ocis
Pull request #4135 (2022-07-07 14:46:32)

Add access_token verification
Try to verify access_token as JWT and extract expiry

We try to parse the access token as a JWT now. Verifying the signature using the keys downloaded from the jwks_uri of the IDP. Currently we only use it to extract the expiry information from the JWT. This could be reworked to extract other claims from the token for authorization purposes.



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.

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

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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![6.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '6.4%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [6.4% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![12.2%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '12.2%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [12.2% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_duplicated_lines_density&view=list)


rhafer: Note, I've not yet added code to verifying the audience of the access token #2967 . It should be pretty straighforware with this change. But I'd like to get agreement on this part first. Especially as it introduces yet another new dependency for the jwks refresh handling. (github.com/MicahParks/keyfunc)

Adding the audience check will happen in another PR.
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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![13.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '13.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [13.0% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_duplicated_lines_density&view=list)


rhafer: @mmattel This adds a couple of new settings. Add you as a reviewer for doc strings.
mmattel: I will do the env string review on monday.
Already some things identified that needs improvement, but I have to leave now.
mmattel: I have reviewed the description texts.
What I cant see is, if there are types and defaults set - check if they are present and add if not.
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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![13.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '13.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [13.0% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_duplicated_lines_density&view=list)


rhafer: > What I cant see is, if there are types and defaults set - check if they are present and add if not.

Yes. Defaults were added for all the new settings. Thanks for the review!
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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![18.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '18.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [18.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=4135&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=4135&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=4135&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=4135&resolved=false&types=CODE_SMELL)

[![18.8%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '18.8%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_coverage&view=list) [18.8% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&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=4135&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=4135&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/.drone.env b/.drone.env
index ec3d6f948d1..3c3e50f89c6 100644
--- a/.drone.env
+++ b/.drone.env
@@ -1,7 +1,7 @@
 # The test runner source for API tests
-CORE_COMMITID=8b15ef46e68cf73ea861d4f180ed1f6bff5096a8
+CORE_COMMITID=3eebf7b731759e71c76481fa2de1d5cdb308f21d
 CORE_BRANCH=master
 
 # The test runner source for UI tests
-WEB_COMMITID=0bb33e791f10f1afebfde4ea4da356e46ecdc201
+WEB_COMMITID=9882f20cdce1b5e699b6ff31057bce29189ab4c7
 WEB_BRANCH=master
diff --git a/.drone.star b/.drone.star
index 4ce8ab9d135..47e78ca728f 100644
--- a/.drone.star
+++ b/.drone.star
@@ -18,7 +18,7 @@ OC_CI_PHP = "owncloudci/php:%s"
 OC_CI_WAIT_FOR = "owncloudci/wait-for:latest"
 OC_CS3_API_VALIDATOR = "owncloud/cs3api-validator:0.2.0"
 OC_LITMUS = "owncloud/litmus:latest"
-OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.6.0"
+OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.8.0"
 OC_SERVER = "owncloud/server:10"
 OC_UBUNTU = "owncloud/ubuntu:20.04"
 OSIXIA_OPEN_LDAP = "osixia/openldap:latest"
@@ -103,6 +103,10 @@ config = {
         "skipExceptParts": [],
         "earlyFail": True,
     },
+    "e2eTests": {
+        "skip": False,
+        "earlyFail": True,
+    },
     "settingsUITests": {
         "skip": False,
         "earlyFail": True,
@@ -317,6 +321,18 @@ def yarnInstallUITests():
         ],
     }]
 
+def yarnInstallE2eTests():
+    return [{
+        "name": "yarn-install-e2e",
+        "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
+        "commands": [
+            ". /drone/src/.drone.env",
+            "cd webTestRunner",
+            "git checkout $WEB_COMMITID",
+            "retry -t 3 'yarn install --immutable'",
+        ],
+    }]
+
 def testOcisModules(ctx):
     pipelines = []
     for module in config["modules"]:
@@ -372,6 +388,9 @@ def testPipelines(ctx):
     if "skip" not in config["uiTests"] or not config["uiTests"]["skip"]:
         pipelines += uiTests(ctx)
 
+    if "skip" not in config["e2eTests"] or not config["e2eTests"]["skip"]:
+        pipelines += e2eTests(ctx)
+
     if "skip" not in config["settingsUITests"] or not config["settingsUITests"]["skip"]:
         pipelines.append(settingsUITests(ctx))
 
@@ -835,6 +854,134 @@ def uiTestPipeline(ctx, filterTags, early_fail, runPart = 1, numberOfParts = 1,
         },
     }
 
+def e2eTests(ctx):
+    e2e_trigger = {
+        "ref": [
+            "refs/heads/master",
+            "refs/tags/**",
+            "refs/pull/**",
+        ],
+    }
+
+    e2e_volumes = [{
+        "name": "uploads",
+        "temp": {},
+    }, {
+        "name": "configs",
+        "temp": {},
+    }, {
+        "name": "gopath",
+        "temp": {},
+    }]
+
+    e2e_test_ocis = [{
+        "name": "e2e-tests",
+        "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION,
+        "environment": {
+            "BASE_URL_OCIS": "ocis-server:9200",
+            "HEADLESS": "true",
+            "OCIS": "true",
+            "RETRY": "1",
+            "WEB_UI_CONFIG": "/drone/src/tests/config/drone/ocis-config.json",
+            "LOCAL_UPLOAD_DIR": "/uploads",
+        },
+        "commands": [
+            "cd webTestRunner",
+            "sleep 10 && yarn test:e2e:cucumber tests/e2e/cucumber/**/*[!.oc10].feature",
+        ],
+    }]
+
+    e2eTestsSteps = \
+        skipIfUnchanged(ctx, "e2e-tests") + \
+        restoreBuildArtifactCache(ctx, "ocis-binary-amd64", "ocis/bin/ocis") + \
+        restoreBuildArtifactCache(ctx, "web-dist", "webTestRunner") + \
+        yarnInstallE2eTests() + \
+        ocisServer("ocis", 4, []) + \
+        e2e_test_ocis + \
+        uploadTracingResult(ctx) + \
+        publishTracingResult(ctx, "e2e test")
+
+    if ("skip-e2e" in ctx.build.title.lower()):
+        return []
+
+    if (ctx.build.event != "tag"):
+        return [{
+            "kind": "pipeline",
+            "type": "docker",
+            "name": "e2e-tests",
+            "steps": e2eTestsSteps,
+            "depends_on": getPipelineNames([buildOcisBinaryForTesting(ctx)]),
+            "trigger": e2e_trigger,
+            "volumes": e2e_volumes,
+        }]
+
+def uploadTracingResult(ctx):
+    return [{
+        "name": "upload-tracing-result",
+        "image": PLUGINS_S3,
+        "pull": "if-not-exists",
+        "settings": {
+            "bucket": {
+                "from_secret": "cache_public_s3_bucket",
+            },
+            "endpoint": {
+                "from_secret": "cache_public_s3_server",
+            },
+            "path_style": True,
+            "source": "webTestRunner/reports/e2e/playwright/tracing/**/*",
+            "strip_prefix": "webTestRunner/reports/e2e/playwright/tracing",
+            "target": "${DRONE_BUILD_NUMBER}/tracing",
+        },
+        "environment": {
+            "AWS_ACCESS_KEY_ID": {
+                "from_secret": "cache_public_s3_access_key",
+            },
+            "AWS_SECRET_ACCESS_KEY": {
+                "from_secret": "cache_public_s3_secret_key",
+            },
+        },
+        "when": {
+            "status": [
+                "failure",
+            ],
+            "event": [
+                "pull_request",
+                "cron",
+            ],
+        },
+    }]
+
+def publishTracingResult(ctx, suite):
+    return [{
+        "name": "publish-tracing-result",
+        "image": OC_UBUNTU,
+        "commands": [
+            "cd webTestRunner/reports/e2e/playwright/tracing/",
+            'echo "<details><summary>:boom: To see the trace, please open the link in the console ...</summary>\\n\\n<p>\\n\\n" >>  comments.file',
+            'for f in *.zip; do echo "#### npx playwright show-trace $CACHE_ENDPOINT/$CACHE_BUCKET/${DRONE_BUILD_NUMBER}/tracing/$f \n" >>  comments.file; done',
+            'echo "\n</p></details>" >>  comments.file',
+            "more  comments.file",
+        ],
+        "environment": {
+            "TEST_CONTEXT": suite,
+            "CACHE_ENDPOINT": {
+                "from_secret": "cache_public_s3_server",
+            },
+            "CACHE_BUCKET": {
+                "from_secret": "cache_public_s3_bucket",
+            },
+        },
+        "when": {
+            "status": [
+                "failure",
+            ],
+            "event": [
+                "pull_request",
+                "cron",
+            ],
+        },
+    }]
+
 def settingsUITests(ctx, storage = "ocis", accounts_hash_difficulty = 4):
     early_fail = config["settingsUITests"]["earlyFail"] if "earlyFail" in config["settingsUITests"] else False
 
@@ -1899,6 +2046,8 @@ def skipIfUnchanged(ctx, type):
         skip = base + unit + acceptance
     if type == "cache":
         skip = base
+    if type == "e2e-tests":
+        skip = base + unit
     if len(skip) == 0:
         return []
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dd7ef7351f..e8d6847b865 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,7 +13,8 @@ The following sections list the changes for unreleased.
 * Enhancement - Improve error log for "could not get user by claim" error: [#4227](https://github.com/owncloud/ocis/pull/4227)
 * Enhancement - Allow providing list of services NOT to start: [#4254](https://github.com/owncloud/ocis/pull/4254)
 * Enhancement - Introduce insecure flag for smtp email notifications: [#4279](https://github.com/owncloud/ocis/pull/4279)
-* Enhancement - Update reva to vx.x.x: [#4272](https://github.com/owncloud/ocis/pull/4272)
+* Enhancement - Update reva to vx.x.x: [#4294](https://github.com/owncloud/ocis/pull/4294)
+* Enhancement - Update ownCloud Web to v5.7.0-rc.7: [#4314](https://github.com/owncloud/ocis/pull/4314)
 
 ## Details
 
@@ -74,14 +75,61 @@ The following sections list the changes for unreleased.
 
    https://github.com/owncloud/ocis/pull/4279
 
-* Enhancement - Update reva to vx.x.x: [#4272](https://github.com/owncloud/ocis/pull/4272)
+* Enhancement - Update reva to vx.x.x: [#4294](https://github.com/owncloud/ocis/pull/4294)
 
    Updated reva to version x.x.x. This update includes:
 
-   https://github.com/owncloud/ocis/pull/4272
-   https://github.com/cs3org/reva/pull/3096
-   *
-   todo:
+  * TODO:
+
+   Https://github.com/owncloud/ocis/pull/4272
+   https://github.com/cs3org/reva/pull/3096 https://github.com/cs3org/reva/pull/4315
+
+   https://github.com/owncloud/ocis/pull/4294
+
+* Enhancement - Update ownCloud Web to v5.7.0-rc.7: [#4314](https://github.com/owncloud/ocis/pull/4314)
+
+   Tags: web
+
+   We updated ownCloud Web to v5.7.0-rc.7. Please refer to the changelog (linked) for details on
+   the web release.
+
+  * Bugfix [owncloud/web#7080](https://github.com/owncloud/web/issues/7080): Add Droparea again
+  * Bugfix [owncloud/web#7357](https://github.com/owncloud/web/pull/7357): Batch deleting multiple files
+  * Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Decline share not possible
+  * Bugfix [owncloud/web#7322](https://github.com/owncloud/web/pull/7322): Files pagination scroll to top
+  * Bugfix [owncloud/web#7348](https://github.com/owncloud/web/pull/7348): Left sidebar active navigation item has wrong cursor
+  * Bugfix [owncloud/web#7355](https://github.com/owncloud/web/pull/7355): Link indicator on "Shared via link"-page
+  * Bugfix [owncloud/web#7325](https://github.com/owncloud/web/pull/7325): Loading state in views
+  * Bugfix [owncloud/web#7344](https://github.com/owncloud/web/pull/7344): Missing file icon in details panel
+  * Bugfix [owncloud/web#7321](https://github.com/owncloud/web/pull/7321): Missing scroll bar in user management app
+  * Bugfix [owncloud/web#7334](https://github.com/owncloud/web/pull/7334): No redirect after disabling space
+  * Bugfix [owncloud/web#3071](https://github.com/owncloud/web/issues/3071): Don't leak oidc callback url into browser history
+  * Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Open file on shared space resource not possible
+  * Bugfix [owncloud/web#7268](https://github.com/owncloud/web/issues/7268): Personal shares leaked into project space
+  * Bugfix [owncloud/web#7359](https://github.com/owncloud/web/pull/7359): Fix infinite loading spinner on invalid preview links
+  * Bugfix [owncloud/web#7272](https://github.com/owncloud/web/issues/7272): Print backend version
+  * Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Rename shared space resource not possible
+  * Bugfix [owncloud/web#7210](https://github.com/owncloud/web/pull/7210): Repair navigation highlighter
+  * Bugfix [owncloud/web#7308](https://github.com/owncloud/web/pull/7308): "Shared with others" and "Shared via Link" resource links not working
+  * Bugfix [owncloud/web#7349](https://github.com/owncloud/web/pull/7349): Missing quick actions in spaces file list
+  * Bugfix [owncloud/web#7038](https://github.com/owncloud/web/issues/7038): File list render performance
+  * Bugfix [owncloud/web#7240](https://github.com/owncloud/web/issues/7240): Access token renewal during upload
+  * Bugfix [owncloud/web#7376](https://github.com/owncloud/web/pull/7376): Tooltips not shown on disabled create and upload button
+  * Bugfix [owncloud/web#7297](https://github.com/owncloud/web/pull/7297): Upload overlay progress bar spacing
+  * Bugfix [owncloud/web#7332](https://github.com/owncloud/web/pull/7332): Users list not loading if user has no role
+  * Bugfix [owncloud/web#7313](https://github.com/owncloud/web/pull/7313): Versions of shared files not visible
+  * Enhancement [owncloud/web#7350](https://github.com/owncloud/web/pull/7350): Change file loading mechanism in `preview` app
+  * Enhancement [owncloud/web#7356](https://github.com/owncloud/web/pull/7356): Declined shares are now easily accessible
+  * Enhancement [owncloud/web#7365](https://github.com/owncloud/web/pull/7365): Drop menu styling in right sidebar
+  * Enhancement [owncloud/web#7252](https://github.com/owncloud/web/pull/7252): Redesign shared with list
+  * Enhancement [owncloud/web#7371](https://github.com/owncloud/web/pull/7371): Use fixed width for the right sidebar
+  * Enhancement [owncloud/web#7267](https://github.com/owncloud/web/pull/7267): Search all files announce limit
+  * Enhancement [owncloud/web#7364](https://github.com/owncloud/web/pull/7364): Sharing panel show label instead of description for links
+  * Enhancement [owncloud/web#7355](https://github.com/owncloud/web/pull/7355): Update ODS to v14.0.0-alpha.12
+  * Enhancement [owncloud/web#7375](https://github.com/owncloud/web/pull/7375): User management app saved dialog
+
+   https://github.com/owncloud/ocis/pull/4314
+   https://github.com/owncloud/web/releases/tag/v5.7.0-rc.7
 # Changelog for [2.0.0-beta.5] (2022-07-19)
 
 The following sections list the changes for 2.0.0-beta.5.
diff --git a/changelog/unreleased/enhancement-access-token-validation.md b/changelog/unreleased/enhancement-access-token-validation.md
new file mode 100644
index 00000000000..f92499e6631
--- /dev/null
+++ b/changelog/unreleased/enhancement-access-token-validation.md
@@ -0,0 +1,14 @@
+Enhancement: Improve validation of OIDC access tokens
+
+Previously OIDC access tokes were only validated by requesting the userinfo from
+the IDP. It is now possible to enable additional verification if the IDP issues
+access tokens in JWT format. In that case the oCIS proxy service will now verify
+the signature of the token using the public keys provided by jwks_uri endpoint
+of the IDP. It will also verify if the issuer claim (iss) matches the expected
+values.
+
+The new validation is enabled by setting `PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD`
+to "jwt". Which is also the default. Setting it to "none" will disable the feature.
+
+https://github.com/owncloud/ocis/issues/3841
+https://github.com/owncloud/ocis/pull/4227
diff --git a/changelog/unreleased/update-reva-beta.6.md b/changelog/unreleased/update-reva-beta.6.md
index 98b18edba57..3077ce7b523 100644
--- a/changelog/unreleased/update-reva-beta.6.md
+++ b/changelog/unreleased/update-reva-beta.6.md
@@ -3,5 +3,9 @@ Enhancement: update reva to vx.x.x
 Updated reva to version x.x.x. This update includes:
 
 * TODO:
+
 https://github.com/owncloud/ocis/pull/4272
-https://github.com/cs3org/reva/pull/3096
\ No newline at end of file
+https://github.com/cs3org/reva/pull/3096
+https://github.com/cs3org/reva/pull/4315
+
+https://github.com/owncloud/ocis/pull/4294
diff --git a/changelog/unreleased/update-web-beta.6.md b/changelog/unreleased/update-web-beta.6.md
new file mode 100644
index 00000000000..b928f69459e
--- /dev/null
+++ b/changelog/unreleased/update-web-beta.6.md
@@ -0,0 +1,43 @@
+Enhancement: Update ownCloud Web to v5.7.0-rc.7
+
+Tags: web
+
+We updated ownCloud Web to v5.7.0-rc.7. Please refer to the changelog (linked) for details on the web release.
+
+* Bugfix [owncloud/web#7080](https://github.com/owncloud/web/issues/7080): Add Droparea again
+* Bugfix [owncloud/web#7357](https://github.com/owncloud/web/pull/7357): Batch deleting multiple files
+* Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Decline share not possible
+* Bugfix [owncloud/web#7322](https://github.com/owncloud/web/pull/7322): Files pagination scroll to top
+* Bugfix [owncloud/web#7348](https://github.com/owncloud/web/pull/7348): Left sidebar active navigation item has wrong cursor
+* Bugfix [owncloud/web#7355](https://github.com/owncloud/web/pull/7355): Link indicator on "Shared via link"-page
+* Bugfix [owncloud/web#7325](https://github.com/owncloud/web/pull/7325): Loading state in views
+* Bugfix [owncloud/web#7344](https://github.com/owncloud/web/pull/7344): Missing file icon in details panel
+* Bugfix [owncloud/web#7321](https://github.com/owncloud/web/pull/7321): Missing scroll bar in user management app
+* Bugfix [owncloud/web#7334](https://github.com/owncloud/web/pull/7334): No redirect after disabling space
+* Bugfix [owncloud/web#3071](https://github.com/owncloud/web/issues/3071): Don't leak oidc callback url into browser history
+* Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Open file on shared space resource not possible
+* Bugfix [owncloud/web#7268](https://github.com/owncloud/web/issues/7268): Personal shares leaked into project space
+* Bugfix [owncloud/web#7359](https://github.com/owncloud/web/pull/7359): Fix infinite loading spinner on invalid preview links
+* Bugfix [owncloud/web#7272](https://github.com/owncloud/web/issues/7272): Print backend version
+* Bugfix [owncloud/web#7379](https://github.com/owncloud/web/pull/7379): Rename shared space resource not possible
+* Bugfix [owncloud/web#7210](https://github.com/owncloud/web/pull/7210): Repair navigation highlighter
+* Bugfix [owncloud/web#7308](https://github.com/owncloud/web/pull/7308): "Shared with others" and "Shared via Link" resource links not working
+* Bugfix [owncloud/web#7349](https://github.com/owncloud/web/pull/7349): Missing quick actions in spaces file list
+* Bugfix [owncloud/web#7038](https://github.com/owncloud/web/issues/7038): File list render performance
+* Bugfix [owncloud/web#7240](https://github.com/owncloud/web/issues/7240): Access token renewal during upload
+* Bugfix [owncloud/web#7376](https://github.com/owncloud/web/pull/7376): Tooltips not shown on disabled create and upload button
+* Bugfix [owncloud/web#7297](https://github.com/owncloud/web/pull/7297): Upload overlay progress bar spacing
+* Bugfix [owncloud/web#7332](https://github.com/owncloud/web/pull/7332): Users list not loading if user has no role
+* Bugfix [owncloud/web#7313](https://github.com/owncloud/web/pull/7313): Versions of shared files not visible
+* Enhancement [owncloud/web#7350](https://github.com/owncloud/web/pull/7350): Change file loading mechanism in `preview` app
+* Enhancement [owncloud/web#7356](https://github.com/owncloud/web/pull/7356): Declined shares are now easily accessible
+* Enhancement [owncloud/web#7365](https://github.com/owncloud/web/pull/7365): Drop menu styling in right sidebar
+* Enhancement [owncloud/web#7252](https://github.com/owncloud/web/pull/7252): Redesign shared with list
+* Enhancement [owncloud/web#7371](https://github.com/owncloud/web/pull/7371): Use fixed width for the right sidebar
+* Enhancement [owncloud/web#7267](https://github.com/owncloud/web/pull/7267): Search all files announce limit
+* Enhancement [owncloud/web#7364](https://github.com/owncloud/web/pull/7364): Sharing panel show label instead of description for links
+* Enhancement [owncloud/web#7355](https://github.com/owncloud/web/pull/7355): Update ODS to v14.0.0-alpha.12
+* Enhancement [owncloud/web#7375](https://github.com/owncloud/web/pull/7375): User management app saved dialog
+
+https://github.com/owncloud/ocis/pull/4314
+https://github.com/owncloud/web/releases/tag/v5.7.0-rc.7
diff --git a/go.mod b/go.mod
index d5282be1fca..83b0c7b7162 100644
--- a/go.mod
+++ b/go.mod
@@ -5,18 +5,19 @@ go 1.18
 require (
 	github.com/CiscoM31/godata v1.0.5
 	github.com/Masterminds/semver v1.5.0
+	github.com/MicahParks/keyfunc v1.1.0
 	github.com/ReneKroon/ttlcache/v2 v2.11.0
 	github.com/blevesearch/bleve/v2 v2.3.3
 	github.com/blevesearch/bleve_index_api v1.0.2
 	github.com/coreos/go-oidc/v3 v3.2.0
-	github.com/cs3org/go-cs3apis v0.0.0-20220711084433-8f71d4e812a3
-	github.com/cs3org/reva/v2 v2.7.3-0.20220729123357-51c6d5d0c041
+	github.com/cs3org/go-cs3apis v0.0.0-20220719130120-361e9f987d64
+	github.com/cs3org/reva/v2 v2.7.3-0.20220803070837-28724e42b3f9
 	github.com/disintegration/imaging v1.6.2
 	github.com/ggwhite/go-masker v1.0.9
 	github.com/go-chi/chi/v5 v5.0.7
 	github.com/go-chi/cors v1.2.1
 	github.com/go-chi/render v1.0.1
-	github.com/go-ldap/ldap/v3 v3.4.3
+	github.com/go-ldap/ldap/v3 v3.4.4
 	github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3
 	github.com/go-micro/plugins/v4/client/grpc v1.1.0
 	github.com/go-micro/plugins/v4/events/natsjs v1.1.0
@@ -37,7 +38,7 @@ require (
 	github.com/golang/protobuf v1.5.2
 	github.com/gookit/config/v2 v2.1.2
 	github.com/gorilla/mux v1.8.0
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.0
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.1
 	github.com/justinas/alice v1.2.0
 	github.com/libregraph/idm v0.3.1-0.20220718103124-c4f6613dce2b
 	github.com/libregraph/lico v0.54.1-0.20220325072321-31efc3995d63
@@ -73,9 +74,9 @@ require (
 	golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
 	golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e
 	golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c
-	google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252
+	google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9
 	google.golang.org/grpc v1.48.0
-	google.golang.org/protobuf v1.28.0
+	google.golang.org/protobuf v1.28.1
 	gopkg.in/yaml.v2 v2.4.0
 	gotest.tools/v3 v3.3.0
 	stash.kopano.io/kgol/oidc-go v0.3.4
@@ -84,7 +85,7 @@ require (
 
 require (
 	contrib.go.opencensus.io/exporter/prometheus v0.4.1 // indirect
-	github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
+	github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
 	github.com/BurntSushi/toml v1.2.0 // indirect
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/sprig v2.22.0+incompatible // indirect
diff --git a/go.sum b/go.sum
index a3d9fbc1d71..fd04a1ad9ab 100644
--- a/go.sum
+++ b/go.sum
@@ -83,8 +83,9 @@ github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvd
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
-github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ=
 github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
+github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e h1:NeAW1fUYUEWhft7pkxDf6WoUvEZJ/uOKsvtpjLnn8MU=
+github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
@@ -99,6 +100,8 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q
 github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
 github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
 github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
+github.com/MicahParks/keyfunc v1.1.0 h1:9NcnRwS0ciuVeVNi+vTdYVMTmk62OID7VlG6y9BgLK0=
+github.com/MicahParks/keyfunc v1.1.0/go.mod h1:a4yfunv77gZ0RgTNw7tOYS+bjtHk5565e+1dPz+YJI8=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
 github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
@@ -283,10 +286,10 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo
 github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
 github.com/crewjam/saml v0.4.6 h1:XCUFPkQSJLvzyl4cW9OvpWUbRf0gE7VUpU8ZnilbeM4=
 github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
-github.com/cs3org/go-cs3apis v0.0.0-20220711084433-8f71d4e812a3 h1:QSQ2DGKPMChB4vHSs1Os9TnOJl21BrzKX9D5EtQfDog=
-github.com/cs3org/go-cs3apis v0.0.0-20220711084433-8f71d4e812a3/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
-github.com/cs3org/reva/v2 v2.7.3-0.20220729123357-51c6d5d0c041 h1:ObeKsyxTeYJoPyKqjz6qBjd9Q4kDjT1Fht3lGzOOfdc=
-github.com/cs3org/reva/v2 v2.7.3-0.20220729123357-51c6d5d0c041/go.mod h1:9FpnWdVFw7ld3iOiuzHHQeCyVH/Ct9h03PZV9ZRplPM=
+github.com/cs3org/go-cs3apis v0.0.0-20220719130120-361e9f987d64 h1:cFnankJOCWndnOns4sKRG7yzH61ammK2Am6rEGWCK40=
+github.com/cs3org/go-cs3apis v0.0.0-20220719130120-361e9f987d64/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
+github.com/cs3org/reva/v2 v2.7.3-0.20220803070837-28724e42b3f9 h1:iA067C/zdGMzpRXY0eGu21vFIPVYb0ONHUJbejSZ1B0=
+github.com/cs3org/reva/v2 v2.7.3-0.20220803070837-28724e42b3f9/go.mod h1:AKcCJX2IWLxKGA60eaM7A43nB6urQYuE9phbJabKkm0=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
 github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
@@ -397,8 +400,9 @@ github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw=
 github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
 github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
 github.com/go-ldap/ldap/v3 v3.4.2/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
-github.com/go-ldap/ldap/v3 v3.4.3 h1:JCKUtJPIcyOuG7ctGabLKMgIlKnGumD/iGjuWeEruDI=
 github.com/go-ldap/ldap/v3 v3.4.3/go.mod h1:7LdHfVt6iIOESVEe3Bs4Jp2sHEKgDeduAhgM1/f9qmo=
+github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
+github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
 github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3 h1:sfz1YppV05y4sYaW7kXZtrocU/+vimnIWt4cxAYh7+o=
 github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3/go.mod h1:ZXFhGda43Z2TVbfGZefXyMJzsDHhCh0go3bZUcwTx7o=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -518,6 +522,7 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
 github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
 github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
@@ -652,8 +657,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
 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/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.0 h1:Ghn7copILfeIg0y8sTGRppI1bd8I4l2VN3cob0Xeqwg=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.0/go.mod h1:dnjr4snxnhRSn5GWqJUva2AoMbeaxyAcepvc0Tg8lXk=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.1 h1:/sDbPb60SusIXjiJGYLUoS/rAQurQmvGWmwn2bBPM9c=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.1/go.mod h1:G+WkljZi4mflcqVxYSgvt8MNctRQHjEH8ubKtt1Ka3w=
 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.11.0 h1:Hw/G8TtRvOElqxVIhBzXciiSTbapq8hZ2XKZsXk5ZCE=
@@ -1301,6 +1306,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/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/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1775,8 +1781,8 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2
 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252 h1:G5AjFxR+ibe9Taamo0TdW+iylfBYK10DSkHYdx7PZ9w=
-google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
+google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 h1:d3fKQZK+1rWQMg3xLKQbPMirUCo29I/NRdI2WarSzTg=
+google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1824,8 +1830,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw=
 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
diff --git a/services/graph/mocks/ldapclient.go b/services/graph/mocks/ldapclient.go
index f2c10eb7539..09a57cbc449 100644
--- a/services/graph/mocks/ldapclient.go
+++ b/services/graph/mocks/ldapclient.go
@@ -163,6 +163,20 @@ func (_m *Client) ModifyWithResult(_a0 *ldap.ModifyRequest) (*ldap.ModifyResult,
 	return r0, r1
 }
 
+// NTLMUnauthenticatedBind provides a mock function with given fields: domain, username
+func (_m *Client) NTLMUnauthenticatedBind(domain string, username string) error {
+	ret := _m.Called(domain, username)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(string, string) error); ok {
+		r0 = rf(domain, username)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 // PasswordModify provides a mock function with given fields: _a0
 func (_m *Client) PasswordModify(_a0 *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) {
 	ret := _m.Called(_a0)
@@ -279,6 +293,27 @@ func (_m *Client) StartTLS(_a0 *tls.Config) error {
 	return r0
 }
 
+// TLSConnectionState provides a mock function with given fields:
+func (_m *Client) TLSConnectionState() (tls.ConnectionState, bool) {
+	ret := _m.Called()
+
+	var r0 tls.ConnectionState
+	if rf, ok := ret.Get(0).(func() tls.ConnectionState); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(tls.ConnectionState)
+	}
+
+	var r1 bool
+	if rf, ok := ret.Get(1).(func() bool); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Get(1).(bool)
+	}
+
+	return r0, r1
+}
+
 // UnauthenticatedBind provides a mock function with given fields: username
 func (_m *Client) UnauthenticatedBind(username string) error {
 	ret := _m.Called(username)
@@ -292,3 +327,17 @@ func (_m *Client) UnauthenticatedBind(username string) error {
 
 	return r0
 }
+
+// Unbind provides a mock function with given fields:
+func (_m *Client) Unbind() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
diff --git a/services/graph/pkg/identity/ldap/reconnect.go b/services/graph/pkg/identity/ldap/reconnect.go
index 8a5c405f681..0a4e924743b 100644
--- a/services/graph/pkg/identity/ldap/reconnect.go
+++ b/services/graph/pkg/identity/ldap/reconnect.go
@@ -317,3 +317,18 @@ func (c ConnWithReconnect) Compare(dn, attribute, value string) (bool, error) {
 func (c ConnWithReconnect) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
 	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
 }
+
+// NTLMUnauthenticatedBind implements the ldap.Client interface
+func (c ConnWithReconnect) NTLMUnauthenticatedBind(domain, username string) error {
+	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
+}
+
+// TLSConnectionState implements the ldap.Client interface
+func (c ConnWithReconnect) TLSConnectionState() (tls.ConnectionState, bool) {
+	return tls.ConnectionState{}, false
+}
+
+// Unbind implements the ldap.Client interface
+func (c ConnWithReconnect) Unbind() error {
+	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
+}
diff --git a/services/proxy/pkg/command/server.go b/services/proxy/pkg/command/server.go
index 88a6ed76ffc..5ce0d1373a7 100644
--- a/services/proxy/pkg/command/server.go
+++ b/services/proxy/pkg/command/server.go
@@ -189,6 +189,8 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config)
 			middleware.HTTPClient(oidcHTTPClient),
 			middleware.TokenCacheSize(cfg.OIDC.UserinfoCache.Size),
 			middleware.TokenCacheTTL(time.Second*time.Duration(cfg.OIDC.UserinfoCache.TTL)),
+			middleware.AccessTokenVerifyMethod(cfg.OIDC.AccessTokenVerifyMethod),
+			middleware.JWKSOptions(cfg.OIDC.JWKS),
 
 			// basic Options
 			middleware.Logger(logger),
diff --git a/services/proxy/pkg/config/config.go b/services/proxy/pkg/config/config.go
index 60a881657a3..20f58810312 100644
--- a/services/proxy/pkg/config/config.go
+++ b/services/proxy/pkg/config/config.go
@@ -80,12 +80,28 @@ type AuthMiddleware struct {
 	CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agent"`
 }
 
+const (
+	AccessTokenVerificationNone = "none"
+	AccessTokenVerificationJWT  = "jwt"
+	// tdb:
+	// AccessTokenVerificationIntrospect = "introspect"
+)
+
 // OIDC is the config for the OpenID-Connect middleware. If set the proxy will try to authenticate every request
 // with the configured oidc-provider
 type OIDC struct {
-	Issuer        string        `yaml:"issuer" env:"OCIS_URL;OCIS_OIDC_ISSUER;PROXY_OIDC_ISSUER" desc:"URL of the OIDC issuer. It defaults to URL of the builtin IDP."`
-	Insecure      bool          `yaml:"insecure" env:"OCIS_INSECURE;PROXY_OIDC_INSECURE" desc:"Disable TLS certificate validation for connections to the IDP. Note that this is not recommended for production environments."`
-	UserinfoCache UserinfoCache `yaml:"user_info_cache"`
+	Issuer                  string        `yaml:"issuer" env:"OCIS_URL;OCIS_OIDC_ISSUER;PROXY_OIDC_ISSUER" desc:"URL of the OIDC issuer. It defaults to URL of the builtin IDP."`
+	Insecure                bool          `yaml:"insecure" env:"OCIS_INSECURE;PROXY_OIDC_INSECURE" desc:"Disable TLS certificate validation for connections to the IDP. Note that this is not recommended for production environments."`
+	AccessTokenVerifyMethod string        `yaml:"access_token_verify_method" env:"PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD" desc:"Sets how OIDC access tokens should be verified. Possible values are 'none' and 'jwt'. When using 'none', no special validation apart from using it for accessing the IPD's userinfo endpoint will be done. When using 'jwt', it tries to parse the access token as a jwt token and verifies the signature using the keys published on the IDP's 'jwks_uri'."`
+	UserinfoCache           UserinfoCache `yaml:"user_info_cache"`
+	JWKS                    JWKS          `yaml:"jwks"`
+}
+
+type JWKS struct {
+	RefreshInterval   uint64 `yaml:"refresh_interval" env:"PROXY_OIDC_JWKS_REFRESH_INTERVAL" desc:"The interval for refreshing the JWKS (JSON Web Key Set) in minutes in the background via a new HTTP request to the IDP."`
+	RefreshTimeout    uint64 `yaml:"refresh_timeout" env:"PROXY_OIDC_JWKS_REFRESH_TIMEOUT" desc:"The timeout in seconds for an outgoing JWKS request."`
+	RefreshRateLimit  uint64 `yaml:"refresh_limit" env:"PROXY_OIDC_JWKS_REFRESH_RATE_LIMIT" desc:"Limits the rate in seconds at which refresh requests are performed for unknown keys. This is used to prevent malicious clients from imposing high network load on the IDP via ocis."`
+	RefreshUnknownKID bool   `yaml:"refresh_unknown_kid" env:"PROXY_OIDC_JWKS_REFRESH_UNKNOWN_KID" desc:"If set to 'true', the JWKS refresh request will occur every time an unknown KEY ID (KID) is seen. Always set a 'refresh_limit' when enabling this."`
 }
 
 // UserinfoCache is a TTL cache configuration.
diff --git a/services/proxy/pkg/config/defaults/defaultconfig.go b/services/proxy/pkg/config/defaults/defaultconfig.go
index 708fef8eff8..1c6f8489348 100644
--- a/services/proxy/pkg/config/defaults/defaultconfig.go
+++ b/services/proxy/pkg/config/defaults/defaultconfig.go
@@ -36,10 +36,17 @@ func DefaultConfig() *config.Config {
 			Issuer:   "https://localhost:9200",
 			Insecure: true,
 			//Insecure: true,
+			AccessTokenVerifyMethod: config.AccessTokenVerificationJWT,
 			UserinfoCache: config.UserinfoCache{
 				Size: 1024,
 				TTL:  10,
 			},
+			JWKS: config.JWKS{
+				RefreshInterval:   60, // minutes
+				RefreshRateLimit:  60, // seconds
+				RefreshTimeout:    10, // seconds
+				RefreshUnknownKID: true,
+			},
 		},
 		PolicySelector: nil,
 		Reva: &config.Reva{
diff --git a/services/proxy/pkg/config/parser/parse.go b/services/proxy/pkg/config/parser/parse.go
index 14218d9e8e9..877f95ee9fe 100644
--- a/services/proxy/pkg/config/parser/parse.go
+++ b/services/proxy/pkg/config/parser/parse.go
@@ -2,6 +2,7 @@ package parser
 
 import (
 	"errors"
+	"fmt"
 
 	ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config"
 	"github.com/owncloud/ocis/v2/ocis-pkg/shared"
@@ -41,5 +42,14 @@ func Validate(cfg *config.Config) error {
 		return shared.MissingMachineAuthApiKeyError(cfg.Service.Name)
 	}
 
+	if cfg.OIDC.AccessTokenVerifyMethod != config.AccessTokenVerificationNone &&
+		cfg.OIDC.AccessTokenVerifyMethod != config.AccessTokenVerificationJWT {
+		return fmt.Errorf(
+			"Invalid value '%s' for 'access_token_verify_method' in service %s. Possible values are: '%s' or '%s'.",
+			cfg.OIDC.AccessTokenVerifyMethod, cfg.Service.Name,
+			config.AccessTokenVerificationJWT, config.AccessTokenVerificationNone,
+		)
+	}
+
 	return nil
 }
diff --git a/services/proxy/pkg/middleware/authentication.go b/services/proxy/pkg/middleware/authentication.go
index f8476a67bc1..15fa4ec4299 100644
--- a/services/proxy/pkg/middleware/authentication.go
+++ b/services/proxy/pkg/middleware/authentication.go
@@ -115,6 +115,8 @@ func newOIDCAuth(options Options) func(http.Handler) http.Handler {
 		TokenCacheSize(options.UserinfoCacheSize),
 		TokenCacheTTL(options.UserinfoCacheTTL),
 		CredentialsByUserAgent(options.CredentialsByUserAgent),
+		AccessTokenVerifyMethod(options.AccessTokenVerifyMethod),
+		JWKSOptions(options.JWKS),
 	)
 }
 
diff --git a/services/proxy/pkg/middleware/oidc_auth.go b/services/proxy/pkg/middleware/oidc_auth.go
index 8fedb3c2f4f..ae3b313f086 100644
--- a/services/proxy/pkg/middleware/oidc_auth.go
+++ b/services/proxy/pkg/middleware/oidc_auth.go
@@ -2,14 +2,21 @@ package middleware
 
 import (
 	"context"
+	"encoding/json"
+	"errors"
+	"io/ioutil"
 	"net/http"
 	"strings"
+	"sync"
 	"time"
 
+	"github.com/MicahParks/keyfunc"
 	gOidc "github.com/coreos/go-oidc/v3/oidc"
+	"github.com/golang-jwt/jwt/v4"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
 	"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
-	"github.com/owncloud/ocis/v2/ocis-pkg/sync"
+	osync "github.com/owncloud/ocis/v2/ocis-pkg/sync"
+	"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
 	"golang.org/x/oauth2"
 )
 
@@ -21,15 +28,19 @@ type OIDCProvider interface {
 // OIDCAuth provides a middleware to check access secured by a static token.
 func OIDCAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
 	options := newOptions(optionSetters...)
-	tokenCache := sync.NewCache(options.UserinfoCacheSize)
+	tokenCache := osync.NewCache(options.UserinfoCacheSize)
 
 	h := oidcAuth{
-		logger:        options.Logger,
-		providerFunc:  options.OIDCProviderFunc,
-		httpClient:    options.HTTPClient,
-		oidcIss:       options.OIDCIss,
-		tokenCache:    &tokenCache,
-		tokenCacheTTL: options.UserinfoCacheTTL,
+		logger:                  options.Logger,
+		providerFunc:            options.OIDCProviderFunc,
+		httpClient:              options.HTTPClient,
+		oidcIss:                 options.OIDCIss,
+		tokenCache:              &tokenCache,
+		tokenCacheTTL:           options.UserinfoCacheTTL,
+		accessTokenVerifyMethod: options.AccessTokenVerifyMethod,
+		jwksOptions:             options.JWKS,
+		jwksLock:                &sync.Mutex{},
+		providerLock:            &sync.Mutex{},
 	}
 
 	return func(next http.Handler) http.Handler {
@@ -47,6 +58,12 @@ func OIDCAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
 				return
 			}
 
+			// Force init of jwks keyfunc if needed (contacts the .well-known and jwks endpoints on first call)
+			if h.accessTokenVerifyMethod == config.AccessTokenVerificationJWT && h.getKeyfunc() == nil {
+				w.WriteHeader(http.StatusInternalServerError)
+				return
+			}
+
 			token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ")
 
 			claims, status := h.getClaims(token, req)
@@ -62,19 +79,30 @@ func OIDCAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
 }
 
 type oidcAuth struct {
-	logger        log.Logger
-	provider      OIDCProvider
-	providerFunc  func() (OIDCProvider, error)
-	httpClient    *http.Client
-	oidcIss       string
-	tokenCache    *sync.Cache
-	tokenCacheTTL time.Duration
+	logger                  log.Logger
+	provider                OIDCProvider
+	providerLock            *sync.Mutex
+	jwksOptions             config.JWKS
+	jwks                    *keyfunc.JWKS
+	jwksLock                *sync.Mutex
+	providerFunc            func() (OIDCProvider, error)
+	httpClient              *http.Client
+	oidcIss                 string
+	tokenCache              *osync.Cache
+	tokenCacheTTL           time.Duration
+	accessTokenVerifyMethod string
 }
 
 func (m oidcAuth) getClaims(token string, req *http.Request) (claims map[string]interface{}, status int) {
 	hit := m.tokenCache.Load(token)
 	if hit == nil {
-		// TODO cache userinfo for access token if we can determine the expiry (which works in case it is a jwt based access token)
+		aClaims, err := m.verifyAccessToken(token)
+		if err != nil {
+			m.logger.Error().Err(err).Msg("Failed to verify access token")
+			status = http.StatusUnauthorized
+			return
+		}
+
 		oauth2Token := &oauth2.Token{
 			AccessToken: token,
 		}
@@ -95,7 +123,7 @@ func (m oidcAuth) getClaims(token string, req *http.Request) (claims map[string]
 			return
 		}
 
-		expiration := m.extractExpiration(token)
+		expiration := m.extractExpiration(aClaims)
 		m.tokenCache.Store(token, claims, expiration)
 
 		m.logger.Debug().Interface("claims", claims).Interface("userInfo", userInfo).Time("expiration", expiration.UTC()).Msg("unmarshalled and cached userinfo")
@@ -111,20 +139,53 @@ func (m oidcAuth) getClaims(token string, req *http.Request) (claims map[string]
 	return
 }
 
-// extractExpiration currently just returns a hardcoded default for now. It was
-// supposed to parse and extract the expiration time from the provided
-// access_token.
-// As the access_token is defined as an opaque string. Validating and parsing it
-// can be tricky:
-// 1. Try to treat it as a JWT:
-//    - Verifying the validity of the token requires downloading the propoer public
-//      key from the IDP (uri in "jwks_uri" in ".well-known/openid-configuration"
-// 2. Verify and extract it via the introspection endpoint of the IDP (RFC7662) for
-//    IDPs that provide that feature
-// 3. Other IDP implementation specific methods.
-// 4. Fallback to default value
-func (m oidcAuth) extractExpiration(token string) time.Time {
+func (m oidcAuth) verifyAccessToken(token string) (jwt.RegisteredClaims, error) {
+	switch m.accessTokenVerifyMethod {
+	case config.AccessTokenVerificationJWT:
+		return m.verifyAccessTokenJWT(token)
+	case config.AccessTokenVerificationNone:
+		m.logger.Debug().Msg("Access Token verification disabled")
+		return jwt.RegisteredClaims{}, nil
+	default:
+		m.logger.Error().Str("access_token_verify_method", m.accessTokenVerifyMethod).Msg("Unknown Access Token verification setting")
+		return jwt.RegisteredClaims{}, errors.New("Unknown Access Token Verification method")
+	}
+}
+
+// verifyAccessTokenJWT tries to parse and verify the access token as a JWT.
+func (m oidcAuth) verifyAccessTokenJWT(token string) (jwt.RegisteredClaims, error) {
+	var claims jwt.RegisteredClaims
+	jwks := m.getKeyfunc()
+	if jwks == nil {
+		return claims, errors.New("Error initializing jwks keyfunc")
+	}
+
+	_, err := jwt.ParseWithClaims(token, &claims, jwks.Keyfunc)
+	m.logger.Debug().Interface("access token", &claims).Msg("parsed access token")
+	if err != nil {
+		m.logger.Info().Err(err).Msg("Failed to parse/verify the access token.")
+		return claims, err
+	}
+
+	if !claims.VerifyIssuer(m.oidcIss, true) {
+		vErr := jwt.ValidationError{}
+		vErr.Inner = jwt.ErrTokenInvalidIssuer
+		vErr.Errors |= jwt.ValidationErrorIssuer
+		return claims, vErr
+	}
+
+	return claims, nil
+}
+
+// extractExpiration tries to extract the expriration time from the access token
+// If the access token does not have an exp claim it will fallback to the configured
+// default expiration
+func (m oidcAuth) extractExpiration(aClaims jwt.RegisteredClaims) time.Time {
 	defaultExpiration := time.Now().Add(m.tokenCacheTTL)
+	if aClaims.ExpiresAt != nil {
+		m.logger.Debug().Str("exp", aClaims.ExpiresAt.String()).Msg("Expiration Time from access_token")
+		return aClaims.ExpiresAt.Time
+	}
 	return defaultExpiration
 }
 
@@ -146,7 +207,64 @@ func (m oidcAuth) shouldServe(req *http.Request) bool {
 	return strings.HasPrefix(header, "Bearer ")
 }
 
+type jwksJSON struct {
+	JWKSURL string `json:"jwks_uri"`
+}
+
+func (m *oidcAuth) getKeyfunc() *keyfunc.JWKS {
+	m.jwksLock.Lock()
+	defer m.jwksLock.Unlock()
+	if m.jwks == nil {
+		wellKnown := strings.TrimSuffix(m.oidcIss, "/") + "/.well-known/openid-configuration"
+
+		resp, err := m.httpClient.Get(wellKnown)
+		if err != nil {
+			m.logger.Error().Err(err).Msg("Failed to set request for .well-known/openid-configuration")
+			return nil
+		}
+		defer resp.Body.Close()
+
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			m.logger.Error().Err(err).Msg("unable to read discovery response body")
+			return nil
+		}
+
+		if resp.StatusCode != http.StatusOK {
+			m.logger.Error().Str("status", resp.Status).Str("body", string(body)).Msg("error requesting openid-configuration")
+			return nil
+		}
+
+		var j jwksJSON
+		err = json.Unmarshal(body, &j)
+		if err != nil {
+			m.logger.Error().Err(err).Msg("failed to decode provider openid-configuration")
+			return nil
+		}
+		m.logger.Debug().Str("jwks", j.JWKSURL).Msg("discovered jwks endpoint")
+		options := keyfunc.Options{
+			Client: m.httpClient,
+			RefreshErrorHandler: func(err error) {
+				m.logger.Error().Err(err).Msg("There was an error with the jwt.Keyfunc")
+			},
+			RefreshInterval:   time.Minute * time.Duration(m.jwksOptions.RefreshInterval),
+			RefreshRateLimit:  time.Second * time.Duration(m.jwksOptions.RefreshRateLimit),
+			RefreshTimeout:    time.Second * time.Duration(m.jwksOptions.RefreshTimeout),
+			RefreshUnknownKID: m.jwksOptions.RefreshUnknownKID,
+		}
+		m.jwks, err = keyfunc.Get(j.JWKSURL, options)
+		if err != nil {
+			m.jwks = nil
+			m.logger.Error().Err(err).Msg("Failed to create JWKS from resource at the given URL.")
+			return nil
+		}
+	}
+	return m.jwks
+}
+
 func (m *oidcAuth) getProvider() OIDCProvider {
+	m.providerLock.Lock()
+	defer m.providerLock.Unlock()
 	if m.provider == nil {
 		// Lazily initialize a provider
 
diff --git a/services/proxy/pkg/middleware/options.go b/services/proxy/pkg/middleware/options.go
index 63994ee8e41..2d07b2b772f 100644
--- a/services/proxy/pkg/middleware/options.go
+++ b/services/proxy/pkg/middleware/options.go
@@ -55,6 +55,11 @@ type Options struct {
 	UserinfoCacheTTL time.Duration
 	// CredentialsByUserAgent sets the auth challenges on a per user-agent basis
 	CredentialsByUserAgent map[string]string
+	// AccessTokenVerifyMethod configures how access_tokens should be verified but the oidc_auth middleware.
+	// Possible values currently: "jwt" and "none"
+	AccessTokenVerifyMethod string
+	// JWKS sets the options for fetching the JWKS from the IDP
+	JWKS config.JWKS
 }
 
 // newOptions initializes the available default options.
@@ -193,3 +198,17 @@ func UserProvider(up backend.UserBackend) Option {
 		o.UserProvider = up
 	}
 }
+
+// AccessTokenVerifyMethod set the mechanism for access token verification
+func AccessTokenVerifyMethod(method string) Option {
+	return func(o *Options) {
+		o.AccessTokenVerifyMethod = method
+	}
+}
+
+// JWKS sets the options for fetching the JWKS from the IDP
+func JWKSOptions(jo config.JWKS) Option {
+	return func(o *Options) {
+		o.JWKS = jo
+	}
+}
diff --git a/services/web/Makefile b/services/web/Makefile
index 59725007153..0e8f5eb67b9 100644
--- a/services/web/Makefile
+++ b/services/web/Makefile
@@ -1,6 +1,6 @@
 SHELL := bash
 NAME := web
-WEB_ASSETS_VERSION = v5.7.0-rc.5
+WEB_ASSETS_VERSION = v5.7.0-rc.7
 
 include ../../.make/recursion.mk
 


Test patch:
diff --git a/services/graph/pkg/identity/ldap_test.go b/services/graph/pkg/identity/ldap_test.go
index 87d0b171627..7db012edbf4 100644
--- a/services/graph/pkg/identity/ldap_test.go
+++ b/services/graph/pkg/identity/ldap_test.go
@@ -2,29 +2,19 @@ package identity
 
 import (
 	"context"
-	"crypto/tls"
 	"errors"
-	"fmt"
 	"net/url"
 	"testing"
-	"time"
 
 	"github.com/go-ldap/ldap/v3"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
+	"github.com/owncloud/ocis/v2/services/graph/mocks"
 	"github.com/owncloud/ocis/v2/services/graph/pkg/config"
+	"github.com/test-go/testify/mock"
 )
 
-// ldapMock implements the ldap.Client interfac
-type ldapMock struct {
-	SearchFunc *searchFunc
-}
-
-type searchFunc func(*ldap.SearchRequest) (*ldap.SearchResult, error)
-
-func getMockedBackend(sf *searchFunc, lc config.LDAP, logger *log.Logger) (*LDAP, error) {
-	// Mock a Sizelimit Error
-	lm := ldapMock{SearchFunc: sf}
-	return NewLDAPBackend(lm, lconfig, logger)
+func getMockedBackend(l ldap.Client, lc config.LDAP, logger *log.Logger) (*LDAP, error) {
+	return NewLDAPBackend(l, lconfig, logger)
 }
 
 var lconfig = config.LDAP{
@@ -60,7 +50,7 @@ var logger = log.NewLogger(log.Level("debug"))
 
 func TestNewLDAPBackend(t *testing.T) {
 
-	l := ldapMock{}
+	l := &mocks.Client{}
 
 	tc := lconfig
 	tc.UserDisplayNameAttribute = ""
@@ -93,7 +83,7 @@ func TestNewLDAPBackend(t *testing.T) {
 }
 
 func TestCreateUserModelFromLDAP(t *testing.T) {
-	l := ldapMock{}
+	l := &mocks.Client{}
 	logger := log.NewLogger(log.Level("debug"))
 
 	b, _ := NewLDAPBackend(l, lconfig, &logger)
@@ -121,10 +111,12 @@ func TestCreateUserModelFromLDAP(t *testing.T) {
 
 func TestGetUser(t *testing.T) {
 	// Mock a Sizelimit Error
-	var sf searchFunc = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock"))
-	}
-	b, _ := getMockedBackend(&sf, lconfig, &logger)
+	lm := &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(
+			nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock")))
+	b, _ := getMockedBackend(lm, lconfig, &logger)
 
 	queryParamExpand := url.Values{
 		"$expand": []string{"memberOf"},
@@ -148,10 +140,12 @@ func TestGetUser(t *testing.T) {
 	}
 
 	// Mock an empty Search Result
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(
+			&ldap.SearchResult{}, nil)
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	_, err = b.GetUser(context.Background(), "fred", nil)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
@@ -168,12 +162,16 @@ func TestGetUser(t *testing.T) {
 	}
 
 	// Mock a valid	Search Result
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{
-			Entries: []*ldap.Entry{userEntry},
-		}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(
+			&ldap.SearchResult{
+				Entries: []*ldap.Entry{userEntry},
+			},
+			nil)
+
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	u, err := b.GetUser(context.Background(), "user", nil)
 	if err != nil {
 		t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
@@ -197,19 +195,23 @@ func TestGetUser(t *testing.T) {
 }
 
 func TestGetUsers(t *testing.T) {
-	var sf searchFunc = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return nil, ldap.NewError(ldap.LDAPResultOperationsError, errors.New("mock"))
-	}
-	b, _ := getMockedBackend(&sf, lconfig, &logger)
+	// Mock a Sizelimit Error
+	lm := &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(nil, ldap.NewError(ldap.LDAPResultOperationsError, errors.New("mock")))
+
+	b, _ := getMockedBackend(lm, lconfig, &logger)
 	_, err := b.GetUsers(context.Background(), url.Values{})
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
 
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(&ldap.SearchResult{}, nil)
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	g, err := b.GetUsers(context.Background(), url.Values{})
 	if err != nil {
 		t.Errorf("Expected success, got '%s'", err.Error())
@@ -220,16 +222,18 @@ func TestGetUsers(t *testing.T) {
 
 func TestGetGroup(t *testing.T) {
 	// Mock a Sizelimit Error
-	var sf searchFunc = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock"))
-	}
+	lm := &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		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)
+	b, _ := getMockedBackend(lm, lconfig, &logger)
 	_, err := b.GetGroup(context.Background(), "group", nil)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
@@ -244,10 +248,11 @@ func TestGetGroup(t *testing.T) {
 	}
 
 	// Mock an empty Search Result
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(&ldap.SearchResult{}, nil)
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	_, err = b.GetGroup(context.Background(), "group", nil)
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
@@ -262,12 +267,13 @@ func TestGetGroup(t *testing.T) {
 	}
 
 	// Mock a valid	Search Result
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(&ldap.SearchResult{
 			Entries: []*ldap.Entry{groupEntry},
-		}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+		}, nil)
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	g, err := b.GetGroup(context.Background(), "group", nil)
 	if err != nil {
 		t.Errorf("Expected GetGroup to succeed. Got %s", err.Error())
@@ -289,19 +295,21 @@ func TestGetGroup(t *testing.T) {
 }
 
 func TestGetGroups(t *testing.T) {
-	var sf searchFunc = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return nil, ldap.NewError(ldap.LDAPResultOperationsError, errors.New("mock"))
-	}
-	b, _ := getMockedBackend(&sf, lconfig, &logger)
+	lm := &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(nil, ldap.NewError(ldap.LDAPResultOperationsError, errors.New("mock")))
+	b, _ := getMockedBackend(lm, lconfig, &logger)
 	_, err := b.GetGroups(context.Background(), url.Values{})
 	if err == nil || err.Error() != "itemNotFound" {
 		t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
 	}
 
-	sf = func(*ldap.SearchRequest) (*ldap.SearchResult, error) {
-		return &ldap.SearchResult{}, nil
-	}
-	b, _ = getMockedBackend(&sf, lconfig, &logger)
+	lm = &mocks.Client{}
+	lm.On("Search", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
+		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
+		Return(&ldap.SearchResult{}, nil)
+	b, _ = getMockedBackend(lm, lconfig, &logger)
 	g, err := b.GetGroups(context.Background(), url.Values{})
 	if err != nil {
 		t.Errorf("Expected success, got '%s'", err.Error())
@@ -309,74 +317,3 @@ func TestGetGroups(t *testing.T) {
 		t.Errorf("Expected zero length user slice")
 	}
 }
-
-// below here ldap.Client interface method for ldapMock
-
-func (c ldapMock) Start() {}
-
-func (c ldapMock) StartTLS(*tls.Config) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Close() {}
-
-func (c ldapMock) IsClosing() bool {
-	return false
-}
-
-func (c ldapMock) SetTimeout(time.Duration) {}
-
-func (c ldapMock) Bind(username, password string) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) UnauthenticatedBind(username string) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) SimpleBind(*ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error) {
-	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) ExternalBind() error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Add(*ldap.AddRequest) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Del(*ldap.DelRequest) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Modify(*ldap.ModifyRequest) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) ModifyDN(*ldap.ModifyDNRequest) error {
-	return ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) ModifyWithResult(*ldap.ModifyRequest) (*ldap.ModifyResult, error) {
-	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Compare(dn, attribute, value string) (bool, error) {
-	return false, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) PasswordModify(*ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) {
-	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-
-func (c ldapMock) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
-	if c.SearchFunc != nil {
-		return (*c.SearchFunc)(searchRequest)
-	}
-
-	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
-func (c ldapMock) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
-	return nil, ldap.NewError(ldap.LDAPResultNotSupported, fmt.Errorf("not implemented"))
-}
diff --git a/services/proxy/pkg/middleware/oidc_auth_test.go b/services/proxy/pkg/middleware/oidc_auth_test.go
index 33045101bea..6b7e97bceb5 100644
--- a/services/proxy/pkg/middleware/oidc_auth_test.go
+++ b/services/proxy/pkg/middleware/oidc_auth_test.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/coreos/go-oidc/v3/oidc"
 	"github.com/owncloud/ocis/v2/ocis-pkg/log"
+	"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
 	"golang.org/x/oauth2"
 )
 
@@ -21,6 +22,7 @@ func TestOIDCAuthMiddleware(t *testing.T) {
 			return mockOP(false), nil
 		}),
 		OIDCIss("https://localhost:9200"),
+		AccessTokenVerifyMethod(config.AccessTokenVerificationNone),
 	)(next)
 
 	r := httptest.NewRequest(http.MethodGet, "https://idp.example.com", nil)
diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
index 53ea58b38fc..39900e8cfbb 100644
--- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
+++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
@@ -38,8 +38,3 @@ The expected failures in this file are from features in the owncloud/ocis repo.
 - [apiSpaces/moveSpaces.feature:185](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/moveSpaces.feature#L185)
 - [apiSpaces/moveSpaces.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/moveSpaces.feature#L186)
 - [apiSpaces/moveSpaces.feature:189](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/moveSpaces.feature#L189)
-
-### [User without space manager role cannot restore space](https://github.com/owncloud/ocis/issues/4027)
- - [apiSpaces/restoreSpaces.feature:63](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/restoreSpaces.feature#L63)
- - [apiSpaces/restoreSpaces.feature:64](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/restoreSpaces.feature#L64)
-
diff --git a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md
index 59d3cd7146b..139e804d06e 100644
--- a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md
+++ b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md
@@ -56,33 +56,11 @@ Other free text and markdown formatting can be used elsewhere in the document if
 - [webUIRestrictSharing/restrictSharing.feature:40](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIRestrictSharing/restrictSharing.feature#L40)
 - [webUIRestrictSharing/restrictSharing.feature:56](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIRestrictSharing/restrictSharing.feature#L56)
 
-### [Searching sharee with displayname](https://github.com/owncloud/ocis/issues/547)
-- [webUISharingAutocompletion/shareAutocompletion.feature:128](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L128)
-- [webUISharingAutocompletion/shareAutocompletion.feature:141](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L141)
-
-### [No occ command in ocis](https://github.com/owncloud/ocis/issues/1317)
-### [Searching sharee with displayname](https://github.com/owncloud/ocis/issues/547)
-- [webUISharingAutocompletion/shareAutocompletion.feature:76](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L76)
-- [webUISharingAutocompletion/shareAutocompletion.feature:115](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L115)
-- [webUISharingAutocompletion/shareAutocompletion.feature:154](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L154)
-- [webUISharingAutocompletion/shareAutocompletion.feature:168](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L168)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:55](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L55)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:56](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L56)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:73](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L73)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:74](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L74)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:75](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L75)
-
-### [Minimum of three characters required for autocompletion](https://github.com/owncloud/ocis/issues/1961)
-- [webUISharingAutocompletion/shareAutocompletion.feature:32](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L32)
-- [webUISharingAutocompletion/shareAutocompletion.feature:44](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L44)
-- [webUISharingAutocompletion/shareAutocompletion.feature:87](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L87)
-- [webUISharingAutocompletion/shareAutocompletion.feature:101](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L101)
-
 ### [Cannot create users with special characters](https://github.com/owncloud/ocis/issues/1417)
-- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:36](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L36)
 - [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:37](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L37)
 - [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:38](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L38)
 - [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:39](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L39)
+- [webUISharingAutocompletion/shareAutocompletionSpecialChars.feature:40](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletionSpecialChars.feature#L40)
 
 ### [No occ command in ocis](https://github.com/owncloud/ocis/issues/1317)
 - [webUISharingInternalUsersBlacklisted/shareWithUsers.feature:16](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalUsersBlacklisted/shareWithUsers.feature#L16)
@@ -151,11 +129,11 @@ Other free text and markdown formatting can be used elsewhere in the document if
 - [webUIComments/comments.feature:40](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIComments/comments.feature#L40)
 - [webUIComments/comments.feature:41](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIComments/comments.feature#L41)
 - [webUIComments/comments.feature:42](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIComments/comments.feature#L42)
-- [webUIFilesDetails/fileDetails.feature:74](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L74)
 - [webUIFilesDetails/fileDetails.feature:90](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L90)
-- [webUIFilesDetails/fileDetails.feature:107](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L107)
-- [webUIFilesDetails/fileDetails.feature:124](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L124)
-- [webUIFilesDetails/fileDetails.feature:153](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L153)
+- [webUIFilesDetails/fileDetails.feature:106](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L106)
+- [webUIFilesDetails/fileDetails.feature:123](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L123)
+- [webUIFilesDetails/fileDetails.feature:140](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L140)
+- [webUIFilesDetails/fileDetails.feature:169](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L169)
 
 ### [Deletion of a recursive folder from trashbin is not possible](https://github.com/owncloud/product/issues/188)
 - [webUITrashbinDelete/trashbinDelete.feature:85](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUITrashbinDelete/trashbinDelete.feature#L85)
@@ -298,8 +276,8 @@ Other free text and markdown formatting can be used elsewhere in the document if
 - [webUIUpload/upload.feature:42](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIUpload/upload.feature#L42)
 
 ### [Favorites deactivated in ocis temporarily](https://github.com/owncloud/ocis/issues/1228)
-- [webUIFilesDetails/fileDetails.feature:42](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L42)
-- [webUIFilesDetails/fileDetails.feature:57](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L57)
+- [webUIFilesDetails/fileDetails.feature:50](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L50)
+- [webUIFilesDetails/fileDetails.feature:70](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFilesDetails/fileDetails.feature#L70)
 - [webUIRenameFiles/renameFiles.feature:257](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIRenameFiles/renameFiles.feature#L257)
 
 ### [Copy/move not possible from and into shares in oCIS](https://github.com/owncloud/web/issues/6892)