Not forwarded from login page - violates the following Content Security Policy directive

Nextcloud version (eg, 20.0.5): 23.0.0
Operating system and version (eg, Ubuntu 20.04): Docker on Ubuntu 20.04
Apache or nginx version (eg, Apache 2.4.25): Docker image: nextcloud:23
PHP version (eg, 7.4): Docker image: nextcloud:23

The issue you are facing:

Unable to “flawlessly” login. I enter my login credentials, but then I seem to be stuck on the login page.
But when I enter the URL of my Nextcloud installation in another tab, I’m logged in and see the dashboard.

On the “stuck” tab, in the browser console, there’s the following error:

Refused to send form data to 'https://×××××.×××/login' because it violates the following Content Security Policy directive: "form-action 'self' https://×××××.×××".

(Instead of ×××××.×××, there’s the real hostname.)

I found that I might solve this issue by changing lib/public/AppFramework/Http/ContentSecurityPolicy.php and changing this array:

        protected $allowedFormActionDomains = [
                '\'self\'',
                'https://×××××.×××/login',
                '*.×××××.×××',
        ];

Didn’t change anything.

This does not happen with all browsers. Only with recent chromium based browsers (Brave, Vivaldi, Edge, Opera). Firefox 95 seems to ignore that.

The output of your config.php file in /path/to/nextcloud (make sure you remove any identifiable information!):

<?php
$CONFIG = array (
  'htaccess.RewriteBase' => '/',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'instanceid' => 'ocp...',
  'passwordsalt' => '...',
  'secret' => '....',
  'trusted_domains' => 
  array (
    0 => 'nc.5y5.one',
  ),
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'mysql',
  'version' => '23.0.0.10',
  'overwrite.cli.url' => 'http://×××××××××××.×××',
  'dbname' => 'nextcloud',
  'dbhost' => 'db',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => '.....',
  'installed' => true,
  'objectstore' => 
  array (
    'class' => '\\OC\\Files\\ObjectStore\\S3',
    'arguments' => 
    array (
      'bucket' => 'nc-...',
      'key' => '.....',
      'secret' => '.....',
      'region' => 'eu-central-1',
      'hostname' => 's3.eu-central-1.wasabisys.com',
      'port' => '',
      'objectPrefix' => 'urn:oid:',
      'autocreate' => false,
      'use_ssl' => true,
      'use_path_style' => false,
      'legacy_auth' => false,
    ),
  ),
  'maintenance' => false,
  'mail_smtpmode' => 'smtp',
  'mail_smtphost' => 'mail.xyz',
  'mail_sendmailmode' => 'smtp',
  'mail_smtpport' => '465',
  'mail_from_address' => 'senden',
  'mail_domain' => 'foo',
  'mail_smtpsecure' => 'ssl',
  'mail_smtpauth' => 1,
  'mail_smtpname' => 'foo',
  'mail_smtppassword' => 'secret',
  'twofactor_enforced' => 'false',
  'twofactor_enforced_groups' => 
  array (
  ),
  'twofactor_enforced_excluded_groups' => 
  array (
  ),
);

CSP is quite browser dependend.
One can only find out the blocking rule by disabeling things. That could be in your .htaccess file, or above in the httpd settings.
You have to evaluate on a per rule base to find out.

If you do not have acces to the above httpd code, try to add this rule to your .htaccess file in the root of the NC install:

Header unset Content-Security-Policy

Hm.
I don’t have a .htaccess file. I’m using Caddy as a webserver; TLS terminates on Caddy.

As far as Apache goes - I’m using the Docker image from Nextcloud. With however Apache is preconfigured.

And for the rule - isn’t the error message quite clear?

Refused to send form data to 'https://×××××.×××/login' because it violates the following Content Security Policy directive: "form-action 'self' https://×××××.×××".

When I change protected $allowedFormActionDomains = […] in ContentSecurityPolicy.php, I see that I’m at the right place - the error message in the console changes, accordingly to what I put there.

I’ve now added Header unset Content-Security-Policy to .htaccess. But isn’t that a bit too extreme? I mean, CSP does make sense, doesn’t it?

Apache uses .htaccess.
Yes, disabling is not what you want, but if it then works, the CSP rules are definitively cause.
In fact, Nextcloud creates this CSP rules. If defined earlier, you get double declarations. And for some rules the effect is that there is no rule anymore. Therefore I had to disable nearly all CSP that was set for the main domain (and subdomains).
You can seee what rules are active for your cloud here: https://gf.dev/csp-test

In my case I have done this for the cloud subdomain only:
Header always add Strict-Transport-Security “max-age=31536000; preload”
Header unset X-Content-Type-Options
Header unset X-XSS-Protection
Header unset X-Download-Options
Header unset Referrer-Policy
Header unset Content-Security-Policy
And this works for all our NC installs that get A+ in security tests. Test the results with the link above.

According to the error message, it should be “form-action”, which is causing issues.

https://gf.dev/csp-test shows the following CSP header (I split it on “;” to have multiple lines):

default-src 'none';
base-uri 'none';
manifest-src 'self';
script-src 'nonce-aDlQNUowdHNEcHVlUjJlcVdZNVZ1NGlRQkRiK1M0bXc0R0ZtVU50TzdHMD06ODZHSlh4SUJXSzNNQWpQZkk4b0d5c3ZLU1ZPcUlkUG4xRTRGQnFKM3ZpTT0=' blob:;
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob: https://*.tile.openstreetmap.org;
font-src 'self' data:;
connect-src 'self' blob: stun.nextcloud.com:443;
media-src 'self' blob:;
frame-src 'self' https://nc.MY.DOMAIN;
child-src blob: 'self';
frame-ancestors 'self';
worker-src 'self' blob:;
form-action https://nc.MY.DOMAIN/login *.MY.DOMAIN 'self' https://nc.MY.DOMAIN

Originally, before I made changes, it was:

form-action 'self' https://nc.MY.DOMAIN

I’ve changed ContentSecurityPolicy.php to have:

/** @var array Domains which can be used as target for forms */
        protected $allowedFormActionDomains = [
                'https://nc.MY.DOMAIN/login',
                '*.MY.DOMAIN',
                '\'self\'',
        ];

I added the two lines “'https://nc.MY.DOMAIN/login',” and “'*.MY.DOMAIN',”.

Doesn’t work - either way.

What the heck… The domain is: https://nc.5y5.one/
I’d of course be willing to create a test account, if that would help.

In my case I’ve only:
form-action ‘self’
at the end.

And the connect-src is in my case (extra without port):
connect-src ‘self’ blob: stun.nextcloud.com:443 stun.nextcloud.com;

And the frame-src
frame-src ‘self’;

The rest is the same as in your settings.

But your domain is missing quite a lot of security.
There is no DNSSEC
Missing HSTS-policy

And in the report I see the CSP is not as above:
default-src ‘self’;
script-src ‘self’ ‘nonce-WnJ5am5BMnVxL2pVdC9MaHJJTXJoM2orTUZXQll5WitoU20zazdwNlVZQT06TGZXWDBsL043NEduMXFpeXhjcDQ5QmVzV3liRldoTTR5RXpENVBRS2Z2WT0=’;
style-src ‘self’ ‘unsafe-inline’;
frame-src *;
img-src * data: blob:;
font-src ‘self’ data:;
media-src *;
connect-src *;
object-src ‘none’;
base-uri ‘self’;

By default, the PHP file contains:

/** @var array Domains which can be used as target for forms */
        protected $allowedFormActionDomains = [
                '\'self\'',
        ];

With this, the generated header was:

form-action 'self' https://nc.5y5.one

The login form is on https://nc.5y5.one/login.

TBH, I don’t quite get, how this actually can be an issue - I mean, I am staying on the same domain (nc.5y5.one).

Yes, HSTS was missing. Thanks, I’ve just added it.

Did you ever resolve this I’m seeing the same issues and have a support thread open as well. I’m not sure what else to try modifying or checking. I don’t know if I should be tweaking something incorrect in my nginx conf or it must reside in the php files on the nextcloud side.

The issue unfortunately still persists. I’m using nextcloud:27 as a docker image and I’m mainly relying on chromium-based browsers. I searched for some more recent solutions, but apparently there are none (which I found). Thanks for the analysis @alexs77, I have pretty much a corresponding config and setup just four versions later and this issue is still alive.

Is there anything which came up in the meantime that I missed? One-time editing any files having a docker setup is more than nasty and would require cumbersome additional tweaks when recreating the container to be on the safe side.

Thanks to anyone in advance for helping out.

@jen.pet Not sure if you still have this issue, but it could very well be that you’re trying to access nextcloud via port 80, and the origin is usually trying to access documents on https://

This would be intended, and the fix would be to access all instances from https://

The issue unfortunately still persists.

This does not happen in a properly configured environment.

The original poster (earlier) likely had a redirect occurring behind the scenes to something like http://their.domain. The browser error doesn’t make it obvious, because when Chrome blocks redirects on a form-action it informs you about the pre-redirect destination.

The most common scenario I encounter is one where the https:// gets directed to http:// due to an improper configuration. For example, the original poster’s configuration has indications they had an accidental mixed http/https config (if you check their overwrite.cli.url it says http:// which is likely a mistake).

So check your overwrite* parameters (see the Admin Manual; you may need to add them) and make sure they accurately reflect your real environment.

I’ve been able to fix it by adding ‘overwriteprotocol’ => ‘https’, to my /var/www/nextcloud/config/config.php file on the nextcloud server side.