Issue with redirect from https to http

Steps to reproduce

  1. Make available only via HTTPS via a single port on Apache using a reverse proxy configuration.
  2. Try to log in or Log out.

Expected behaviour

Should work without trying to redirect to http, without issue.

Actual behaviour

It attempts to access something on http, which results in an exception if http isn’t available. You won’t see this if you have it available on both 443 and 80. In that configuration, it goes to 80, then back to 443 using normal browser semantics. But, if you don’t have it on port 80, or use a port other than 443 for your HTTPS, you get an error. So, if use port 444, I get this:

# Bad Request

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

Note that if you force it each time you log in or out to correctly prefix the URL with https again by typing it into the URL, you can continue. You have to do this each time you log in or out.

I have not tried accessing from mobile where you can’t do that, but rely on the client to handle all HTTP communication with a single URL for your remote instance. I only tested using a PC browser.

Server configuration

Operating system:

Linux - Fedora

Web server:

Used your docker compose, then ran reverse proxy to port 8080. This works. However, because I’ll be access multiple instances and other things through a single Apache HTTP server with reverse proxy through a WIFI router using virtual hosting, each one will have only one port and it will use HTTPS.

Reverse proxy through Apache

Database:

MariaDB (your docker compose)

PHP version:
w/e is in your docker compose

ownCloud version: (see ownCloud admin page)

ownCloud 10.6.0 (stable)

Updated from an older ownCloud or fresh install:

Where did you install ownCloud from:

docker compose

1 Like

You need to verify that you are actually connecting to the port with the correct protocol if you are not using standard ports. For HTTP this is 80 and for HTTPS it is port 443. So if you are deviating from that, define it in your address bar:
https://domain.tld:444

Additionally I’d strongly recommend to clear your browser cache. Some of the redirect behavior is cached and can lead to frustrating bug search.

If you want to be 100% sure, use curl for debugging:
curl -I http://domain.tld <- should show connection refused if the port 80 is unused.
curl -I https://domain.tld <- should show connection refused if the port 443 is unused.
curl -I https://domain.tld:444 <- should show location response header to redirect you to the login.

And this final redirect to login page might be where the problem lies. ownCloud might not see correctly on which port/protocol it is hosted behind the proxy. So perhaps try to override the automatic proxy detection with your correct values:

In docker you’d typically set these using the available environment variables:

[...]
OWNCLOUD_OVERWRITE_CLI_URL ${OWNCLOUD_PROTOCOL}://${OWNCLOUD_DOMAIN}${OWNCLOUD_SUB_URL}
OWNCLOUD_OVERWRITE_COND_ADDR
OWNCLOUD_OVERWRITE_HOST
OWNCLOUD_OVERWRITE_PROTOCOL
OWNCLOUD_OVERWRITE_WEBROOT
[...]
1 Like

OK, I don’t mean to brag, but I programmed in over 30 languages by my 20s and web applications since the 90s. I prefer TS today in both the back-end (node) and front-end (Angular). I don’t program in PHP because I really like being able to share code in both the browser and back-end that TS permits today, via Node libraries.

That said, I’m telling you that when you log out, it will in two places REDIRECT from the HTTPS to HTTP. I include port “:444” after the host, of course. In that case, it does not change the “:444” in the host, thus you get the error I pasted in the OP.

I told you, If you configure to only work on 443/80, and it is on BOTH, then it works, because it will seamlessly use port 80 then go back to 443 when there is no port designation in the URL due to how the browser defaults to those ports when there is no override with the port suffix after the host name. This configuration, however, is NOT an option for several reasons.

  • I do not want HTTP to be accessible on the public network. Only HTTPS.

  • I need to route several HTTPS ports for different ownCloud instances through routers that do not support name based virtual hosting. Most port forwarding in OTS routers only handles ports, and not host name filtering. Thus, there is no way to route multiple name based port forwarding through the same port, ie port 443.

Thus, I need the specific non-443 use case to work, and shared with you the outcome of using port 444.

Somewhere in your code when a user clicks to login, or if logged in, when they click to logout, you appear to have something forcing use of “HTTP”, despite the browser URL set to use HTTPS.

Like I said, these are the only points it does this. Please replicate this issue by setting up HTTPS on a non-standard port such as 444, OR make sure that ownCloud is NOT on port 80.

You can leave other things running on port 80. If you are using port 443 for HTTPS, you’ll just get a different error about the page not being found if it is not available on port 80. One of these pages is “/login” IIRC. When redirected, it insists on first accessing this page via HTTP before then redirecting to back to HTTPS.

The solution is to find out where in the code at these times, login and logout, it REDIRECTS to using HTTP.

Note also that the reason you won’t “see” this if using 443/80 is because once it redirects to HTTP, it immediately redirects back to HTTPS if the HTTP successfully accesses w/e it is trying to access in ownCloud. So, it’s a fast blip you may not notice. You will only reproduce this issue if it cannot satisfy the HTTP request.

DUE TO YOUR

Sorry, new users can only put 2 links in a post.

ERROR, I HAD TO MODIFY THE URLs BELOW SO I COULD POST THIS. BUT, YOU CAN FIGURE OUT WHAT THE ORIGINAL URLs WERE.


I reproduced this in both FF and Chrome. Here, in Chrome, I just logged in after entering the user ID and password. You can see upon the redirect of a successful login, it forwarded to an HTTP URL:

Now, when I insert the ‘s’ in there after ‘http’, I am in. I can view files and use ownCloud until I go to logout using the dropdown menu on the right. At that point it forwarded me to this URL

http : //corsair-own-pub:444/logout?requesttoken=JjcdVgoDfDUwMFhaVEBVFSg2Aw45G34hJwsefQ0ufjU%3D:VVR7hUNZVG96b7/CbzS7Cm3IPRFNebFf5PrjP7O%2Btz8%3D

Giving me the BAD REQUEST error. Once again, missing the ‘s’. If I insert the ‘s’, it sends me to

http : //corsair-own-pub:444/login

Again, missing the ‘s’ with the BAD REQUEST error. I them modify it to

https : //corsair-own-pub:444/login

and now I’m at the login screen where I can enter the login credentials and repeat this.

Thanks for the doc on the redirect behind a proxy issue. The question I have is why it doesn’t just use relative paths? Then it doesn’t need to know which schema is used.

I can play with the OWNCLOUD_PROTOCOL setting and report back.

Setting OWNCLOUD_PROTCOL to ‘https’ didn’t change it. It still redirects to http. I set it in both the docker-compose.yml and .env, and did a docker-compose down and up. You can see I verified the value is set to ‘https’ in the container.

$ docker-compose exec owncloud bash
root@7a10309c0b52: /var/www/owncloud # echo $OWNCLOUD_PROTOCOL
https

Here is the response with curl

# curl -Ik https://corsair-own-pub:444
HTTP/1.1 302 Found
Date: Sun, 31 Jan 2021 06:34:22 GMT
Server: Apache
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Robots-Tag: none
X-Frame-Options: SAMEORIGIN
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-src *; img-src * data: blob:; font-src 'self' data:; media-src *; connect-src *
Location: http://corsair-own-pub:444/login
Content-Type: text/html; charset=UTF-8
Set-Cookie: oc0axd505crh=01c4kibfg15c9u14mrrat36sqi; path=/; HttpOnly
Set-Cookie: oc_sessionPassphrase=EBkFBipOc8FP51%2Bxc%2B3ddFTJQfc597ausZYM1Bv9UNQfDy%2FXs7CeuGZHO6mylyButbsyJ9iUE7u1zi1UtE4vj5mrI7h4rOP5bprFZ3jT5O7pboDXYs6OxJsf34IVxsJW; path=/; HttpOnly; SameSite=strict

There is no place to put .htaccess in a reverse proxy as it has no content directory of its own. However, I have been modifying an httpd conf used to setup the SSL to no avail.

# BEGIN force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
#RewriteRule (.) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
#RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L]
# END force HTTPS

This redirect does work if I put it in the port 80 (http) configuration, in that it always forces it to use https. But this http port will not be available on the public network, which will only have access to port 444 with https. That redirect never seems to work on a port that is already serving https. Many others have reported this issue on the Internet with no resolution.

Perhaps the issue is that the server always sees HTTPS as on regardless of what’s in the request schema? I tried this, to no avail

#RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_SCHEME} !=https

UPDATE: I enabled tracing of rewrite, and it only logs the rewriting if I use port 80. Does not log any rewriting for the 443/444 ports. This could be because the RewriteCond is always false.

UPDATE: Confirmed via CustomLog that %{HTTPS} is off when it does the access that causes the Bad Request, and on for the URLs it handles correctly with https. Have logging set to

LogLevel alert rewrite:trace8

I finally got trace rewrite log output for the SSL port. It applies rewrite rules for every request EXCEPT the one that results in Bad Request. The only thing I suspect right now due to all this process of elimination is that HTTPD does not apply rewrite rules when it detects this exception.

This is still an open issue. SUMMARY: Cannot get owncloud to use https instead of http for its login and logout process URLs and cannot get Apache to invoke the rewrite when it gives the Bad Request error to correct it.

Considering using NGINX for the reverse proxy. Has anyone successfully routed a reverse proxy through NGINX? Can it do a rewrite when a Bad Request is invoked due to http being detected on an https port?

It might be your reverse proxy the one giving problems.

I have haproxy as reverse proxy in front of some docker container and I had to add the following:

        http-request set-header X-Forwarded-Port %[dst_port]
        http-request add-header X-Forwarded-Proto https if { ssl_fc }

        option forwardfor

It’s very likely that your reverse proxy should send those headers somehow. Note that the reverse proxy will send the request as http to the port 8080 (assuming default ownCloud docker setup) but ownCloud will need to know the external protocol and ports. That’s why those headers are required for a reverse proxy setup.

I don’t know how to set it up with apache, so you’ll have to look for documentation. Anyway, you can use whatever reverse proxy you’re more confortable with.

2 Likes

Yeah bro, it was worked for me.

2 Likes

That’s helpful. Thanks for the input. I couldn’t get it to work with Apache, though, using

Header set X-Forwarded-Port 444
Header set X-Forwarded-Proto https

This is now resolved. What I had to do was set this in config.php

  'overwriteprotocol' => 'https',

That allowed everything to work except LOCAL_IP:8080 from a PC browser, which wasn’t critical since the reverse proxy is on the same machine allowing local LAN access without having to use any public IP/DNS. Ironically, LOCAL_IP:8080 did still work from mobile.

Was also able to accomplish this in the docker-compose.yml with:

  - OWNCLOUD_OVERWRITE_PROTOCOL=https

But, setting it in the .env didn’t to take effect.

1 Like