Remove Access-Control-Allow-Origin defined in web.config with ASP.NET - asp.net

We have a definition in web.config to set Access-Control-Allow-Origin header for all requests to one predefined server. like this:
<customHeaders>
<add name="Access-Control-Allow-Origin"value="http://constantServer.com" />
<add name="Accept-Bytes" value="none" />
</customHeaders>
there are some cases we need to allow access to different server to a specific resource. we check the origin and set the Access-Control-Allow-Origin by code, like this:
Response.AddHeader("Access-Control-Allow-Origin", origin);
Response.AddHeader("Access-Control-Allow-Credentials", "true");
The problem is that the browser get multiple values for the Access-Control and its not allowed it.
We want to remove by code the header that was defined in the web.config in cases that we need to allow it for different origin.
I tried to remove it at the global.asax in the Application_PreSendRequestHeaders event, but i didnt find this header there.(its seems that this header is being added after this event)
Thanks

See this answer for more details on IHttpModule solution on how to change a header value. It was about the Server default header added by IIS, which I believe to be the harder case to handle.
This question provides a lot of other options in its answers, including installing and using URL Rewrite (direct link to corresponding answer).
You may by example change your code to only add the Access-Control-Allow-Credentials, then write a URL Rewrite rule for changing Access-Control-Allow-Originto origin.
<system.webServer>
...
<rewrite>
<outboundRules>
<rule name="handleCredentialCors" preCondition="credential">
<match serverVariable="Access-Control-Allow-Origin" pattern=".*" />
<action type="Rewrite" value="origin" />
</rule>
<preConditions>
<preCondition name="credential">
<add input="{RESPONSE_Access_Control_Allow_Credentials}" pattern="true" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
...
</system.webServer>
(Untested)
My bad, I have overlooked origin was a local variable, not a literal string.
Well, if you can infer that origin value from server variables (which in URL rewrite include request headers), URL Rewrite may still get the job done. It is able of extracting values then reusing them in the rewritten value. But the rule could be a bit more complex to write.

Related

ASP.NET 4 WebApi: route with back slash

I have a WebApi-route api/{type}({id})/{prop}
and I want to call it with url like /api/User(domain\username)/groups - the key point is "\" in id value. I send it from the client url-encoded i.e. as:
api/User(domain%5Cusername)/groups. But the route is ignored and I'm getting 404.
How to pass back slash into a route's argument?
As #ATerry suggested in comments the problem is not with ASP.NET but in HTTP.SYS + IIS. Back-slashes are replaced by HTTP.SYS onto forward-slashes even before coming to IIS.
We can work this around with help of UrlRewrite IIS-module as it has access to original (undecoded) url.
For my example I came up with the following rule.
<rule name="allow backslash" stopProcessing="true">
<match url="api/(.*)\((.*)\)(.*)" />
<action type="Rewrite" url="api/{R:1}({C:1}{C:2}{C:3}){R:3}" logRewrittenUrl="true" />
<conditions>
<add input="{UNENCODED_URL}" pattern="\((.*)(%5C)(.*)\)" />
</conditions>
</rule>
It's not ideal as it's very specific. It'd more useful to have a generic rule which just processes %5C.
The idea is to catch an url with %5C and rewrite it to put it back. It's a little bit weird but it works.
Besides the rule we need to set allowDoubleEscaping=false in system.webServer/security/requestFiltering:
<security>
<requestFiltering allowDoubleEscaping="true">
</requestFiltering>
</security>
With this rule the value come into a Mvc/Api controller will be encoded (with %). So we'll have to decode it:
public virtual DomainResult GetObjectProp(string type, string id, string prop)
{
id = Uri.UnescapeDataString(id);
}

URL Rewrite rule with HTTP headers

I'm trying to use the URL Rewrite module of IIS to redirect my users to Another application/site on the IIS server, however I need to retain the custom HTTP headers included for authentication purposes, but they seem to get lost in the rewrite. Does anyone know if, and how, the rules must be setup in order to include those HTTP headers when sending the user on his/her merry way?
This is the rule, as per today:
<rewrite>
<rules>
<rule name="API Redirect">
<match url="/API/Tracker/\d{1,2}.\d{1,2}/(.*)" />
<action type="Rewrite" url="/Tracker/1.0/tracker.svc/{R:1}" appendQueryString="false" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
I was having problems with something similar. I kept losing some Cache-Control headers that I was attempting to use.
The below was able to help me out. I'm not sure how you would go about doing this if you wanted your headers to have dynamic values, but this worked for me.
I came to this while using IIS 8.5.
Go into your site, and in IIS > HTTP Response Headers
Then add the custom header that you would want to use and the value. Again, I'm not sure how you would go about doing this if you needed the header to have a dynamic value.
Have you tried to enable querystring?
appendQueryString="true"
Just wanted to share a solution that would apply a custom http header based on the current URL - not sure if this is exactly what you are looking for but it worked for me when I wanted to add a X-Robots-Tag to all requests to our admin-page.
In web.config, add this:
<location path="admin">
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="X-Robots-Tag" />
<add name="X-Robots-Tag" value="noindex"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</location>

Regex to extract a part out of a URL and use it as a reference in url rewrite

OK, I'm wondering if someone can lend a hand with a regex I'm trying to write.
Basically, what I want to do is use IIS urlrewrite module to do a redirect to a specific URL if the user accesses a URL on another site. The only catch is I have to also capture a bit of the query string, and move it into the redirect. I think I actually DO have the regex correct for this, but it's implementing it in my web.config that is causing the problem.
so here is the input, the URL that a user may access would look like:
https://of.example.com/sfsv3.aspx?waform=pro&language=en
I want to match that URL (either http or https, case insensitive), and capture from it also one piece of information, the two letter language code. then the url i want to forward the user to looks like:
http://example.com/ca/en/ppf
(where en is replaced by whatever i captured above)
So, I'm working with IIS Rewrite module, and I've gotten my input data and regex in, so far the regex pattern I have is this:
https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))
so basically i'm matching the whole string, plus a group and a subgroup for language and it's code. in the IIS test pattern dialog, this is working.
I get the following
{R:1} language=en
{R:2} en
great! so then my IIS rewrite rule should look like this to redirect the user:
<system.webServer>
<rewrite>
<rules>
<rule name="test" stopProcessing="true" enabled="true">
<match url="https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))" ignoreCase="true" />
<action type="Redirect" url="http://www.example.com/ca/{R:2}/ppf" />
</rule>
</rules>
</rewrite>
</system.webServer>
this all seems right to me. however, IIS is balking and saying that my web.config is invalid. specifically, it says "Entity '(' is not defined" and it's pointing to the ( right before language as the problem. So, I can't build or deploy this application till I fix that. If i build it without and then just try to drop that into the web.config, i get an error loading the site:
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Can someone help me figure out how to put a capture group into a rewrite rule properly?
You forgot to code the ampersand. Should be:
<system.webServer>
<rewrite>
<rules>
<rule name="test" stopProcessing="true" enabled="true">
<match url="https?://of.example.com/sfsv3.aspx\?waform=pro&(language=(..))" ignoreCase="true" />
<action type="Redirect" url="http://www.example.com/ca/{R:2}/ppf" />
</rule>
</rules>
</rewrite>

Using Url Rewrite to change REMOTE_ADDR works for files but not folders

I have a number of websites that make use of the REMOTE_ADDR server variable to record client IPs for metrics. In moving the hosting of these sites into a load balanced environment we're now only ever getting the load balancer IP in REMOTE_ADDR. I'm fully aware of the use of HTTP_X_FORWARDED_FOR and how it works and we do have access to it and my preferred solution is to simply update the applications to use it.
However, the powers that be here want to avoid having to update all of the websites :( I'm looking into alternatives in the mean time.
Ultimately this means finding some way of replacing REMOTE_ADDR with HTTP_X_FORWARDED_FOR before the request hits the applications.
I'm trying to get the URL Rewrite 2.0 module working using advice from another acole76's question here:
IIS 7 Rewrite web.config serverVariables directive not working in sub folder
My web.config is practically the same as his:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="RemoteHostRewrite">
<match url="(.*)" ignoreCase="true" />
<serverVariables>
<set name="REMOTE_ADDR" value="4.3.2.1" />
</serverVariables>
<action type="Rewrite" url="{R:0}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I'm using a hard-coded value 4.3.2.1 here for testing. I'll eventually replace that with the real value {HTTP_X_FORWARDED_FOR}.
Now, this works absolutely fine if a url contains a file name. It does not work if the url does not end with a file name.
For example:
mysite.local/default.aspx - works
mysite.local/ - does not work
mysite.local/folder/default.aspx - works
mysite.local/folder/ - does not work
I'm stumped! Can anyone offer any help?
you have to set another rule:
<match url="^$" />
<action type="Rewrite" url="/default.aspx" />
or whatever your default-page is
otherwise "url" will be empty --> no rule used

iis rewrite url with dot at end of url

I have some external links coming into my site which mistakenly had a period added to their ends. (so, I can't fix them). Since inbound links are always good, I want to redirect these links to a legit page. I've tried a number of rules in the urlrewrite module for iis.5 and nothing seems to capture this url.
I've seen other questions on here regarding asp.net urls with periods at the end, but I'm trying to capture this one at the IIS rewrite module level. Any pointers on making this work?
This is quite an old one but as i was facing similar issue recently i've decided to post my findings...
I assume that one of modules that run prior to url-rewrite module terminates, with an exception, preventing request from continuing to url-rewrite (i suspect some security checks). Thus it is not possible to resolve your issue with url-rewrite.
One possible workaround could be to redirect requests ending with dot '.' at the very early stage in Global.asax, like here:
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
if (Context.Request.RawUrl.EndsWith(".aspx."))
{
//permanent redirect and end current request...
Context.Response.RedirectPermanent(Context.Request.RawUrl.TrimEnd('.'), true);
}
}
That might be far from optimal answer but at least it gets job done ;)
I used a solution that removes all trailing dots at the web.config level:
<rule name="RemoveTrailingDots" stopProcessing="false">
<match url="^(.*[^.])\.+$" />
<action type="Rewrite" url="{R:1}" />
</rule>
This rule just rewrites the request url internally at the beginning of my rewrite rules, allowing the request to process through the normal rules instead of being caught upstream
If you don't have any more rules to apply, and just want to redirects anything with dots at the end, just change the action type to Redirect (case sensitive)
If you have a fixed set of inbound links that are incorrect, you can concentrate on redirecting the main part of the URL, rather than the dot.
For example, with this URL:
http://www.example.com/index.html.
Have your IIS Rewrite look for a URL matching "^index.html.*" and redirect to the page you need. That should catch the URL both with and without the dot.
On IIS 8.5 I implemented something substantially similar to that proposed by GWR but with one subtle change. I needed the attribute appendQueryString="true" on the Rewrite action tag. (Perhaps this was the default back in 2016, but now needs to be specified.)
Here's what worked for me:
<system.webServer>
<modules>
...
</modules>
<validation validateIntegratedModeConfiguration="false" />
<rewrite>
<rules>
<rule name="RemoveTrailingDots">
<match url="^(.*[^.])\.+$" />
<action type="Rewrite" url="{R:1}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
I had to install the URL Rewrite feature from here: https://www.iis.net/downloads/microsoft/url-rewrite

Resources