SSL enabled causes infinite 301.

5 months ago
4.50
I have an Nginx reverse proxy with an SSL cert installed that works fine. When I forward requests to nop without enabling ssl in nop's settings, some of the page is secure and others (like resources and images) are not using https.

So I go into the settings and I enable SSL for the store (and change the store's url to Https).
Suddenly, all pages on the site redirect infinitely with a 301 to the same url until my browser throws an error. According to logs, nop is the server which is replying with the 301 (not nginx), and I'm not sure where or why.

My appsettings hostconfig:

"HostingConfig": {
    "UseHttpXForwardedProto": true,
    "UseProxy": false,
    "ForwardedProtoHeaderName": "",
    "ForwardedForHeaderName": "",
    "KnownProxies": ""
  },


My nginx location block:

    location / {
        proxy_pass         http://nopcommerce_web; # container orchestration DNS resolves name to nop server
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }


Via the suggestion of https://docs.nopcommerce.com/en/getting-started/advanced-configuration/how-to-install-and-configure-ssl-certification.html
I have done:
-Cleared browser cache and cookies to make sure it wasn't the browser storing the 301
-Cleared server/nginx cache
-Checked that there were no other possible redirects in nginx or hosting which could be causing a loop. The 301 header comes directly from nop, reaches the browser, and the subsequent request reaches all the way back to nop where it sends a 301 again.
-I am not using a cdn or cloudflare. The DNS name for my site points directly to my server's IP.

The redirect chain is like so:
https://example.com/ returns 301 to https://example.com/
https://example.com/ returns 301 to https://example.com/
https://example.com/ returns 301 to https://example.com/
https://example.com/ returns 301 to https://example.com/
It doesn't change between redirects, the same page returns the same page.
5 months ago
Hi there,
It's because of you have set up "UseHttpXForwardedProto": true
this field needs to be set true only when your hosting uses a load balancer. It'll be used to determine whether the current request is HTTPS.
Please turn it to false, then restart your application, hopefully it will solve your problem.
5 months ago
Thank you for the response, unfortunately disabling "UseHttpXForwardedProto" has not fixed the problem.
5 months ago
I think you can't have the https setting in Nop that would trigger the 301 because Nop does not have a tls certificate only nginx. To fix the mixed content when tls is turned of in Nop you should redirect 80 traffic in nginx to 443

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;
  return 301 https://$host$request_uri;
}
more info https://linuxize.com/post/redirect-http-to-https-in-nginx/
5 months ago
Unfortunately, I have that redirecting location block already in my nginx config and it works fine. When SSL is disabled on nop, the actual html it delivers includes a bunch of http links, which correctly redirect, but still produces the warning.
5 months ago
Ralek wrote:


My appsettings hostconfig:

"HostingConfig": {
    "UseHttpXForwardedProto": true,
    "UseProxy": false,
    "ForwardedProtoHeaderName": "",
    "ForwardedForHeaderName": "",
    "KnownProxies": ""
  },



Please, remove "UseHttpXForwardedProto" and set "UseProxy" to true value.

Ralek wrote:

Via the suggestion of https://docs.nopcommerce.com/en/getting-started/advanced-configuration/how-to-install-and-configure-ssl-certification.html


Unfortunately, the article is currently outdated, we'll update it soon.
5 months ago
Below is my working NGINX conf (domain name replaced). Also, appsettings.json has UseHttpXFrowardProto: true


  "HostingConfig": {
    "UseHttpClusterHttps": false,
    "UseHttpXForwardedProto": true,
    "ForwardedHttpHeader": ""
  }






#
server {
    listen 80;
    listen [::]:80;

    server_name   mydomain.co.uk mypublicipaddress;
  return 301 https://mydomain.co.uk;

  }


server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name mypublicipaddress;

    ssl_certificate /var/ssl/mydomain_co_uk/mydomain_co_uk_bundle.crt;
    ssl_certificate_key /var/ssl/mydomain_co_uk/mydomain_co_uk.key;
    return 301 https://mydomain.co.uk$request_uri;
}

server {
    listen 443;
    listen [::]:443;

    server_name   mydomain.co.uk;


    location / {
    proxy_pass         http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection keep-alive;
    proxy_set_header   Host $host;
    proxy_cache_bypass $http_upgrade;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    }

    ssl on;
    ssl_certificate /var/ssl/mydomain_co_uk/mydomain_co_uk_bundle.crt;
    ssl_certificate_key /var/ssl/mydomain_co_uk/mydomain_co_uk.key;

    ssl_stapling on;
    ssl_stapling_verify on;



    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
    #
    # Note: You should disable gzip for SSL traffic.
    # See: https://bugs.debian.org/773332
    #
    # Read up on ssl_ciphers to ensure a secure configuration.
    # See: https://bugs.debian.org/765782
    #
    # Self signed certs generated by the ssl-cert package
    # Don't use them in a production server!
    #
    # include snippets/snakeoil.conf;
}





5 months ago
Unfortunately neither suggestion seems to be working, it still infinitely 301's.

Here is my hostingConfig:

"HostingConfig": {
    "UseProxy": true,
    "ForwardedProtoHeaderName": "",
    "ForwardedForHeaderName": "",
    "KnownProxies": ""
  },


And my full nginx config: (Removing the first 2 server blocks doesn't change anything, they're to remove the WWW and switch http to https, respectively)


server {
  server_name www.my-site.com;
  return 301 $scheme://my-site.com$request_uri;
}
server {
    listen 80;
    listen [::]:80;
    server_name my-site.com;

    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name my-site.com;

    ssl_certificate /etc/letsencrypt/live/my-site.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-site.com/privkey.pem;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    location / {
        proxy_pass         http://nopcommerce_web; # DNS resolves name to nop server
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}



And here is the full code that gets repeated each time the server receives a request, it gets repeated about 10 times or so:


nopcommerce_nginx      | 45.132.227.30 - - [08/Apr/2022:20:17:56 +0000] "GET / HTTP/1.1" 301 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0" "-"
nopcommerce_web        | {"EventId":1,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Hosting.Diagnostics","Message":"Request starting HTTP/1.1 GET http://my-site.com/ - -","State":{"Message":"Request starting HTTP/1.1 GET http://my-site.com/ - -","Protocol":"HTTP/1.1","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"http","Host":"my-site.com","PathBase":"","Path":"/","QueryString":""}}
nopcommerce_web        | {"EventId":0,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Routing.EndpointMiddleware","Message":"Executing endpoint \u0027Nop.Web.Controllers.HomeController.Index (Nop.Web)\u0027","State":{"Message":"Executing endpoint \u0027Nop.Web.Controllers.HomeController.Index (Nop.Web)\u0027","EndpointName":"Nop.Web.Controllers.HomeController.Index (Nop.Web)","{OriginalFormat}":"Executing endpoint \u0027{EndpointName}\u0027"}}
nopcommerce_web        | {"EventId":3,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker","Message":"Route matched with {action = \u0022Index\u0022, controller = \u0022Home\u0022, area = \u0022\u0022}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Index() on controller Nop.Web.Controllers.HomeController (Nop.Web).","State":{"Message":"Route matched with {action = \u0022Index\u0022, controller = \u0022Home\u0022, area = \u0022\u0022}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Index() on controller Nop.Web.Controllers.HomeController (Nop.Web).","RouteData":"{action = \u0022Index\u0022, controller = \u0022Home\u0022, area = \u0022\u0022}","MethodInfo":"Microsoft.AspNetCore.Mvc.IActionResult Index()","Controller":"Nop.Web.Controllers.HomeController","AssemblyName":"Nop.Web","{OriginalFormat}":"Route matched with {RouteData}. Executing controller action with signature {MethodInfo} on controller {Controller} ({AssemblyName})."}}
nopcommerce_web        | {"EventId":3,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker","Message":"Authorization failed for the request at filter \u0027Nop.Web.Framework.Mvc.Filters.HttpsRequirementAttribute\u002BHttpsRequirementFilter\u0027.","State":{"Message":"Authorization failed for the request at filter \u0027Nop.Web.Framework.Mvc.Filters.HttpsRequirementAttribute\u002BHttpsRequirementFilter\u0027.","AuthorizationFilter":"Nop.Web.Framework.Mvc.Filters.HttpsRequirementAttribute\u002BHttpsRequirementFilter","{OriginalFormat}":"Authorization failed for the request at filter \u0027{AuthorizationFilter}\u0027."}}
nopcommerce_web        | {"EventId":1,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Mvc.Infrastructure.RedirectResultExecutor","Message":"Executing RedirectResult, redirecting to https://my-site.com/.","State":{"Message":"Executing RedirectResult, redirecting to https://my-site.com/.","Destination":"https://my-site.com/","{OriginalFormat}":"Executing RedirectResult, redirecting to {Destination}."}}
nopcommerce_web        | {"EventId":2,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker","Message":"Executed action Nop.Web.Controllers.HomeController.Index (Nop.Web) in 5.6776ms","State":{"Message":"Executed action Nop.Web.Controllers.HomeController.Index (Nop.Web) in 5.6776ms","ActionName":"Nop.Web.Controllers.HomeController.Index (Nop.Web)","ElapsedMilliseconds":5.6776,"{OriginalFormat}":"Executed action {ActionName} in {ElapsedMilliseconds}ms"}}
nopcommerce_web        | {"EventId":1,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Routing.EndpointMiddleware","Message":"Executed endpoint \u0027Nop.Web.Controllers.HomeController.Index (Nop.Web)\u0027","State":{"Message":"Executed endpoint \u0027Nop.Web.Controllers.HomeController.Index (Nop.Web)\u0027","EndpointName":"Nop.Web.Controllers.HomeController.Index (Nop.Web)","{OriginalFormat}":"Executed endpoint \u0027{EndpointName}\u0027"}}
nopcommerce_web        | {"EventId":2,"LogLevel":"Information","Category":"Microsoft.AspNetCore.Hosting.Diagnostics","Message":"Request finished HTTP/1.1 GET http://my-site.com/ - - - 301 0 - 13.0938ms","State":{"Message":"Request finished HTTP/1.1 GET http://my-site.com/ - - - 301 0 - 13.0938ms","ElapsedMilliseconds":13.0938,"StatusCode":301,"ContentType":null,"ContentLength":0,"Protocol":"HTTP/1.1","Method":"GET","Scheme":"http","Host":"my-site.com","PathBase":"","Path":"/","QueryString":""}}
nopcommerce_nginx      | 45.132.227.30 - - [08/Apr/2022:20:17:56 +0000] "GET / HTTP/1.1" 301 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0" "-"
5 months ago
JonQuick wrote:


    location / {
    proxy_pass         http://localhost:5000;
    }


Is there a reason you're using port 5000 here specifically, or just chose that? I haven't defined the port on my proxy_pass. But when I set it to 5000 or 443 Nginx returns a bad gateway.

Nginx and Nop are both running in separate docker containers under a virtual network, so dns names such as 'nopcommerce_web' get resolved into the local IP of that container.
5 months ago
Is there an update to this issue? How can I be the only one facing this with a completely fresh install? Do people just not use SSL with their nop stores? I'm thinking about just launching my site with 4.40 or older, whatever version allows SSL because I've tried just about everything with 4.50.