Cross domain request in asp.net signalr core does not work? - c#

I am working on asp.net core signalr 1.1.0 under asp.net core 2.2 version. I want to
make the cross-domain request for web client and as well as a mobile client.
When I send request from javascript client, then this request blocked, and below error shows,
(index):1 Access to XMLHttpRequest at 'https://localhost:44373/chatHub/negotiate?token=12' from origin 'https://localhost:44381' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
My Javascript client code
var connection = new signalR.HubConnectionBuilder().withUrl("https://localhost:44373/chatHub?token="+12).build();
Signalr core service startup class code
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()/*WithOrigins("https://localhost:44381")*/
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddSignalR();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
//services.AddCors();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
//app.UseStaticFiles();
//app.UseCookiePolicy();
app.UseMvc();
}
builder.AllowAnyOrigin() its not working
builder => builder.WithOrigins("https://localhost:44381") its worked, but this is specific for this origin ,
I want to make AllowAnyOrigin()??

I got it working this way
On Configure services at the top
services.AddCors();
and in the Configure method
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services
.AddDbContext<ChatContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 60000000;
});
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
services.AddMvcCore()
.AddAuthorization()
.AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
var identityServerAuthOptions = Configuration.GetSection("Identity").Get<IdentityServerAuthenticationOptions>();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = identityServerAuthOptions.Authority;
options.RequireHttpsMetadata = identityServerAuthOptions.RequireHttpsMetadata;
options.ApiName = identityServerAuthOptions.ApiName;
});
var settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.ContractResolver= new CamelCasePropertyNamesContractResolver();
services.AddSignalR()
.AddJsonProtocol(options => {
options.PayloadSerializerSettings = settings;
});
services.AddTransient<IUserService, UserService>();
services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
//Data.AddData(app.ApplicationServices.GetService<ChatContext>());
app.Use(async (context, next) =>
{
if (string.IsNullOrWhiteSpace(context.Request.Headers["Authorization"]))
{
if (context.Request.QueryString.HasValue)
{
var token = context.Request.QueryString.Value.Split('&').SingleOrDefault(x => x.Contains("authorization"))?.Split('=')[1];
if (!string.IsNullOrWhiteSpace(token))
{
context.Request.Headers.Add("Authorization", new[] { $"Bearer {token}" });
}
}
}
await next.Invoke();
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials());
app.UseSignalR(config =>
{
config.MapHub<UserHub>("/UsersHub");
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
});
}
}
app.UseCors(builder =>
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
Whole code can be found here. This used to work just fine for me. I haven't opened it lately though
Github Repo

I see two issues with your code. Let's tackle them one by one.
Allowing all origins for the entire application even though you need it only for the SignalR connection. Consider the below code if you want to apply CORS policy only for the signalR endpoint
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<UsersHub>("/UsersHub")
.RequireCors((policyBuilder) => policyBuilder
.WithOrigins("clientUrls")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
});
It is recommended to not allow all origins but if you have such a use case then the below workaround can fix your problem. This is the trick of using .SetIsOriginAllowed(_ => true)
.SetIsOriginAllowed(_ => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
Further if you want more information, have a look at this guide for more details.

Related

Asp core sessions aren't persisting after requests ends

Trying to store a string in a session while waiting for confirmation from the front end, but on the next request (confirmation request) the session is completely empty.
Config
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDistributedMemoryCache();
services.AddSession(options => {
options.Cookie.Name = ".SingleTouch.API.Session";
options.IdleTimeout = TimeSpan.FromMinutes(20);
options.Cookie.IsEssential = true;
options.Cookie.HttpOnly = true;
});
string allowedHosts = Configuration.GetValue<string>("AllowedHosts");
services.AddCors(options =>
{
options.AddPolicy(name: CorsAllowedUrls,
builder =>
{
builder.WithOrigins(allowedHosts)
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllersWithViews(options =>
options.Filters.Add(new ApiExceptionFilter()));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(CorsAllowedUrls);
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
}
And in one endpoint I have
_httpContextAccessor.HttpContext.Session.SetString("payEvent", "bro you good?");
and on the the following endpoint it retrieves it again
_httpContextAccessor.HttpContext.Session.GetString("payEvent");
but on retrieval, the session is empty. It's definitely being added initially because if you inspect or run GetString in the first request the value exists. Asp core 6 is in use.
The Session has scoped lifetime, i.e. for any request you always get a new session. This is nesessary as each request can be issued by a differing user. If you want to store information for specific users, you need to do this in a singleton service.

How to troubleshoot cors error on IIS server

I'm working on an application which the backend is a net core API with SignalR and the front end is Angular. Debugging on my computer it works as expected but when I publish on the server it shows Cors error even after enabling them on the startup.cs.
This is the error Im getting:
Access to XMLHttpRequest at 'http://server:10079/fareg/api/account' from origin 'http://server' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Can anyone please help to identify what I'm doing wrong to get ride of the CORS error?
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//add Windows authentication for http options request
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddDbContext<FAContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("FADB")));
services.AddCors(options =>
{
options.AddPolicy(name: _MyCors, builder =>
{
builder
.SetIsOriginAllowed(origin => new Uri(origin).Host == "server name")
//.WithOrigins("http://server/fareg", "http://localhost:4200")
.AllowCredentials()
.AllowAnyHeader()
//.SetIsOriginAllowed(_ => true)
.AllowAnyMethod();
});
});
services.AddSignalR().AddMessagePackProtocol();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors(_MyCors);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseSignalR(routes =>
{
routes.MapHub<Hubs.HubFA>("/signalr");
});
app.UseMvc();
}
}
you put the UseCors() in a wrong place. Try to use this syntax
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy(_MyCors,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
.....
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
.....
// app.UseRouting();
app.UseCors(_MyCors);
// app.UseAuthorization();
// app.UseEndpoints(..
}
Make sure that UseCors should be in the end of Configure method but before UseAuthorizaton. In your case it should be just above UseMvc(). But AddCors should be moved to the top of Configure services.
If this syntax is working for you, only after this you can try to add useorigin.

how to allow CORS for POST and PUT method with c# front-end reactJS

PROBLEM: in localhost all method(GET,POST,PUT) working fine but after deployment in server i got CORS POLICY BLOCKED err. although in server GET method working fine
C# with ef core
following my Startup.cs file.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
readonly string AllowLocalHostOrigins = "_allowLocalHostOrigins";
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<venus_aestheticsContext>(options => options
// replace with your connection string
.UseMySql(Configuration["dbConnection:startup"],
mysqlOptions =>
{
mysqlOptions
.ServerVersion(new Version(8, 0, 18), ServerType.MySql);
}));
// services.AddScoped<IDataRepository<Token, long>, TokenManager>();
// services.AddMvc();
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddControllers();
// enable cors
services.AddCors(options =>
{
options.AddPolicy(AllowLocalHostOrigins,
builder =>
{
builder.WithOrigins("http://localhost:3000").AllowAnyHeader().AllowAnyMethod();
builder.WithOrigins("http://www.testing.com").AllowAnyHeader().AllowAnyMethod();
});
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
//     services.AddPaging();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseOptions();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
//c.RoutePrefix = string.Empty;
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseSession();
app.UseRouting();
app.UseCors(AllowLocalHostOrigins);
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Can you please replace
app.UseCors(AllowLocalHostOrigins);
With
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());

CROS error in asp.net core3.1 and signalr Core

i followed the exact tutorial from
https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio
and then i wanted to access the hub from another Origin. so i followed the exact instructions in
https://learn.microsoft.com/en-us/aspnet/core/signalr/security?view=aspnetcore-3.1
but i get this error:
Access to XMLHttpRequest at 'http://localhost:55039/myhub/negotiate?negotiateVersion=1' from origin 'http://localhost:54114' 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.
here is the code:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
o.HandshakeTimeout = TimeSpan.FromSeconds(5);
});
}
and :
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:54114/")
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("/myhub");
});
}
asp.net core 3.1
AspNetCore.SignalR
any tips and guides will be appriciated
Configure the CORS like below:
ConfigureServices
services.AddCors(options =>
options.AddPolicy("CorsPolicy",builder =>
{
builder.WithOrigins("http://localhost:44338")
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials();
}));
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
o.HandshakeTimeout = TimeSpan.FromSeconds(5);
});
Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseCors("CorsPolicy");
//...
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chatHub");
});
}

Angular SPA on .NET Core 3.0 Web API Connection issues

I made an API with a swagger interface, on localhost:5599.
If I do a GET to localhost:5599/api/owner i get a JSON of owners, everything works.
Next step I want to take is make an Angular interface, so I added a webproject with Angular template to the solution, set the webproject as startup project (localhost:49960 is the app url; but with ssl 44376 and with the app running uses the last port).
Calling localhost:5599/api/owner gives: Failed to load resource: net::ERR_CONNECTION_REFUSED
This makes sense as the API project is not "running", but how can I make this work?
In which startup.cs file should i put what?
Do I need to "connect" this angular project to the API startup somehow in endpoints?
All help is much appreciated!
This is the startup.cs for the Angular WebApp
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
// spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
}
});
}
}
These snippets from API startup.cs
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
app
.UseCors("CorsPolicy")
.UseHttpsRedirection()
.UseRouting()
.UseEndpoints(config => config.MapControllers())
.UseSwagger()
.UseSwaggerUI(config => config.SwaggerEndpoint("v1/swagger.json", "VerticalSliced.DogFaceAPI - V1"))
.UseStaticFiles();
services
.AddMediatR(cfg => cfg.AsScoped(), typeof(ToDoItemsQueryHandler).GetTypeInfo().Assembly)
.AddMediatR(cfg => cfg.AsScoped(), typeof(OwnersQueryHandler).GetTypeInfo().Assembly)
.AddMediatR(cfg => cfg.AsScoped(), typeof(DogsQueryHandler).GetTypeInfo().Assembly)
.AddMediatR(cfg => cfg.AsScoped(), typeof(MediaFilesQueryHandler).GetTypeInfo().Assembly)
.AddMediatR(cfg => cfg.AsScoped(), typeof(MedicalFilesQueryHandler).GetTypeInfo().Assembly)
.AddSwaggerGen(config => config.SwaggerDoc("v1", new OpenApiInfo { Title = "VerticalSliced.DogFaceAPI", Version = "v1" }))
.AddControllers()
.AddNewtonsoftJson(opt => opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
The constructor for the fetch-owners-component in Angular
constructor(http: HttpClient, #Inject('API_BASE_URL') apiBaseUrl: string) {
http.get<UIOwner[]>(apiBaseUrl + 'api/owner').subscribe(result => {
this.owners = result;
}, error => console.error(error));
}
API_BASE_URL is http:localhost:5599/
If there is something else I'm missing, would be glad to hear!
Grts
Since you mentioned that API runs on different port make sure to change the URL on the Angular app.
Also you need to configure CORS on the DotNet API, you can do it as,
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);

Categories

Resources