How to add the "Access-Control-Allow-Credentials" request header to a POST request in ASP.NET? - c#

So, I am trying to set the "Access-Control-Allow-Credentials", using the HttpContext.Request.Headers.Add("Access-Control-Allow-Credentials", "true"); , but it will only work for my GET requests, but not for my POST ones, and i don't know why.
I've also tried to set those in Startup.cs, as so:
services.AddCors(o => o.AddPolicy("ApiCorsPolicy", builder =>
{
builder
.WithOrigins("My_Web_App")
.AllowCredentials()
.AllowAnyMethod()
.AllowAnyHeader();
}));
And then use it in Configure with app.UseCors("ApiCorsPolicy");
That's the code from my controller, so nothing fancy in here, I think:
[ApiController]
[Route("[controller]")]
[EnableCors("ApiCorsPolicy")]
public class UserController : Controller
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpPost("RegisterUser")]
public void GetTournaments([FromBody] UserDTO user)
{
HttpContext.Request.Headers.Add("Access-Control-Allow-Credentials", "true");
_userService.RegisterUser(user);
}
}
My question is, why I can't put the "Access-Control-Allow-Credentials" header using the Headers.add method( Which works for my GET requests ) ? If that is not the correct approach to it, then how to do it ?
Thanks!
Edit:
I've added all my Startup file, as requested:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("ApiCorsPolicy", builder =>
{
builder
.WithOrigins("http://"MyIpAddressHere"/")
.AllowAnyMethod()
.AllowAnyHeader();
}));
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingGeneral());
});
IMapper mapper = mapperConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddSingleton<ITournamentService, TournamentService>();
services.AddSingleton<IUserService, UserService>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "my_app", Version = "v1" });
});
}
// 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();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "my_app v1"));
}
app.UseRouting();
app.UseCors("ApiCorsPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}

Change
.WithOrigins("My_Web_App")
to
.WithOrigins("http://localhost....") //your web app url
//your Url shouldn't end with "/"
and remove from code:
//sometimes it interfers with token if you have
.AllowCredentials()
// you don't need this at all
HttpContext.Request.Headers.Add("Access-Control-Allow-Credentials", "true");
Your UseCors should be after UseRouting but before UseAuthorization.
and remove from your controller:
[EnableCors("ApiCorsPolicy")]

I highly suspect that the culprit is in this:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
Credentials are not supported without a correct origin.

Related

security page filter for jost many pages

i create a page filter in asp.net core razor page
I want it to be only for those handlers that are inside the administration area
this is my pageFilter
namespace ServiceHost
{
public class SecurityPageFilter :IPageFilter
{
private readonly IAuthHelper _authHelper;
public SecurityPageFilter(IAuthHelper authHelper)
{
_authHelper = authHelper;
}
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
}
public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
var handlerCompulsoryPermission = (NeedPermissionAttribute)context.HandlerMethod.MethodInfo.GetCustomAttribute(typeof(NeedPermissionAttribute));
var accountPermissions = _authHelper.CurrentAccountPermissions();
if (handlerCompulsoryPermission == null)
return;
if (!_authHelper.IsAuthenticated())
context.HttpContext.Response.Redirect("/Account");
if (!accountPermissions.Contains(handlerCompulsoryPermission.Permission))
context.HttpContext.Response.Redirect("/Account");
}
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
}
}
}
and this is my startup file
namespace ServiceHost
{
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.AddHttpContextAccessor();
var connectionString = Configuration.GetConnectionString("Keyson_Shop");
ShopManagementBootstrapper.Configure(services, connectionString);
DiscountManagementBootstrapper.Configure(services, connectionString);
InventoryManagementBootstrapper.Configure(services, connectionString);
BlogManagementBootstrapper.Configure(services, connectionString);
CommentManagementBootstrapper.Configure(services, connectionString);
AccountManagementBootstrapper.Configure(services, connectionString);
services.AddTransient<IZarinPalFactory, ZarinPalFactory>();
services.Configure<CookiePolicyOptions>(options =>
{
//this line does access to tempData work
// options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
{
o.LoginPath = new PathString("/Account");
o.LogoutPath = new PathString("/Account");
o.AccessDeniedPath = new PathString("/AccessDenied");
});
services.AddCors(options => options.AddPolicy("MyPolicy", builder =>
builder
.WithOrigins("https://localhost:5002")
.AllowAnyHeader()
.AllowAnyMethod()));
services.AddRazorPages()
.AddMvcOptions(options =>
{
options.Filters.Add<SecurityPageFilter>();
});
services.AddTransient<IMenuQuery, MenuQuery>();
services.AddTransient<IFileUploader, FileUploader>();
services.AddSingleton<IPasswordHasher, PasswordHasher>();
services.AddTransient<IAuthHelper, AuthHelper>();
services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.BasicLatin,UnicodeRanges.Arabic));
}
// 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.UseAuthentication();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapDefaultControllerRoute();
});
}
}
}
i want to know page filter has any option to give that and just run in my administration areas handler.
but if that hasn't an option what should i need to do about this problem
i get happy if answer this question

How to inject own services in Controller

I tried to inject my own service in my api controller, but it throws an InvalidOperationException. It is unable to resolve the service. (.NET 5)
What I am doing wrong?
public class MyController : ControllerBase
{
private readonly MyService _myService;
public ContractsController(MyService service)
{
myService = service;
}
[HttpGet("{id}")]
public Item GetItemById(string id)
{
return _myService.getContract(id);
}
}
This is my Startup file:
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.AddControllers();
services.AddSwaggerGen(c =>
{
c.CustomOperationIds(selector => $"{selector.HttpMethod.ToLower().Pascalize()}{selector.ActionDescriptor.RouteValues["controller"]}");
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My.Portal.Server", Version = "v1" });
});
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.SetIsOriginAllowed(origin => new Uri(origin).IsLoopback)
.WithOrigins(Configuration.GetSection("AllowedOrigins").Get<string[]>())
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
// 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();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My.Portal.Server v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
If i create a new instance in the constructor, then it is working.
thank you in advance!
Example, as per request in comment:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IInfoStorageService>(c => new InfoStorageService(Configuration["ImageInfoConnectionString"]));
This is telling the application to pass an instance of InfoStorageService in where IInfoStorageService is injected. It is instantiated with a connection string that it reads from configuration.
AddScoped means that the injected service will be the same across the request. You can also use AddTransient() which means it will not match any other uses of the service, or you can use AddSingleton(), which means it will use the same instance through the whole lifetime of the application.

API call: "Endpoint ... contains authorization metadata, but a middleware was not found that supports authorization."

I am currently working on creating a simple web application in angular using Auth0 to offload the authorization portion. Right now I am trying to connect the front end portion and the backend portion and I am having some trouble.
For some reason when I send a https request to the API it keeps giving me the following error in the chrome console.
So I went to use postman to try and access the api. I got past the CORS part error but instead het Endpoint .... contains authorization metadata, but a middleware was not found that supports authorization.
This is what my startup class looks like in my backend:
public class Startup
{
readonly string MyAllowSpecificOrigins = "localhost_origin";
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)
{
string domain = $"https://{Configuration["Auth0:Domain"]}/";
services.AddControllers();
// 1. Add Authentication Services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("read:messages", policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
});
services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("https://localhost:4200").AllowAnyMethod().AllowAnyHeader();
});
});
}
// 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("/Home/Error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
//app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Here is my test controller that I call the api on:
[Route("api")]
public class TestController : Controller
{
[HttpGet]
[Route("private")]
[Authorize]
public IActionResult Private()
{
return Json(new
{
Message = "Hello from a private endpoint! You need to be authenticated to see this."
});
}
}
I've read the documentation and followed the examples on auth0's sites for implementing this. I can't quite find where I went wrong.
Okay for the people that might run into a similar issue. It ended up being a problem of the order of things in the startup.cs file and making my localhost origin use http instead of https. I wasn't able to deduce this from the tutorial article because they ommitted a lot of code. I ended up having to download the sample project and compare line by line. This is the final startup.cs file that worked for me:
public class Startup
{
readonly string MyAllowSpecificOrigins = "localhost_origin";
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)
{
string domain = $"https://{Configuration["Auth0:Domain"]}/";
services.AddControllers();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder
.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
// 1. Add Authentication Services
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("read:messages", policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
});
services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
}
// 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("/Home/Error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

CORS not working in ASP.NET core Web API project

I built an ASP.NET core Web API (net core 3.1), and I try to enable CORS but it seems not working.
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder =>
{
builder.SetIsOriginAllowed(t => true)
.AllowCredentials();
});
});
...
}
‌
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("AllowMyOrigin");
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseHttpsRedirection();
}
Controller:
[Route("api/[controller]")]
[ApiController]
public class airdata_updateController : ControllerBase
{
[EnableCors("AllowMyOrigin")]
[HttpGet]
public string test()
{
return "ok";
}
...
}
I use Postman test my API on local computer and it working well:
local computer
But I use Postman on other computer in the same LAN to call my API, it failed:
other computer
What should I do?
Try this:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors();
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseCors(
options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()
);
...
}
You won't need any decorators in your controller methods, the specified CORS policy ( AllowAnyOrigin, AllowAnyHeader, AllowAnyMethod) is applied in all of them. In order to customize the policy, check https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1
maybe this option can help you.
services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder => builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowAnyOrigin()
);
});

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

Categories

Resources