Redirect Response always redirects to the same domain - asp.net-core

I'm writing a suite of ASP.NET Core web applications that occasionally have to redirect to one another. When testing locally, everything works fine. However, when I publish them on our staging server, the redirects always "stay" in the same host. For example, if I am on http://app1.test/ and redirect to http://app2.test/somepath, what I actually get in the Location HTTP header i http://app1.test/somepath: any URL I specify is transformed so that it "stays" in the current host name.
This doesn't happen locally, however. I've deployed the apps as Kestrel processes, and they are exposed via IIS working as a reverse proxy. May this be the cause? What should I do to fix the issue?
UPDATE
Here is the full web.config for the reverse proxy of app1.test:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:5000/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
<system.web>
<sessionState mode="InProc" />
<customErrors mode="RemoteOnly" />
</system.web>
</configuration>
app2.test's web.config is virtually the same (apart, of course, for the port numbers).
UPDATE 2
I'll try to explain better. I noticed that the target site doesn't really matter, so I'll keep things simpler: I have an action in my application that I want to redirect the user to Google. This is the action, in the Home controller:
public IActionResult ToGoogle()
{
return Redirect("https://www.google.com?q=Hi");
}
If I launch the web app locally and request http://localhost:1234/Home/ToGoogle, everything is fine: the response is a 302 Found, with the correct URL (www.google.com etc.) in the Location header.
Once I publish the app to the staging server (Kestrel app on port 5000, behind an IIS reverse proxy with the rewrite rule posted above), this is what happens instead:
What is the cause of that?

I found the solution myself. It was indeed a problem with reverse proxy.
IIS has an option to rewrite the host in response headers. The solution is described in this answer (there are addenda in other answers to that same question if your version of IIS or Windows Server is not the one specified).

Related

IIS blue-green deployment using ARR

I am trying to figure out steps for deploying on IIS using ARR (Application Request Routing).
The setting was guided by this article https://kevinareed.com/2015/11/07/how-to-deploy-anything-in-iis-with-zero-downtime-on-a-single-server/
Based on the above article - everything works, but only when using http.
Only if we enable SSL (443 port) - everything stops working at once.
What was done:
Two sites, let's say devblue.somedomain.com and devgreen.somedomain.com, both use the following bindings 8001 and 443 and 8002 and 443
A farm has been brought up with the name let's say develop.somedomain.com
The above servers have been added to the develop.somedomain.com farm pool
Healthchecks are set up
Wildcard certificates added to IIS
Added entries to the HOSTS file for develop, devblue and devgreen, all pointing to 127.0.0.1
Set up an inbound URL Rewrite rule, to direct any requests for "develop" to the Server farm (This is one example of a global farm rule that I have used)
<rule name="develop HTTPS" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{SERVER_PORT}" pattern="^443$" />
<add input="{HTTP_HOST}" pattern="^develop.somedomain.com$" />
</conditions>
<action type="Rewrite" url="https://develop.somedomain.com/{R:0}" />
</rule>
SSL off-loading checkbox unchecked.
I can request the blue and green sites individually. The health checks for the web farm seem to be working, so when I edit one from "down" to "up", it becomes healthy, and vice versa.
The problem is when requesting https://develop.somedomain.com - it is not routing to one of the servers in pool, so I suspect the problem is in the URL Rewrite rule (maybe I need more rules).
I've tried a lot of methods and different articles, connected sites to the farm on different https ports as well (8443 and 9443 for example), tried with and without offloading ssl.
Found some mentions to add HTTP_X_ARR_SSL but unfortunately I didn't get it right (should it be added to some rule or separately, I tried it both ways), but nothing works.
How do I figure out what is wrong? Can you please advise who had similar experience of configuration

How to enforce HTTPS only (no redirect, block HTTP) on Azure App Service / Web App

Microsoft's own documentation on HSTS says the following regarding HSTS, HTTPS redirection, and APIs:
Web APIs should either:
Not listen on HTTP.
Close the connection with status code 400 (Bad Request) and not serve the request.
…
… a single authenticated call to an API over HTTP has risks on insecure networks. The secure approach is to configure API projects to only listen to and respond over HTTPS.
My takeaway is: APIs should not redirect, since clients may happily send sensitive data over HTTP and everything "just works" due to the redirection. Even for browsers and when using HSTS, the first request (with potentially sensitive data) may be done using HTTP. Instead, APIs should fail HTTP requests and respond only via HTTPS.
After having spent the better part of the day researching this, I find that in Azure App Service / Web App, there seems to be no simple way to follow these recommendations. Regardless of whether "HTTPS Only" is On or Off, the API can be called via HTTP: If On, it redirects to HTTPS, and if Off, it's fully available with HTTP without redirection. One would think there'd be a simple way to make the app service / web app listen only over HTTPS. For example if the "HTTPS Only" button was Off/Redirect/On.
The documentations says that:
To disable HTTP redirection in an API, set the ASPNETCORE_URLS environment variable or use the --urls command line flag. For more information, see Use multiple environments in ASP.NET Core and 5 ways to set the URLs for an ASP.NET Core app by Andrew Lock.
Unfortunately, neither of these two links describe whether this is relevant for App Service / Web App, or what the environment variables should be. I have not been able to get it to work. It also seems that this would require duplicating any custom domains, forcing you to remember to keep the environment variable in sync with changes to custom domains.
How can I make Azure App Service / Web App listen only on HTTPS?
My current workaround is to deploy the following web.config which, ironically, requires "HTTPS Only" to be Off for the HTTP request to reach the app service and be rejected. However, it does do the job of ensuring that no HTTP-only API clients will be developed, since they simply won't work from the outset.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Disable HTTP" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
<add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
</conditions>
<action type="CustomResponse" statusCode="400" statusReason="HTTPS Required" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
(Conditions from this blog post.)
If anyone has a better, simpler, or more official method, I'll gladly accept that answer. Also, I'm not sure the the WARMUP_REQUEST part works (copied from elsewhere); if I change CustomResponse to AbortRequest, the slot swap operation fails because the warmup requests are dropped.

How to properly configure IIS URL Rewrite

I am running IIS 8.5 on Win 2012 R2. I have a website under which I have hosted multiple .Net Core 3.1 WebAPIs, each running under its own non-managed app pools.
wwww.myrootsite.com -> this is site binding on the Website in IIS
|-> API.Employees -> Separate app running on non-managed AppPool1
|-> API.Departments -> Separate app running on non-managed AppPool2
Within API.Employees, lets say I have 2 controllers mapping to /api/employees and api/teams.
Currently, for UI, the endpoint looks like this.
https://wwww.myrootsite.com/API.Employees/api/employees
https://wwww.myrootsite.com/API.Employees/api/teams
I want URLs to look like this.
https://wwww.myrootsite.com/api/employees
https://wwww.myrootsite.com/api/teams
I already have ARR 3.0 and URL Rewrite 2.0 modules installed on the server.
So I tried creating an inbound rule for api/teams. This is what I have currently configured.
<rewrite>
<rules>
<rule name="API.Employees.Teams Rewrite" stopProcessing="true">
<match url="^api/teams?(.*)" />
<action type="Rewrite" url="API.Employees/{R:0}" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
However, when I try to access the URL https://wwww.myrootsite.com/api/teams?id=100, I get 500 internal server error. I am not able to get further details of what is causing the 500 error. Can anyone kindly point out, what am I doing wrong and how do I get further details of the error?
Thanks!

Azure Cloud Service redirect http to https not working (tried answers on many links)

I'm trying to do the 'simple' task of redirecting/rewriting traffic from http to https, I have one endpoint in a CloudService which is correctly configured for SSL.
I've tried many IIS rewrite rules, like the one below, but none are working. I've also tried setting up the rules via remote desktop on the IIS 8 server directly which also doesn't work.
When I enter any tag in the Azure web.config file the rewrite tag has a blue line under it with a message saying it is invalid under <system.webServer> :
<system.webServer>
...
<rewrite>
<rules>
<rule name="RedirectToHTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{SERVER_NAME}/{R:1}" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>
</system.webServer>
Any advice is much appreciated.
In order for these rules to work you have to configure both the endpoints - HTTP and HTTPS !!
If you have not configured plain HTTP endpoint on port 80, your server will never be hit by an Internet traffic, so rewrite rules will never trigger.Thus you get the timeout when you try opening the domain over plain HTTP. There is simply no process listening on port 80 when you haven't defined endpoint for it.

https://www.mydomain.com and https://mydomain.com go to different pages

Web Server: IIS 6.0 (ASP.Net 4.0)
I host two sites: one is the main web site and the other is the store site. Each are separate web sites in IIS. Each share the same wildcard SSL certificate. The store site uses a Host Header (store.mydomain.com) to direct traffic to it.
I want it so any URL used without the sub-domain "store" directs the user to the main web site, not the store web site.
The problem I'm experiencing is that the following URL always directs users to the default.aspx page on the store web site:
https://www.mydomain.com
Yet, these URLs correctly go to the main page on the main web site:
http://mydomain.com
http://www.mydomain.com
https://mydomain.com
What's up with the https://www that directs users to different page?
I have added a rewrite rule in the web.config file for both sites but it doesn't have any effect:
<rewrite>
<rules>
<rule name="Consistent Domain" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_HOST}" pattern="^mydomain.com$" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="http://www.mydomain.com/{R:1}" />
</rule>
</rules>
</rewrite>
First, are you sure this is IIS6? The URLRewrite feature is part of IIS7 and would have no effect under IIS6 if present. If this is IIS6 that may well be the answer to your question.
That aside, it is difficult to answer this based on the data given. It is possible that the bindings of the sites is incorrect and resulting in the traffic going to a site you don't expect.