Skip to content

Conversation

@cbcoutinho
Copy link

@cbcoutinho cbcoutinho commented Oct 12, 2025

When using Bearer token authentication with OIDC, API requests to endpoints with @CORS annotations (like Notes API) were failing with 401 Unauthorized errors. This occurred because:

  1. Bearer token validation successfully authenticated the user
  2. A session was created for the authenticated user
  3. Nextcloud's CORSMiddleware detected the logged-in session but no
    CSRF token, causing it to call session->logout()
  4. The logout invalidated the session, breaking the API request

This fix sets the 'app_api' session flag during Bearer token authentication, which instructs CORSMiddleware to skip the CSRF check and logout logic. This is the same mechanism used by Nextcloud's AppAPI framework for external application authentication.

The flag is set at all successful Bearer token authentication points:

  • Line 243: After OIDC Identity Provider validation
  • Line 310: After auto-provisioning with bearer provisioning
  • Line 315: After existing user authentication
  • Line 337: After LDAP user sync

Fixes: #836 regarding enabling OIDC for non-OCS endpoints like Notes app, etc.

@julien-nc
Copy link
Member

Thanks for the fix suggestion. We are discussing it.

So the problematic case is an ApiController using the #[CORS] method attribute like in https://github.com/nextcloud/notes/blob/main/lib/Controller/NotesApiController.php .

So if i understand correctly, the problem is that even requests (to the Notes app API for example) that are NOT made by a browser (but with CURL for example) will fail. Right @cbcoutinho ?

@cbcoutinho
Copy link
Author

cbcoutinho commented Oct 13, 2025

Hi @julien-nc, yes - that's correct.

In my limited investigation, it appears that any request to a non-OCS endpoint outside of a browser is rejected.

It's my understanding that this is because the CORSMiddleware.php class logs out users that do not have a CSRF token - see:
/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php

The app_api session flag is the established Nextcloud pattern for API-based authentication. It's used throughout core to distinguish API authentication from browser sessions. Key examples:

This ensures Bearer token authentication works with @CORS endpoints (like Notes API) without triggering browser-specific security checks like CSRF, which don't apply to token-based API requests.

@cbcoutinho cbcoutinho force-pushed the fix/bearer-auth-cors-session-logout branch from deab2da to 824c926 Compare October 13, 2025 16:14
@cbcoutinho cbcoutinho changed the title Fix Bearer token authentication causing session logout Fix Bearer token authentication for non-OCS endpoints Oct 16, 2025
@edward-ly
Copy link
Contributor

Hello, FYI @julien-nc is currently on vacation until Oct. 28, so unfortunately, discussions are on hold until then.

Pro tip: in the meantime, for a cleaner commit history, we'd suggest rebasing your branch so that the base is up-to-date with main (rather than having multiple empty merge commits):

git checkout main
git pull
git checkout fix/bearer-auth-cors-session-logout
git rebase main
git push -f

@cbcoutinho cbcoutinho force-pushed the fix/bearer-auth-cors-session-logout branch from 2b24387 to 5ee3e7f Compare October 20, 2025 09:13
@cbcoutinho
Copy link
Author

Thanks for the update @edward-ly - no rush.

I'll maintain this branch and make sure that it is rebased on main until the PR is merged or closed.

@oleksandr-nc
Copy link

Cons/risks of current solution:

  • Scope of app_api: it also disables 2FA checks for the session and remove AppAPI requests from rate limiting. Using it for OIDC API calls is functionally consistent with app passwords/external apps, but it is broader than "just skip CORSMiddleware logout"
  • Session semantics: if browser ends up reusing that session cookie, the session is now an API session skipping 2FA. In practice, modern browsers should third‑party cookie use and most API clients do not send browser cookies, but this is a theoretical thing to be aware of (server code specifically checks the session flag, not the presence of cookies)
  • Tight coupling to AppAPI naming: app_api flag was introduced for ExApps. Reusing it for OIDC Bearer is pragmatic, but semantically it is two different concepts.

Solutions I can propose:

  1. Extend CORSMiddleware to also accept Bearer auth (without relying on app_api). Somewhere in CORSMiddleware::beforeController() if the route has #[CORS] and the request has Authorization: Bearer ..., add the skip of basic‑auth fallback/logout. (motivation/inspiration will be how SecurityMiddleware already done)

    Server issues about this: [Bug]: "CORS requires basic auth" error when authenticating with OIDC token server#44365

  2. Add route attribute (e.g., #[TokenAuthAllowed]) and honor it in CORSMiddleware

    Rather than wide Bearer allowed on all #[CORS], introduce explicit attribute that apps can add where Bearer should be accepted without CSRF/Basic.

  3. Create separate flag recognized by CORSMiddleware/SecurityMiddleware that bypasses CSRF for CORS routes like app_api does, but does not inherit all AppAPI semantics.

  4. Change apps (e.g., Notes) to expose OCS wrappers for their APIs (OCS already treats Bearer as valid)

I lean towards point 4 as the most conceptual cleanest one. Except point 4 I like the point 2.

@cbcoutinho
Copy link
Author

cbcoutinho commented Oct 21, 2025

Thanks for the overview @oleksandr-nc, I've been learning a lot about how Nextcloud handles auth via these PRs, and I appreciate your response.

My preference (beyond this PR) would be your first solution - allow Bearer tokens to bypass CORS check within the Nextcloud server itself. To facilitate the discussion, I've opened PR nextcloud/server#55878

When using Bearer token authentication with OIDC, API requests to
endpoints with @cors annotations (like Notes API) were failing with
401 Unauthorized errors. This occurred because:

1. Bearer token validation successfully authenticated the user
2. A session was created for the authenticated user
3. Nextcloud's CORSMiddleware detected the logged-in session but no
   CSRF token, causing it to call session->logout()
4. The logout invalidated the session, breaking the API request

This fix sets the 'app_api' session flag during Bearer token
authentication, which instructs CORSMiddleware to skip the CSRF check
and logout logic. This is the same mechanism used by Nextcloud's
AppAPI framework for external application authentication.

The flag is set at all successful Bearer token authentication points:
- Line 243: After OIDC Identity Provider validation
- Line 310: After auto-provisioning with bearer provisioning
- Line 315: After existing user authentication
- Line 337: After LDAP user sync

Fixes: Bearer token authentication for all Nextcloud APIs
Tested-with: nextcloud-mcp-server integration tests
Signed-off-by: Chris Coutinho <[email protected]>
@cbcoutinho cbcoutinho force-pushed the fix/bearer-auth-cors-session-logout branch from 1040d90 to 04ea9b8 Compare October 21, 2025 09:10
Copy link
Contributor

@edward-ly edward-ly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be confirmed by @julien-nc when he's back, but I agree with @oleksandr-nc in the meantime that we shouldn't rely on app_api to do this which does (and may in the future) do something different than what is intended here. I don't have a strong preference for any of the 4 solutions as of now.

@github-actions
Copy link

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Does the user_oidc application support notes and other non-OCS API endpoints?

4 participants