H2CK / oidc

OpenID Connect App for Nextcloud
GNU Affero General Public License v3.0
68 stars 6 forks source link

CORS headers not added for any app end points #434

Closed rjclark closed 3 weeks ago

rjclark commented 1 month ago

I've enabled the app and started poking around to see about using it as an OIDC provider. I noticed that the CORS headers are not being added automatically - breaking the login for remote apps.

Versions

Steps:

  1. Enable the app
  2. (optional) Add an OpenID Connect clients. I tried both with and without a client defined
  3. Execute curl GET commands against /index.php/.well-known/openid-configuration , /index.php/apps/oidc/openid-configuration or /index.php/apps/oidc/token

All of them are missing the Access-Control-Allow-Origin header in the response.

Example output:

curl -vvv https://<my site>//index.php/.well-known/openid-configuration

returns

< HTTP/2 200 
< date: Sun, 21 Jul 2024 03:21:05 GMT
< content-type: application/json; charset=utf-8
< content-length: 1154
< vary: Accept-Encoding
< set-cookie: oc_sessionPassphrase=<redacted>
< set-cookie: __Host-nc_sameSiteCookielax=<redacted>
< set-cookie: __Host-nc_sameSiteCookiestrict=<redacted>
< set-cookie: oc545ewdci0o=<redacted>
< expires: Thu, 19 Nov 1981 08:52:00 GMT
< pragma: no-cache
< x-request-id: fJIKmZJsMix0rtuvFv81
< cache-control: no-cache, no-store, must-revalidate
< content-security-policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
< feature-policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
< x-robots-tag: noindex, nofollow
< x-nextcloud-well-known: 1
< referrer-policy: no-referrer
< x-content-type-options: nosniff
< x-download-options: noopen
< x-frame-options: SAMEORIGIN
< x-permitted-cross-domain-policies: none
< x-robots-tag: noindex, nofollow
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=15724800; includeSubDomains
< 
{"issuer": ...

Logging

I could not find anything in the logs, even at DEBUG, but I'm happy to go searching for more.

Workaround

I hacked my nginx config to add the following, which forces the header on every request. This is not ideal for me however, so I'm hoping to enable the headers on just the OIDC related URIs

# Set default $hdr_access_control_allow_origin if Access-Control-Allow-Origin does not exist
map $upstream_http_access_control_allow_origin $hdr_access_control_allow_origin {
    '' "*";
}

server {
    ... stuff ...

    add_header Access-Control-Allow-Origin $hdr_access_control_allow_origin  always;
}
H2CK commented 1 month ago

We have to differentiate the behavior for the different endpoints.

First to the endpoints at index.php/.well-known/openid-configuration and index.php/.well-known/webfinger : Those endpoints are controlled by the Nextcloud server and it is not possible to set the CORS headers from an Nextcloud app. See also for this: https://help.nextcloud.com/t/cors-preflight-for-well-known-webfinger/182001

The only way to set CORS here correctly is currently by configuring your web server or reverse proxy. This can also be done in more granular way than in your proposed workaround. Nevertheless for the .well-known endpoints you have to do a configuration in your web server / reverse proxy anyhow since the endpoint should be accessible externally without the index.php in the URL.

To the other URLs I will give you later further feedback.

H2CK commented 1 month ago

CORS usually is based on a preflight request. This OPTIONS request with the headers Origin and Access-Control-Request-Method (optionally also Access-Control-Request-Headers) is initiated by the browser in the background and in the response the expected Access-Control-xxx headers are contained. See also: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

Up to version 0.9.1 the implementation of CORS was mainly based on the CORS preflight request.

Your curl request does not automatically initiate a CORS preflight request. You are expecting to have the Access-Control-xxx headers in the response of the request itself (even without setting the Origin and Access-Control-Request-Method headers - which usually should be set to receive the CORS headers). So you are referring to the simple requests from the obsolete CORS spec. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests

In version 0.9.2 the support for CORS for simple requests was improved. For the endpoint index.php/.well-known/openid-configuration I managed to set the CORS headers in simple requests as well. But for the webfinger endpoint the previous statement still fully applies.