CORS errors when deploying signalR notification Hub to IIS - deployment

My signalR Hub can run fine in VS2019 debug mode on secure port 44311, but as soon as I publish it to my local IIS on my dev box, the ../hub/negotiate fails with a CORS policy exception.
ex. in debug mode, the IIS tray
and signalr Hub starts fine:
Now onto my local Window 10 IIS settings where I deployed the signalR Hub project:
I setup the https bindings
I successfully setup the SSL Cert, and set the Require SSL checkbox:
I Restart my IIS Website, and Browse on 44311 to test
But sure enough, my app cannot connect to the HUB:
Access to XMLHttpRequest at 'https://localhost:44311/hub/negotiate?negotiateVersion=1' from origin 'http://localhost:4200' 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.
POST https://localhost:44311/hub/negotiate?negotiateVersion=1 net::ERR_FAILED
Yet in my code I injected CORS:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NotificationHub.Hubs;
namespace NotificationHub
{
public class Startup
{
readonly string MyAllowedSpecificOrigins = "_myAllowedSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowedSpecificOrigins,
builder => {
builder.WithOrigins("https://localhost:4200", "localhost:4200")
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true);
}
);
});
services.AddSignalR(hubOptions => {
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = System.TimeSpan.FromMinutes(1000);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowedSpecificOrigins);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<Notifications>("/hub", options => {
options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;
});
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Notification HUB has started!");
});
});
}
}
}
I'm not sure at this point if it's a coding issue (i.e. not setting CORS properly), or a deployment issue.
Help is appreciated.
thanks.
UPDATE
As per the suggested answer below, my CORS issue is resolved when deployed to IIS:
Install cors for IIS: https://www.iis.net/downloads/microsoft/iis-cors-module
Add below <customHeaders> to web.config
However, I still CANNOT connect to the hub successfully in IIS deployment mode (http://localhost:55271/hub/negotiate?negotiateVersion=1 throws 404 not found); however debug works fine.
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Allow-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>

make sure you enabled iis .net feature. enable directory browsing in iis for the site:
1)Start IIS Manager.
2)In IIS Manager, expand the server name, expand Web sites, and then select the website.
3)In the Features view, double-click Directory Browsing.
4)In the Actions pane, click Enable.
add below code in web.config file:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://my-external-app-domain.com" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
install cors module in iis by using web platform installer or from below link:
https://www.iis.net/downloads/microsoft/iis-cors-module
Update:
Add below to web.config:
HttpRequest,x-requested-with were both needed in "Access-Control-Request-Headers" . In addition, I inserted header name="Access-Control-Allow-Headers" with same values as Request-Headers.

Related

ASP.NET Core 3.1 - "site can’t provide a secure connection" when setting application url using .UseUrls()

I'm running the app using "dotnet run". If I don't set the url programmatically using .UseUrls() then it picks it up from launchSettings.json and all good. However if I set THE SAME url using .UseUrls() I get the message below on the brower.
There are no errors from the code i.e. both cases report " Now listening on: http://localhost:6001". Any ideas?
Remove Strict-Transport-Security from your Web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security"
value="max-age=16070400; includeSubDomains" />
</customHeaders>
</httpProtocol>
</system.webServer>
My mistake - launchSettings.json was using https://localhost:6001 and the code was using http://localhost:6001. Doh!

ColdFusion REST API Enable CORS

I am trying to build a REST API using coldfusion components and I can't figure out how to enable CORS. I am using IIS 10 and ColdFusion 2016. I can't find anywhere in IIS to configure CORS following instructions on google and I don't see anywhere under CF admin settings to enable CORS, so I figured I would try to enable CORS in my API instead of fiddling with configuration in each environment I deploy this to (qa, uat, prod).
This is what my application.cfc currently looks like and you can see in the onRequestStart I am attempting to set the headers (two ways I've tried)
<cfscript>
component output="false" {
this.name = ....
public boolean function onApplicationStart() {\
restInitApplication( ... );
return true;
}
public void function onApplicationEnd(ApplicationScope) {
return;
}
public void function onMissingTemplate(targetPage) {
return;
}
public void function onRequestStart(targetPage) {
cfheader(name="Access-Control-Allow-Origin", value="*");
// i've also tried ...
GetPageContext().getResponse().addHeader("Access-Control-Allow-Origin","*");
}
public void function onSessionStart() {
return;
}
public void function onSessionEnd(sessionScope, applicationScope) {
return;
}
}
</cfscript>
I would recommend installing the IIS CORS module - reference. Here is a snippet from that reference:
Functionality Overview
The Microsoft IIS CORS Module is an extension that enables web sites to support the CORS(Cross-Origin Resource Sharing) protocol.
The IIS CORS module provides a way for web server administrators and web site authors to make their applications support the CORS protocol. With this module, developers can move CORS logic out of their applications and rely on the web server. The module's handling of CORS requests is determined by rules defined in the configuration. These CORS rules can be easily defined or configured making it simple to delegate all CORS protocol handling to the module.
IIS CORS module is a server-side CORS component
The CORS protocol governs client/server communication. Usually, web browsers act as the client-side CORS component, while the IIS server works as the server-side CORS component with the help of the IIS CORS module.
A CORS request occurs when a protocol aware client, such as a web browser, makes a request to a domain (origin) that differs from the current domain. This scenario is known as a cross-origin request. When CORS is not used, cross-origin requests will be blocked by the client. When the CORS module is used, IIS will inform clients whether a cross-origin request can be performed based on the IIS configuration.
Don't try implementing this from ColdFusion, let the web server do what it is designed to do. Once you have the module installed you can create the rules you want within the web.config files for any/all IIS sites.
Sample config file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*" />
<add origin="https://*.microsoft.com"
allowCredentials="true"
maxAge="120">
<allowHeaders allowAllRequestedHeaders="true">
<add header="header1" />
<add header="header2" />
</allowHeaders>
<allowMethods>
<add method="DELETE" />
</allowMethods>
<exposeHeaders>
<add header="header1" />
<add header="header2" />
</exposeHeaders>
</add>
<add origin="http://*" allowed="false" />
</cors>
</system.webServer>
</configuration>
You can download the IIS CORS module from here.

UseOpenIdConnectAuthentication kills postback

I am trying to include SSO with office 365 for one of our web applications.
the problem is that as soon as SSO is working all my postbacks are getting ignored.
what I did was the following,
I installed those Nuget Packages
- Microsoft.Owin
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security
- Microsoft.Owin.Security.Cookies
- Microsoft.Owin.Security.OpenIdConnect
- Owin
I created an app in my AAD
then I've added some settings to my web.config
<add key="ida:PostRedirectUri" value="http://localhost:4439" />
<add key="ida:ClientId" value="XXXXXXX" />
<add key="ida:AADInstance" value="https://login.microsoftonline.com/" />
<add key="ida:Tenant" value="XXXX.onmicrosoft.com" />
<add key="ida:PostLogoutRedirectUri" value="http://localhost:4439" />
and I added Startup.vb to my solution with the following content
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions())
app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions() With {
.ClientId = clientId,
.Authority = authority
})
app.UseStageMarker(PipelineStage.Authenticate)
and after this the SSO works however al postbacks on buttons fail
if I click a button the page just gets reloaded.
also the IsPostBack parameter is alwayst false.
What I found was that when I remove the "app.UseOpenIdConnectAuthentication" part, postbacks are working again, but SSO is not.
how can I make sure my postbacks are working and I can also use UseOpenIdConnectAuthentication ?
thank you.
I found the issue,
in my web.config I had
<modules runAllManagedModulesForAllRequests="true">
in system.web
removing the key "runAllManagedModulesForAllRequests" solved the problem
<modules>

NWebsec's "A potentially dangerous redirect was detected" with Facebook logon

I have read through NWebSec's documentation to try and resolve the problem.
Set the web.config to
<nwebsec>
<httpHeaderSecurityModule
xsi:noNamespaceSchemaLocation="NWebsecConfig/HttpHeaderSecurityModuleConfig.xsd"
xmlns="http://nwebsec.com/HttpHeaderSecurityModuleConfig.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<redirectValidation enabled="false">
<allowSameHostRedirectsToHttps enabled="false"/>
<add allowedDestination="https://www.facebook.com/"/>
<add allowedDestination="http://www.nwebsec.com/"/>
<add allowedDestination="https://www.google.com/accounts/"/>
</redirectValidation>
<securityHttpHeaders>
<strict-Transport-Security max-age="365" includeSubdomains="true" httpsOnly="false" preload="true" />
</securityHttpHeaders>
</httpHeaderSecurityModule>
but I am still getting
A potentially dangerous redirect was detected. Add the destination to the whitelist in configuration if the redirect was intended. Offending redirect: https://www.facebook.com/dialog/oauth?response_type=code&
This came up in google before the answer, which is here: https://docs.nwebsec.com/en/latest/nwebsec/Redirect-validation.html
In summary you have to whitelist the URL which your login service refers to, like this:
app.UseRedirectValidation(opts =>
{
opts.AllowedDestinations( "https://www.facebook.com/dialog/oauth");
opts.AllowedDestinations("https://login.microsoftonline.com"); // Tested
});

Configure Webmatrix for Windows Users

I create asp .net page and i have use windows user to authenticate.
<authentication mode="Windows" />
I create simply page with one label and display information.
if (Page.User.Identity.IsAuthenticated)
{
Label1.Text = "Authenticated = 'TRUE'<br/>";
Label1.Text = Page.User.Identity.Name;
}
else
{
Label1.Text = "Authenticated = 'FALSE'<br/>";
}
I often get Authenticated = 'FALSE'
How configure web.config and WebMatrix to take user from Windows?
Probably you published your web site without changing authentication on the corresponding virtual directory of IIS.
You should deactivate "Anonymous" authentication and activate "Windows" authentication. The existence of <authentication mode="Windows" /> line in web.config is not enough for IIS. Moreover "Windows" authentication must be installed of cause (see for example this for more information).
try
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>