Asp.Net Core 2.0 HTTP -> HTTPS on Kestrel - c#

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();

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.

Consume third party API with Blazor WebAssembly [duplicate]

I have a blazor web assembly which fetches from an external API built on ASP.NET Core which I do not have access to. I can perform get requests, but cannot perform post requests. I get the following error when I do.
Access to fetch at 'http://external:9000/User/Create' from origin 'http://localhost:56138' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
The author of the api confirms he enabled cors to allow any header in his startup and also suggested I do the same but this did not fix the issue. I confirmed from the debugger I am sending the right data format the endpoint requires and I am also running on http scheme same as the web service.
This is the client configuration in program.cs
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://external:9000/") });
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder => builder.WithOrigins("http://external:9000/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
This is how I post
var dataJson = JsonConvert.SerializeObject(application);
var stringContent = new StringContent(dataJson, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync($"User/Create", stringContent);
I have read this is a common problem with blazor assembly, I'm not entirely sure of what I read. I am currently trying to move the project to blazor server to see if it would work, but I would prefer it on web assembly.
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder => builder.WithOrigins("http://external:9000/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
This configuration should be done on a Server, and not yours but the server of the external API. You do nothing in that regard, except call end points on that Web Api.
The author of the api confirms they enabled cors to allow any header in his startup
If so, ask them for the code for confirmation...
and also suggested I do the same but this did not fix the issue.
You do nothing of the sort.
Workaround solution:
AS CORS is a security feature of JavaScript enforced by the browser, you can circumvent it by calling your Server code from which you perform the call to this Web Api end point, and then returns it back to your WebAssembly front-end. Use asynchronous code as much as you can.
Update as per comment
Are you saying I should have two projects, the server and the client under one solution? The server calls the calls the external api, then passes it to the client. Is this what your last suggestion is?
If you're using WebAssembly Blazor App hosted wherein the hosting server contains Web Api controllers, then you should expose end points that can be called from your WebAssembly front-end. The code in these end points should perform the HTTP calls to the external Web Api, and pass back to the WebAssembly calling methods the data received from the external Web Api.
Note: If you don't have such controllers ( they are created by default by Visual Studio), you may add them yourself to the server project.
If you already have created a Web Api project instead of those controllers, then expose the necessary end points from your Web Api project. Note that it makes no difference whether your Web Api project resides in the same solution of the WebAssembly front-end, as long as you provide the correct Url.
If you're using WebAssembly Blazor App stand alone; that is, the default installation does not create a Server project, you'll need to create a Web Api project and use it, unless you've already created one.
You are working with localhost so you should use this configuration to your Server:
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder =>
builder.WithOrigins("http://localhost:56138/")
.SetIsOriginAllowed((host) => true) // this for using localhost address
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
//
app.UseCors("_myAllowSpecificOrigins");

WebApi Swagger (Swashbuckle) - can't access Swagger UI when connecting through proxy

I have a swagger (Swashbuckle) enabled on one of my API controllers.
Server sits on http://192.168.7.119:1001 and Swagger UI is accessed through http://192.168.7.119:1001/swagger.
When connecting locally, everything is fine and I can access Swagger UI on port 1001 as expected.
But when trying connect throug proxy on port 1000 (which redirects 1000 to 1001), I get a well known error:
"Can't read from server. It may not have the appropriate access-control-origin settings".
I have read this:
Unable to access swagger despite cors enabled Asp.NET WebAPI
and tried to set the RootUrl manually in Startup file, within Swagger like this:
.EnableSwagger(c =>
{
c.RootUrl(req => #"http://192.168.7.119:1001";
...
});
CORS settings are set as:
appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
Any hints what am I doing wrong here?
Putting together this two pages from github repos of Swashbuckle the easy way to do what you're asking is:
From Github Make sure that your proxy is sending the X-Forwarded-* headers (Apache does it out of the box while Nginx doesn't seems so. You have to do some changes on the nginx conf.
From Github. Create this HttpRequestMessageExtensions static class with the ComputeHostAsSeenByOriginalClient method and then
.EnableSwagger(c =>
{
c.RootUrl(req => req.ComputeHostAsSeenByOriginalClient());
...
});

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?

Categories