asp.net core CORS not working as I would expect - asp.net-core

I've got a node app that is hosted at localhost:9000 running (React with Express). I'm making an axios REST POST to my ASP.NET Core 2.0 web project with as follows:
http://localhost:50494/rest/sessions
GET works but POST does not. In My Startup.cs files I believe I've set all origins and methods to be allowed on my asp.net core end points but still I'm getting what I think is a CORS not setup error.
http://localhost:50494/rest/sessions/6184: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.
Here is my setup on the asp.net side:
Program.cs
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
Startup.cs
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.AddCors();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseCors(builder =>
builder.AllowAnyOrigin().AllowAnyMethod());
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
Why am I getting this error?

Related

Dot Net Core Web API Return Response From Endpoint

I'm busy trying to create a very simple Dot Net Core Web API (Dot Net 5) and I've run into a strange issue where I cannot get the endpoint to return a response.
I've tried to use
await context.Response.WriteAsync("Hello World!");
as per the documentation but I'm getting the error
'HttpResponse' does not contain a definition for 'WriteAsync'
This is the full Startup.cs code
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services) { }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
app.UseRouting();
app.UseEndpoints(endpoints => {
endpoints.MapGet("/test", async context => {
//Console.WriteLine("Exec Test");
await context.Response.WriteAsync("Hello World!");
});
});
}
}
I'm sure there's something I'm missing
Add the dependency for Microsoft.AspNetCore.Http.Abstractions.dll which contains the WriteAsync method you are looking for based on the HttpResponse.
Please refer to the following documentation:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.httpresponsewritingextensions.writeasync?view=aspnetcore-5.0
https://www.carlrippon.com/asp-net-5-hello-world/

.net core 5.0.2 and jwt => response 401 Unauthorized

I am following an video tutorial for identity server 4 with web api's.
And Im not sure when I went wrong.
Im getting 401 Unauthorized when I try to call api with bearer token.
In previos step, without authorization, my api worked.
This is my api controller in my TablesReach.API project:
...
namespace TablesReach.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly DataContext _context;
public UsersController(DataContext context)
{
_context = context;
}
// GET: api/Users
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
return await _context.Users.ToListAsync();
}
...
this is my Startup.cs of my api project:
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.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(opts =>
{
opts.Authority = "http://localhost:5000";
opts.RequireHttpsMetadata = false;
opts.ApiName = "TablesReachApi";
});
services.AddDbContext<DataContext>(opts => opts.UseInMemoryDatabase("UNWDb"));
services.AddControllers();
}
// 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.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
}
}
My other project TablesReach.IdentityServer is host on localhost:5000
and Im being able to get bearer token, so I assume that this project is quite OK.
identityServer startup.cs class:
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.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiScopes(Config.GetAllApiResources())
.AddInMemoryClients(Config.GetClients());
}
// 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");
// // 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();
//app.UseRouting();
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
//});
app.UseIdentityServer();
}
}
and Config.cs:
public class Config
{
public static IEnumerable<ApiScope> GetAllApiResources()
{
return new List<ApiScope>
{
new ApiScope("TablesReachApi", "Api for solution")
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "TablesReachApi" }
}
};
}
}
Note: When I remove annotation [Authorize] from my api controller I can reach my method.
For some middleware, order matters. Authentication and authorization, for example, can't go in the order that you have put them in the API. Microsoft has some clear documentation on this for you to read here..

.NET Core Identity and Simple Injector. Crosswire not working

I am using simple injector (4.8.1) on a project that uses asp.net core identity. I tried to crosswise UserManager but I got an error saying
No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Tenancy.Core.Domain.AppUser]' has been registered."
the SimpleInjectorConfig class is:
public static class SimpleInjectorConfig
{
private static Container _container;
public static void ConfigureServices(IServiceCollection services, IConfiguration config,
IWebHostEnvironment env)
{
_container = new Container();
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
_container.ConfigureCore(config, env);
_container.RegisterInitializer<BaseApiController>(controller =>
{
controller.Mediator = _container.GetInstance<IMediator>();
});
services.AddSingleton(_container);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddControllers();
services.AddLogging();
// Sets up the basic configuration that for integrating Simple Injector with
// ASP.NET Core by setting the DefaultScopedLifestyle, and setting up auto
// cross wiring.
services.AddSimpleInjector(_container, options =>
{
// AddAspNetCore() wraps web requests in a Simple Injector scope and
// allows request-scoped framework services to be resolved.
options
.AddAspNetCore()
.AddControllerActivation();
options.AddLogging();
options.CrossWire<UserManager<AppUser>>();
});
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSimpleInjector(_container);
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
IdentityModelEventSource.ShowPII = true;
}
//app.UseHttpsRedirection();
_container.Verify();
}
}
and I called it in my Startup.cs file
public class Startup
{
public IConfiguration _configuration { get; }
public IWebHostEnvironment _env { get; }
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
_configuration = configuration;
_env = env;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
SimpleInjectorConfig.ConfigureServices(services, _configuration, _env);
CorsConfig.ConfigureServices(services);
DatabaseConfig.ConfigureServices(services, _configuration);
MvcConfig.ConfigureServices(services);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
SimpleInjectorConfig.Configure(app, env);
CorsConfig.Configure(app, _configuration);
MvcConfig.Configure(app);
}
}
The configurations have their own class and called in the Startup called in the Startup class just to keep it clean, SimpleInjectorConfig is the config class for simple injector.

.net core not showing HTML static file changes

I made some changes to the static file index.html but running via .net-core and inspecting elements these changes do not apply however when I open the static file via live server extension of vscode I can see the changes.
I am very new to .net core, I looked up a few threads but couldn't find what the problem is or a similar one.
My Startup class looks as so:
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.AddMvc().ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});
}
// 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.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
also, the project repository is here
Thanks to everyone who takes their time to help.

.Net Core 2.x Redirect to Error Page

I have a simple ASP.Net Core 2.0 web application and I have enabled Windows Authentication in project property by enabling Windows Authentication and disabled Anonymous Authentication.
For Authorization at Application/Site level filtering by AD security group, I have the following code in Startup.cs:
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.AddMvc();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole("Application - Administrator")
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
}
// 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.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
//app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");
//app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");
app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
To handle Http 403 status code when a un-authorized user tries to access the application, it will be redirect to a custom error page. So I tried the following 3 approaches in Configure method within Startup.cs:
app.UseStatusCodePagesWithRedirects("/Home/Error/{0}");
app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");
app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
In the HomeController, I tried both the default Error method
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
and customized one to handle specific status code:
public IActionResult Error(string errCode)
{
if (errCode == "500" || errCode == "404" || errCode == "403")
{
return View($"~/Views/Error/{errCode}.cshtml");
}
return View("~/Views/Shared/Error.cshtml");
}
And I have a simple error page 403.cshtml under /Views/Error/ folder.
But none of them works, all display this page:
I am wondering if something I missed or forgot to implement for display a formatted error page?
Thanks in advance.
I am not 100% sure but there should be 2 variations of windows authentications:
The host only allows authenticated users
When you enable Windows Authentication and disable Anonymous Users
[Authorize] and [AllowAnonymous] no effect, because unauthenticated requests never reach your application
Hence you can't / don't need to set up global filter. You might have to setup the friendly error pages on the server?
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/home/error");
}
app.UseStaticFiles();
app.UseMvcWithDefaultRoutes();
}
}
The host allows both anonymous and authenticated users
When you enable both Windows Authentication and Anonymous Users
[Authorize] requires additional setup on Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireRole("Application - Administrator")
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseStatusCodePagesWithReExecute("/error", "?code={0}");
app.UseAuthentication();
app.UseMvcWithDefaultRoutes();
}
You need to use [AllowAnonymous] on the error controller to override the [Authorize] global filter to allow anonymous requests.
[AllowAnonymous]
public class ErrorController : Controller
{
public IActionResult Index(int? code)
{
...
}
}
The problem is at the Error method, it missed the AllowAnonymous attribute to allow anonymous access to the error method when the user failed authorization.
Credit to #Calc
Try app.UseStatusCodePagesWithRedirects("/Home/Error/{0}"); in startup.configure(IApplicationBuilder app, IHostingEnvironment env)
Works on ASP.NET CORE2.0 web app
It will handle any kind of HTTP error