Azure App Service terminating https before application? [duplicate] - c#

This question already has answers here:
Is current request being made over SSL with Azure deployment
(2 answers)
Closed 3 months ago.
I'm building an asp.net core web application on framework 2.2 and hosting on an azure app service on a linux app service plan.
Inside my application I inspect HttpRequest.Scheme. Running locally this returns https if I make a request using https. Running on azure it returns http.
It appears Azure App Services is terminating the SSL connection and proxying to my app. Is there a way to configure Azure App Services so the https request makes it to my application unmodified? Or at least HttpRequest.Scheme matches the original request?
I've built a sample diagnostic page to show this behavior:
var healthStatus = new
{
Port = context.Request.Host.Port?.ToString() ?? "unknown",
context.Request.Scheme,
context.Request.IsHttps,
Headers = context.Request.Headers.Select(x => $"{x.Key}:{x.Value}").ToArray()
};
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(healthStatus));
Debugging in VS Locally: https://localhost:1234/ping:
{
"Port":1234,
"Scheme": "https",
"IsHttps": true,
"Headers": <standard headers - nothing interesting>
}
Deploying to Azure App Services: https://appServiceExample.myDomain.com/ping:
{
"Port":"unknown",
"Scheme": "http",
"IsHttps": false,
Headers: [
// there are several more headers, but only these looked interesting:
"X-Forwarded-For:195.206.xxx.xxx:6922",
"X-Forwarded-Proto:https",
"X-AppService-Proto:https"
]
}
As a workaround: Could I solve this problem my relying on the X-AppService-Proto or X-Forwarded-Proto header? But this seems a bit of a hack, as I'd rather inspect the original incoming request - and I'm unsure how reliable these headers are.

Just summarize your comment.
The Azure App Service frontend layer TERMINATES the TLS channel (aka TLS offloading) and opens a new plain HTTP connection to your Web Worker, where your code lives. Routing is performed by ARR (Application Request Routing).
Therefore, from the point of view of your code every single request is "insecure".
X-Forwarded-Proto=https hints about the original request (that hit the frontends).
If checks have to be made, make them against X-ARR-SSL instead.
For more details, you could refer to this SO thread.

Related

Self-hosted SignalR in Windows .Net Service blocked by CORS on same server, works on other servers

I've been using a Self-Hosted SignalR Windows service accessed from multiple production servers (now in Azure) for 6+ years without a problem. I created an identical server for development in Azure but when I'm accessing SignalR from a browser on the SAME SERVER, SignalR gives me the following error when using either http:6287 or https:6286:
Access to XMLHttpRequest at 'http://myserver.learn.net:6287/signalr/negotiate?clientProtocol=1.5&xxxxxxx' from origin 'http://myserver.learn.net' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
However... It WORKS when connecting from OTHER SERVERS! I'm starting the connection with no errors using:
SignalR = WebApp.Start("http://myserver.learn.net:6287/");
SignalRSSL = WebApp.Start("https://myserver.learn.net:6286/");
(also SignalR = WebApp.Start("*:628x/" for both);
In my client code, I include the following script:
<script src="http://myserver.learn.net:6287/signalr/hubs"></script>
When I enter that url (or https version) in a browser ON THE SAME OR DIFFERENT SERVER, it shows the ASP.NET SignalR JavaScript Library v2.3.0-rtm page correctly! I've turned off the firewall with no change, added Microsoft.Owin.Host.HttpListener (someone suggested). I have also entered the wildcard certificate with netsh so the SignalR service can deal with the SSL connection using:
netsh http add sslcert ipport=0.0.0.0:6286 appid={12345678-db90-4b66-8b01-88f7af2e36bf} certhash=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Edit: I've also tried changing the ipport value to the real internal IP of the server as well as the public IP but no change.
So, why can't I access SignalR from the same server?
I found a solution in another answer here that worked. I changed:
$j.connection.hub.start().done(function () {
To:
$j.connection.hub.start({ jsonp: true, xdomain: true }).done(function () {
Which worked for both internal and external clients. xdomain:true alone didn't work but when I added jsonp:true it did. I have no real idea why, just that it's working now.

Asp.Net Core 2.0 HTTP -> HTTPS on Kestrel

I am learning Web-Based Programming and currently chose to work on Asp.Net Core 2.0.
I had successfully created a Web App with 2 layers of Controllers Home & API.
The Home Controller interacts directly with my Views while the API controller is called using GetAsync, PostAsync, PutAsync, etc. from my Home controller.
Recent I decided to move this app into HTTPS. Learned about self-signed certificates and had successfully gotten it to run except my API becomes inaccessible.
With SSL switched off, I could still call my API with Postman.
I used to call my API using this URI: http://localhost:5667/api/WebApi.
var response = client.GetAsync(“SomeApi”)
response.Wait();
Now I tried using URI: https://localhost:5667/api/WebApi but breaks at response.Wait().
Any advice, please. Thanks in advance
As requested: here’s a portion of my Startup.cs
services.AddMvc(
options =>
{
options.SslPort=5667;
options.Filters.Add(new RequireHttpsAttribute());
}
);
services.AddAntiforgery(
options =>
{
options.Cookie.Name=“_af”;
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy=CookieSecurePolicy.Always;
options.HeaderName=“X-XSRF-TOKEN”;
}
)
HTTP and HTTPS cannot be served over the same port. If your localhost HTTP endpoint is on 5667, then likely your HTTPS endpoint is on 5668 - though you can check the port number for yourself in the info that Kestrel will log on startup.
In production, HTTP is typically served over port 80, while HTTPS is served over port 443. These are the defaults if you don't specify otherwise.
Separately, you might want to consider enabling HTTPS redirection in your Configure block:
app.UseHttpsRedirection();

Mobile devices with credentials flag to true

I have to send credentials to authenticate on the server (windows authentication) for my application:
with-credentials = true
The problem is that my clients are mobile devices, and I can't tell to the server in Access-Control-Allow-Origin the origin domains.
I would like to do that:
Access-Control-Allow-Origin = *
But I know it is not possible because of security issues.
How can I do that with HTTP?
PS: I am using a server in ASP.NET and clients are made with Ionic (Angular). Currently, I am using a temporary solution:
Access-Control-Allow-Origin = localhost:8100
But when I will deploy the application it won't work on real devices.
From enable-cors.org:
CORS In ASP.NET
If you don't have access to configure IIS, you can still add the header through ASP.NET by adding the following line to your source pages:
Response.AppendHeader("Access-Control-Allow-Origin", "*");
See also: you can also Configure IIS6 / IIS7
Reference Taken
Sometimes you need to check this wihtin your AuthorizeAttribute
// pre-flight request (OPTIONS) are always ok.
// https://stackoverflow.com/questions/26296779/chrome-v37-38-cors-failing-again-with-401-for-options-pre-flight-requests#28235624
if (actionContext.Request.Method == System.Net.Http.HttpMethod.Options)
{
return true;
}

Deploy WebAPI alongside web site in IIS on port 80

I believe this might be a troublesome request but I want to give it due diligence because I didn't know how best to respond to the requester.
We have an AngularJS client that is making a call through $resources to RESTful ASP.NET WebApi services deployed to IIS.
When I was demoing the connections, I served the WebApi on port 56730 out of Visual Studio (IIS Express) and my client's service is structured something like this:
app.service('repository', ['$resource', function ($resource) {
var repository = $resource(
'http://localhost:56730/api/Foo/:component',
{},
{
bars: {
method: 'GET'
,isArray: false
,url: 'http://localhost:56730/api/Foo/bars'
}
}
);
return repository;
}]);
To cut right to the chase, he was wondering why the WebAPI was not being served on Port 80 seeing as how it is "just serving json data." I wanted to respond that it's running inside its own process and the http server is running on port 80, but I wanted to respect his request on the off chance that I can deploy an ASP.NET WebApi project side-by-side with a client site on port 80.
I think this essentially boils down to the desire to have the "/api/{controller}/{id}" area of the site handled by WebAPI and have the http://server.com/resource requests handled as static resources.
Can it be done?
If it can, is it worth the trouble?

Using WCF service in MonoTouch with Authentication

I am using a WCF service client generated by slsvcutil form Silverlight toolkit version 4. I've also tried version 3 with the same problems. When I use a client instance running on http with no user credentials it runs without problems. But I need to switch to https for productive servers and send user credentials that are hardcoded for my application. I use the following code for that:
var binding = new BasicHttpBinding (BasicHttpSecurityMode.TransportCredentialOnly);
var endpoint = new EndpointAddress (AppSettings.FlareEndPoint);
_service = new TopicAnalystAPIClient(binding, endpoint);
_service.ClientCredentials.UserName.UserName = "xxx";
_service.ClientCredentials.UserName.Password = "xxx";
When I call a method on that service pointing to http with no authentication it works. When I use the this code against http/https with the credential I get "There was an error on processing web request: Status code 401(Unauthorized): Unauthorized" exception. I've checked that the credentials are correct, I am able to open the service reference in my browser. I've also tried several combinations of http/https and SecurityMode value. I've also tried it on four different servers always with the same result.
What can be the problem?
A lot of permutations are possible. BasicHttpSecurityMode.TransportCredentialOnly should be usable without SSL [1] using HTTP itself. This means the server will send one (or more) authentication method(s) to the client (e.g. basic, digest, ntlm) and Mono (including MonoTouch) should be providing support for the most of them.
It is possible that the linker (if used) removes one of them. In that case you could try building and testing without linking (or skip linking of System.Net.dll).
It's also possible that the authentication method that the serve insist on is not supported. You could find which one is used by running a network trace (e.g. wireshark) or, maybe, it will show up in more details in the server log (along with the 401 error).
[1] http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode%28v=vs.95%29.aspx

Categories