nextcloud / nextcloud/server

SSO/OIDC with redirect and nextcloud's form-action CSP do not play nice together

Open
#29,317 7 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage 25-feedback bug feature: authentication needs review
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

How to use GitHub
  • Please use the πŸ‘ reaction to show that you are affected by the same issue.
  • Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
  • Subscribe to receive notifications on status change and new comments.
Explanation

This issue is related to https://github.com/nextcloud/server/pull/16711 from @rullzer

Background: You will remember (πŸ™„ ) that Chrome and Firefox apply the form-action CSP differently when the response to a form request is a redirect. This is currently undefined behavior and the W3C has not yet decided what to do about it. Firefox does not apply the form-action CSP, but Chrome does.

The above merged PR from @rullzer fixes the case where Nextcloud responds to the POST /login/flow request with a 303 redirect to the OIDC callback url. This is working fine.

However... what happens when the service being redirected to itself issues a redirect to a different origin (that wasn't in the original allowed form-action source list?

   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚                            β”‚
   β”‚  POST   <NC>/login/flow    β”‚
   β”‚                            β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   303 redirect oidc callback url  β”‚
β”‚                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    oidc service 302/3 redirect   β”‚
β”‚                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Well for Firefox this works just fine as it doesn't keep the form-action CSP around.

On Chrome/Edge, the "Grant Access" button just spins for a long time and if you open the console you see:

Refused to send form data to 'ORIGINAL <NC>/login/flow' because it violates the following Content Security Policy directive: "form-action 'self' https://oidc-callback-url".

The solution is to ensure that the domain for the 2nd redirect is included in the original form-action CSP.

I was able to manually add this by editing lib/public/AppFramework/Http/ContentSecurityPolicy.php and appending my extra domain to the $allowedFormActionDomains array.

I'm not sure what the proper solution is here. As a nextcloud administrator I need to have some way to allow certain domains in the form-action policy. But the workaround in the previous paragraph is NOT a good solution as it applies to every form in the application, whereas it is only required for the POST /login/flow during the oauth/oidc workflow.

Maybe the "OAuth 2.0 clients" feature should allow additional URIs?

image

Steps to reproduce

This is rather cumbersome to reproduce as you will need a third-party software authenticating to nextclouds oidc provider.

  1. Install matrix's synapse homeserver on your server
  2. Install the element web client on your server
  3. Configure synapse to support user authentication via the Nextcloud OIDC provider
  4. Attempt to login in Element to the server (via the SSO option)
Expected behaviour

The oauth login flow should complete without error

Actual behaviour

Firefox : Everything works fine

Chrome/Edge: The login flow fails after pressing the "Grant Access" button in nextcloud.

Given:

Then the POST https://nextcloud.example.com/login/flow returns 303 redirect with Location: https://matrix.example.com/_synapse/client/oidc/callback, and this also returns a 302 redirect to https://chat.example.com/something/something

So from Chrome's point of view all three domains must exist in the form-action CSP, but only the first two are included.

Server configuration

Operating system: linux

Web server: apache

Database: postgres

PHP version: 21.0.5

Nextcloud version: 21.0.5

Updated from an older Nextcloud/ownCloud or fresh install: no

Where did you install Nextcloud from: official docker image 21-apache tag

Signing status:

Signing status
No errors have been found.

List of activated apps:

App list
Enabled:
  - accessibility: 1.7.0
  - activity: 2.14.3
  - audioplayer: 3.2.2
  - cloud_federation_api: 1.4.0
  - comments: 1.11.0
  - contactsinteraction: 1.2.0
  - dav: 1.17.1
  - discoursesso: 1.22.0
  - external: 3.8.2
  - federatedfilesharing: 1.11.0
  - federation: 1.11.0
  - files: 1.16.0
  - files_external: 1.12.0
  - files_pdfviewer: 2.1.0
  - files_rightclick: 1.0.0
  - files_sharing: 1.13.1
  - files_texteditor: 2.14.0
  - files_trashbin: 1.11.0
  - files_versions: 1.14.0
  - files_videoplayer: 1.10.0
  - firstrunwizard: 2.10.0
  - logreader: 2.6.0
  - lookup_server_connector: 1.9.0
  - mail: 1.10.5
  - nextcloud_announcements: 1.10.0
  - notifications: 2.9.0
  - oauth2: 1.9.0
  - password_policy: 1.11.0
  - privacy: 1.5.0
  - provisioning_api: 1.11.0
  - recommendations: 1.0.0
  - serverinfo: 1.11.0
  - settings: 1.3.0
  - sharebymail: 1.11.0
  - spreed: 11.3.2
  - support: 1.4.0
  - survey_client: 1.9.0
  - systemtags: 1.11.0
  - text: 3.2.0
  - theming: 1.12.0
  - twofactor_backupcodes: 1.10.0
  - updatenotification: 1.11.0
  - user_status: 1.1.1
  - viewer: 1.5.0
  - weather_status: 1.1.0
  - workflowengine: 2.3.1
Disabled:
  - admin_audit
  - dashboard
  - encryption
  - photos
  - user_ldap

Nextcloud configuration:

Config report
{
    "system": {
        "htaccess.RewriteBase": "\/",
        "memcache.local": "\\OC\\Memcache\\APCu",
        "apps_paths": [
            {
                "path": "\/var\/www\/html\/apps",
                "url": "\/apps",
                "writable": false
            },
            {
                "path": "\/var\/www\/html\/custom_apps",
                "url": "\/custom_apps",
                "writable": true
            }
        ],
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_proxies": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "***REMOVED SENSITIVE VALUE***"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "pgsql",
        "version": "21.0.5.1",
        "overwrite.cli.url": "REMOVED SENSITIVE VALUE",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "auth.bruteforce.protection.enabled": false,
        "overwriteprotocol": "https",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": "587",
        "mail_smtpsecure": "tls",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "skeletondirectory": "",
        "mail_smtpmode": "smtp",
        "mail_smtpauthtype": "LOGIN",
        "mail_sendmailmode": "smtp",
        "mail_smtpauth": 1,
        "mail_smtpname": "***REMOVED SENSITIVE VALUE***",
        "mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
        "default_language": "de",
        "default_locale": "de_AT",
        "theme": "",
        "loglevel": 0,
        "maintenance": false,
        "default_phone_region": "AT"
    }
}

Are you using external storage, if yes which one: local + sftp

Are you using encryption: no

Are you using an external user-backend, if yes which one: no

Client configuration

Browser: Chrome + Firefox

Operating system: Windows + Linux + Mac

Logs

Refused to send form data to 'ORIGINAL <NC>/login/flow' because it violates the following Content Security Policy directive: "form-action 'self' https://oidc-callback-url".

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up β€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with lib/public/AppFramework/Http/ContentSecurityPolicy.php and the /login/flow redirect handling described in the issue and related PR 16711. Reproduce the SSO flow with Synapse and Element in Chrome or Edge, then determine how the second redirect should be represented in form-action without affecting every form; done means the OAuth login completes without the CSP error.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
authentication, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.