craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.22k stars 626 forks source link

Can't log in post-install: Server responds with 400 "Bad Request: Unable to verify your data submission." #2622

Closed utcns closed 6 years ago

utcns commented 6 years ago

Description

I've come to this point after successfully installing Craft 3.0.0-RC15 locally using multi-environment configs and hosting the site from a sub-directory of my local public_html folder (which is my goal for staging/production as well), but then failing to deploy to my staging server (via git and composer, which ultimately led to failed log-in attempts similar to what I'm describing below).

In effort to pin down the cause, I tried to install directly on the server with Composer which ultimately led back to the inability to log into the CP: the login page attempts to POST to index.php?p=admin/actions/users/login, and then the server respons with 400 "Bad Request: Unable to verify your data submission."

Thanks in advance for any assistance.

Steps to reproduce

While logged into my staging server:

1. Create project with Composer [success]

$ composer create-project -s RC craftcms/craft craft
...
...
...
Welcome to Craft CMS! Run the following command if you want to setup Craft from your terminal:

    ~/sources/craft/craft setup

2. Run Craft setup [success]

$ ~/sources/craft/craft setup
Which database driver are you using? [mysql,pgsql,?]: mysql
Database server name or IP address: [localhost] xxxxx.xxxxx.xxxxx
Database port: [3306]
Database username: [root] xxxxx
Database password:
Database name: xxxxx
Database table prefix: craft_
Testing database credentials... success!
Saving database credentials to your .env file... done

Install Craft now? (yes|no) [yes]:

Username: [admin]
Email: xxxxx@xxxxx.xxx
Password:
Confirm:
Site name: Craft-Test
Site URL: [@web] http://test.api.mydomain.com
Site language: [en-US]
...
...
...
*** installed Craft successfully (time: 6.125s)

3. Per Craft documentation (as my web root is already configured by our hosting provider to be ~/public_html): copy contents of ~/sources/craft/web to ~/public_html.

Note: Unless I'm missing something or misreading, the documentation should be more clear on the steps necessary to serve Craft from a location other than /craft/web. Simply moving the contents of /craft/web to the desired web root location (as indicated in the documentation) overlooks the need to define a custom Craft base path in index.php (or through env variables). Consequently, as the next step will show, the app will fail to respond to requests.

4. Navigate to http://test.api.mydomain.com/admin/login [fail]

Server Responds with 500 error (expected).

5. Update ~/public_html/index.php to define correct Craft base path.

<?php
/**
 * Craft web bootstrap file
 */

// Set path constants
define('CRAFT_BASE_PATH', '/path/to/home/sources/craft');
define('CRAFT_VENDOR_PATH', CRAFT_BASE_PATH.'/vendor');

// Load Composer's autoloader
require_once CRAFT_VENDOR_PATH.'/autoload.php';

// Load dotenv?
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
    (new Dotenv\Dotenv(CRAFT_BASE_PATH))->load();
}

// Load and run Craft
define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
$app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php';
$app->run();

6. Navigate to http://test.api.mydomain.com/admin/login [success]

7. Attempt to log in [fail]

POST to index.php?p=admin/actions/users/login responds with 400, “Bad Request: Unable to verify your data submission”.

Additional info

utcns commented 6 years ago

Oddly enough, after a couple of refreshes and log-in attempts, the the login session was established--however, while navigating the CP there are continuous "An unknown error occurred" alerts.

Furthermore, now, if I attempt to log in and get the same failure as originally reported above, and then navigate to /admin, the CP session is active (though the "An unknown error occurred" alerts persist).

brandonkelly commented 6 years ago

We’ve seen this happen when SSL is involved but not required. If you have an SSL cert, make sure you are enforcing it from your web server config by redirecting non-SSL requests over to SSL.

utcns commented 6 years ago

Hi Brandon,

Thanks for the reply. I was actually using HTTPS initially and then dialed back to HTTP for further testing. As of this moment, I can confirm that the issue still stands regardless of SSL.

I just went through two additional fresh installs of Craft via Composer: one setting up the project from the command line and using the HTTPS version "Site URL" (as well as trying with the default "@web"), and one setting the project up via the web install (after defining configuring the database in .env). Both fail.

When attempting to set up via the web install, after entering my initial user details the POST to /index.php?p=admin/actions/install/validate-account fails with a 400 error. A preview of the response shows "Bad Request: Request must accept JSON in response".

Note that we have Craft 2 running on this same hosting platform at my university without issue. As I'm sure you'll see below, we are using NGINX as a proxy cache layer--but this hasn't posed any issues in the past and so I don't believe it's somehow related to this issue.

Thanks again for any guidance.

Here are the headers I'm seeing in Chrome when trying to install from the web.

General Header

Request URL: https://test.api.my.domain.edu/index.php?p=admin/actions/install/validate-account
Request Method: POST
Status Code: 400 Bad Request
Remote Address: xxx.xxx.xxx.xxx:443
Referrer Policy: origin-when-cross-origin

Response Header

HTTP/1.1 400 Bad Request
Server: nginx
Date: Thu, 22 Mar 2018 15:33:06 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Set-Cookie: cache_id=906f1d6bb5c65285ea7e6be492b0b6c1; expires=Thu, 22-Mar-18 16:33:06 GMT; path=/; Secure
X-Robots-Tag: none
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-Powered-By: Craft CMS
Strict-Transport-Security: max-age=0; includeSubDomains
Set-Cookie: balancer_id=utweb-px-z1-p02_https|WrPMt|WrPMn; path=/; Secure

Request Header

POST /index.php?p=admin/actions/install/validate-account HTTP/1.1
Host: test.api.my.domain.edu
Connection: keep-alive
Content-Length: 77
Origin: https://test.api.my.domain.edu
X-CSRF-Token: uo3t0oabzPN1nkhe_zuW-wYBKQF_OPnxZooGe1bNo5L8DWpOnSglkOPcoOexyrWxEcQCKZkN_Z4wZH1DO0izlTDpXzE7lfHCkWcbAtseZ_k=
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: https://test.api.my.domain.edu/admin/install
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: cache_id=906f1d6bb5c65285ea7e6be492b0b6c1; CRAFT_CSRF_TOKEN=f2d59956741dbfa265c7e99e439278ebf6ea109b0603fc0adaddb9aff25808a2a%3A2%3A%7Bi%3A0%3Bs%3A16%3A%22CRAFT_CSRF_TOKEN%22%3Bi%3A1%3Bs%3A40%3A%22YQM57QyBdZJwf6ke6eTBDpJdVcYJmXRPmjqLF6Bi%22%3B%7D; balancer_id=utweb-px-z1-p02_https|WrPMo|WrPMn

And the .htaccess config

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Force HTTPS
    RewriteCond %{HTTPS} !=on
    RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
    RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>
narration-sd commented 6 years ago

@utugs, don't know if this is what @brandonkelly refers to, but I had something related to your case happen a few days ago on a seasoned dev installation.

The cause was the baseUrl setting in the default Site -- somehow I'd gotten http://name.domain.com in there. This crossed with a recent further tightening up of Chrome and Firefox https insistence on a .dev domain to suddenly show up as a problem.

The result was failing Ajax, in particular the admin login, as I think you've seen.

A fix that worked was to go into the database, since I had no CP access, and change the default Site baseUrl to //name.domain.com -- no protocol.

I've just checked, and at recent levels of Craft RC, @web (only) seems fine for this value also.

narration-sd commented 6 years ago

n.b. small edits to make clearer what Site I'm referring to...which you find in the craft_sites table of the db.

utcns commented 6 years ago

@narration-sd --

I appreciate you taking the time to share your experience. In my case, this is happening on a fresh install where I've confirmed the correct domain name and the appropriate HTTPS protocol are both in place from the get-go. At this point, I've tried every which way to configure the domain (defining the HTTP and HTTPS versions, as well as just going with the default "@web") and in all cases I run into the same behavior.

Hopefully Brandon will have some further insights.

Cheers.

brandonkelly commented 6 years ago

@utugs I think it’s actually more of a Chrome caching issue, than Craft. Try going into Chrome settings and clearing all browser data for the domain, and then try again.

utcns commented 6 years ago

@brandonkelly Cache was cleared early on and throughout all of my testing, and have found that this issue occurs on multiple browsers, computers, and networks. I've also gone so far as to purge the NGINX cache on the server instance.

At this point, I'm fairly confident we can rule out cache as the root cause.

brandonkelly commented 6 years ago

@utugs Is this happening on a public server anywhere that we can access? If so can you send login/FTP credentials over to support@craftcms.com ?

narration-sd commented 6 years ago

A strange one. Makes you think about Craft's cache also, as is still necessary sometimes at least with Assets things -- believe I cleared that in the midst of throes (when locked out, cd storage, rm -rf * => be careful)

narration-sd commented 6 years ago

@utugs Might have something further for you here.

I just had my version of this issue recur on the same rather new site. I don't yet recognize why that would happen, though possibly because the server was auto-restartd by digitalocean around a security upgrade.

I was again able to view the site, but was summarily refused admin access. This was because of mixed content -- cp_resources items being sent as http, while the site is https. This meant the login screen itself was missing most of its formatting -- just raw html fields and texts displayed. It's very visible as errors in the browser dev console, if you want to check for that.

Here's what I did to bring it back to clean operation with admin login and CP:

  1. As mentioned before, I checked the baseUrl field in the craft_sites table of the database. Still //site.domain.com -- again, checked, @web instead works fine on recent RC level.
  2. I found a case Brad @angrybrad dealt with, and on that basis changed my nginx caching for static items to be very short, then sudo systemctl restart nginx to put change in place. This didn't by itself affect the problem, and I may experiment with reverting it, but as this config came from nginx defaults, here's the offending config block from within the server block, with original cache time commented out, revised just above it.
        expires 1M;
        # expires max;
        add_header Pragma public;
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    }
  1. Then, here's what fixed it. There was in the same default nginx config a line to do with https which I'd questioned, and intended to go back to see about when not in a hurry for this test site. This block is also within the https-running server block, and you can see the line commented out.

After this and another sudo systemctl restart nginx, the site including CP admin came back to full life.

 location ~ ^(.+\.php)(.*)$ {
        # try_files $uri =404;
        fastcgi_split_path_info       ^(.+\.php)(.*)$;
        fastcgi_pass localhost:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#        fastcgi_param HTTPS off;
    }

Oh yes, along the way and re: @brandonkelly 's latest suggestion, I did clear everything including cookies on a Chrome browser where primarily testing. This doesn't seem to have been necessary on the Firefox browser still showing the faulted screen, as it worked fine after simply reloading the site, but there could be other situations, and I'd be sure to do it. I also did an rm -rf of everything within the /storage/runtime folder -- I'm thinking this step wasn't needed, due to the root of this solution, but it's there to try, always being very careful of what folder you are in before engagingrm -rf.

utcns commented 6 years ago

@narration-sd Based on your description, I think we're experiencing dissimilar issues (though perhaps related in some way). Editing the NGINX configuration is not an option in my environment.

@brandonkelly I'll send you a follow-up by email.

As for an update: I'm finding that this issue looks to be related to /admin/action URL endpoints. I continue to get a variety of errors when sending POST or GET requests. Furthermore, a test install of Craft 2 on this same server instance proves to work without issue, so this appears rooted in Craft 3 or Yii2.

narration-sd commented 6 years ago

@utugs well, you may well have something else as the issue, as ever, and I am going to bow out here.

However, I suspect you are going to need to have an open mind about server configuration -- making a friend of the knowledgeable administrator if you're unable to do it. As in Brandon's response, if this was a widespread problem, the team there would have heard about it.

That HTTPS_ON configuration is actually rather critical, as it determines whether PHP can recognize it's been passed a secure request. And, there's evidence that the nginx configuration I mentioned is often defaulted wrongly due to a mistake, probably the assumption which is no longer valid in today's world that http is the normal case.

For an example discussed, try https://github.com/symfony/symfony-docs/issues/5517 .

In any case, just commenting that config line out as I did on a fast pass to get a test going isn't necessarily going to give the right results, depending on internal defaults, and I've corrected my own server to respond according to actual request. This should be a solid solution, especially since you seem to alternate between https or not.

fastcgi_param HTTPS $https;

Changing this line alone should work unless your nginx is an older version not providing the $https variable, in which case your administrator can pull two lines to set that out of this post, which also underlines that others use this method: https://stackoverflow.com/questions/4848438/fastcgi-application-behind-nginx-is-unable-to-detect-that-https-secure-connectio

We can seldom depend on server config being just right, but there's a lot of useful information on nginx in particular out there on StackOverflow etc., which your administrator will understand. And so, good fortune...

utcns commented 6 years ago

@brandonkelly After returning to this issue, I finally secured a solution--and it's not what I expected: the HTTP_ACCEPT header was missing support for JSON.

@narration-sd Thanks again for sharing your past thoughts.

Background On the servers here at my institution, where I have Craft 2 driving a number of projects, I quickly found that it was necessary to explicitly set the HTTP_ACCEPT header as follows otherwise Craft would throw an error (only mentioning the absence of the HTTP_ACCEPT header but not the required value):

HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Fix for Craft 3 When diving into the issue again today, I remembered back to an earlier point when I reported that the 400 response stated, "Bad Request: Request must accept JSON in response". Simply updating the HTTP_ACCEPT header to include JSON support as follows resolved the issue:

HTTP_ACCEPT text/html,application/xhtml+xml,application/xml,application/json;q=0.9,*/*;q=0.8

Could this be captured in some way as an error and presented to the user?

At any rate, happy to have Craft 3 now working in our environment.

angrybrad commented 6 years ago

@utugs Sounds like the servers at your institution are maybe sitting behind some proxy or firewall that are stripping out the HTTP_ACCEPT header from the request.

Any time Craft itself makes an AJAX request, it sets that header with application/json value. The Craft controllers on the other end check that value to determine whether they need to respond with JSON vs. HTML (some controller actions support multiple response methods).

If I'm understanding your fix, then you're manually setting HTTP_ACCEPT to include application/json on all requests, which I would assume would break the controller actions that support multiple responses as they'd always return JSON now.

Seems like the proper fix would be to figure out why those headers are stripped in the first place and allow them to pass through to the web server untouched.

cballenar commented 6 years ago

Just ran into this issue, my VM was throwing this error in every page, brand new instance. As it turns out it was being caused by the .htaccess configuration provided by the HTML5 Boilerplate. I guess it was being too restrictive, after commenting out the Media types block, which "Serves resources with the proper media types (f.k.a. MIME types).", the error disappeared. (lines ~154-238)

I wasn't sure how to modify it to serve the files properly though. Anybody?

brandonkelly commented 6 years ago

@cballenar You might want to ask that at craftcms.stackexchange.com

laurabennett commented 2 years ago

I know this is closed but I just ran into it for the first time. I copied my database while logged in and then when I tried to login to the new "dev" server it wouldn't let me. I changed /login to /logout and tried again... worked this time. A nicer error like "This user is already logged in" would have been nice.

brandonkelly commented 2 years ago

@laurabennett I’m unable to reproduce. What version of Craft are you running?

laurabennett commented 2 years ago

4.2.0.2