Disable HTTP Options method in ASP.Net Core 3.1 - asp.net-core

We have a requirement of disabling the HTTP OPTIONS method in an ASPNET Core Web application due as a part of security fixes. How can we disable the HTTP OPTIONS method in ASP.Net core 3.1 API?

Here is a demo with middleware:
Add this to your startup Configure:
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
if (context.Request.Method=="OPTIONS")
{
context.Response.StatusCode = 405;
return;
}
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
result:
Or you can apply
[HttpGet]
[HttpPost]
[HttpPut]
...
on your action method in controller.Here is an official document about the Http Verbs.

Related

Custom HTTP response headers on internal IdentityServer4 endpoints

I've been trying to add some custom HTTP response headers to the built-in IdentityServer endpoints like /connect/checksession with global filter approach depicted in the code snippet below (taken from Startup.cs ConfigureServices method):
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
options.Filters.Add(typeof(SecurityHeadersAttribute));
});
While the headers appear just fine on custom MVC endpoints like /AccountSelect and /Login the internal IdentityServer endpoints seem to ignore those altogether.
I was thinking whether the order of the registration in the startup overrides the global filters. In my case the code below is executed after AddMvc
services.AddIdentityServer(options =>
{
//code omitted for brevity
});
One option is to add your own middleware step in the request pipeline that will execute for every incoming request to your IdentityServer application.
Just add this code in Startup.Configure:
app.Use(async (context, next) =>
{
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("MyMagic", "Header");
return Task.FromResult(0);
});
await next();
});

Asp.Net Core MVC middleware returns 404 instead of 401 even with AuthorizeFilter

I have a very simple web api application that is configured like that:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
Services has MVC registration like that:
_services
.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
})
There is no default route registered for root, so when I do a request to root of the application, I get 404. What I was expecting to get is 401 though as I thought that absolutely all requests should require authorization.
I have not figured a way to achieve that, and not even sure this is correct semantically, but there is no open endpoints in my API and I would like to just return 401 if there is no authentication for any route.
ASP.NET uses 401 internally, you will always get 404, you can handle it by using
AddAuthentification() Extension in your Service collector
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
}).AddCookie("Cookies",
(options) =>
{
options.AccessDeniedPath = "..your access denied page route..";
options.LoginPath ="..your login route.."
})

Middleware to Require Authentication for Local IP .Net Core

In IIS, I have both antonymous and windows authentication enabled. In the code, I want to check if the request IP is a non routable IP, if not, I want the browser to challenge for credentials.
I tried returning a 401 status code, but that doesn't force the browser to challenge. What am I missing? Is there a better way to do this? How could I create a custom attribute, similar to Authorize, to achieve the same behavior (something like LocalOnly) for WebAPI methods?
Here's what I have in the Configure method in Startup.cs:
app.Use(async (context, next) =>
{
var ip = context.Connection.RemoteIpAddress.ToString();
var isInternal = Regex.IsMatch(ip, #"(^127\.)|(^(0)?10\.)|(^172\.(0)?1[6-9]\.)|(^172\.(0)?2[0-9]\.)|(^172\.(0)?3[0-1]\.)|(^169\.254\.)|(^192\.168\.)");
if (!isInternal && !context.User.Identity.IsAuthenticated) {
context.Response.StatusCode = 401;
} else
{
await next();
}
});

.NET Core 3 (preview) Web API return UnAuthorized (401) instead of NotFound (404)

Having read through many posts, blogs and this SO thread, this code doesn't do what I expect it to do:
services.AddAuthentication().AddCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
context.Response.Clear();
context.Response.StatusCode = 401;
return Task.CompletedTask;
}
};
});
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
};
});
An excerpt from an API controller (using the authorize attribute):
[ApiController]
[Route("api/[controller]")]
[Authorize(Roles = "User")]
public class TravelPlanController : BaseController{
...
}
This is part of the startup configuration of a Web API in .NET Core 3.x (preview) and should return a 401 UnAuthorized (which essentially should be UnAuthenticated) but instead returns a 404 NotFound.
The 404 results from the fact that the default .NET Core Authentication Middleware redirects to something like /auth/login and that route is not available (by design; it is an API not a MVC website). So the request is unauthorized, gets redirected by default, and results in a 404 :s
Both the apporaches of OnRedirectToLogin handlers should intercept this default behaviour, which is odd for a RESTfull API, and return a simple 401 UnAuthorized. But they don't, breakpoint isn't hit in debug mode, Postman and an Angular app in Chrome both report a 404.
Did anything change since .NET Core 3.x? Or did the solutions from others never really work.
This did the trick:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityContext>()
.AddDefaultTokenProviders()
.AddRoles<IdentityRole>();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
Working with ASP.NET Core 3.x (preview) and the default Identity provider the order in which the above declarations are specified makes the difference for the OnRedirectToLogin event to be fired.
I eloborated on this in this SO thread as well.
Try to define the OnRedirectToAccessDenied on the Events as you did for OnRedirectToLogin.

CORS error with Aurelia calling .NET core API 2.0

I am getting a CORS error and I don't know how to fix it. I have an Aurelia app, calling a .NET core 2.0 API using aurelia-fetch-client. I am getting the following error:
Failed to load http://localhost:58289/api/info: 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:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
TypeError: Failed to fetch
at applyInterceptors (webpack-internal:///./node_modules/aurelia-fetch-client/dist/native-modules/aurelia-fetch-client.js:428:14)
at processResponse (webpack-internal:///./node_modules/aurelia-fetch-client/dist/native-modules/aurelia-fetch-client.js:411:10)
at eval (webpack-internal:///./node_modules/aurelia-fetch-client/dist/native-modules/aurelia-fetch-client.js:299:14)
From previous event:
at HttpClient.eval (webpack-internal:///./node_modules/aurelia-fetch-client/dist/native-modules/aurelia-fetch-client.js:287:61)
at HttpClient.fetch (webpack-internal:///./node_modules/aurelia-fetch-client/dist/native-modules/aurelia-fetch-client.js:273:21)
at App.callApi (webpack-internal:///app:42:25)
at CallScope.evaluate (webpack-internal:///./node_modules/aurelia-binding/dist/native-modules/aurelia-binding.js:1578:19)
at Listener.callSource (webpack-internal:///./node_modules/aurelia-binding/dist/native-modules/aurelia-binding.js:5279:40)
at Listener.handleEvent (webpack-internal:///./node_modules/aurelia-binding/dist/native-modules/aurelia-binding.js:5288:10)
at HTMLDocument.handleDelegatedEvent (webpack-internal:///./node_modules/aurelia-binding/dist/native-modules/aurelia-binding.js:3363:20)
Please find my code below.
aurelia-fetch-client configuration:
const http = new HttpClient().configure(config => {
config
.withBaseUrl(environment.apiBaseUrl)
.withDefaults({
headers: {
'Content-Type': 'application/json'
}
})
.withInterceptor({
request(request: Request) {
var token = localStorage.getItem('access_token')
request.headers.append('Authorization', 'Bearer ' + token)
return request;
},
responseError(error){
return error;
}
});
});
aurelia.container.registerInstance(HttpClient, http);
Call the API:
callApi(){
this.httpClient.fetch("/info")
.then(response => console.log(response));
}
API startup configuration:
public void ConfigureServices(IServiceCollection services)
{
string domain = $"https://{Configuration["Auth0:Domain"]}/";
var allowedCors = Configuration["CorsSite"];
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = domain;
options.Audience = Configuration["Auth0:ApiIdentifier"];
});
services.AddCors(options => options.AddPolicy("AllowSpecificOrigin", `builder => {`
builder.AllowAnyOrigin().AllowAnyMethod(); }));
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.UseCors("AllowSpecificOrigin");
app.UseAuthentication();
app.UseMvc();
}
Controller:
[Produces("application/json")]
[Route("api")]
public class InfoController : Controller
{
// GET api/values
[HttpGet]
[Route("Info")]
public IActionResult Get()
{
return Ok("Api V1.0");
}
[Route("authorizedInfo")]
[Authorize]
[HttpGet]
public IActionResult GetAuthorized()
{
return Ok("Authorized Api V1.0");
}
}
Please ignore the authorisation bit for now. I am only trying to hit the unauthorised API endpoint in localhost, but I am stuck. How can I fix my problem?
To do this start with registering CORS functionality in ConfigureServices() of Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Add service and create Policy with options
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials() );
});
services.AddMvc();
}
The AddCors() call above adds the CORS features to ASP.NET and creates a custom policy that can be reused in the application by name. There are other ways to do essentially the same thing by explicitly adding a policy builder in the configuration step but to me this seems cleanest - define one or more policies up front and then apply it.
Once the policy has been defined it can be applied.
You can apply the policy globally to every request in the application by call app.useCors() in the Configure() method of Startup:
public void Configure(IApplicationBuilder app)
{
// ...
// global policy - assign here or on each controller
app.UseCors("CorsPolicy");
// ...
// IMPORTANT: Make sure UseCors() is called BEFORE this
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
or you can apply the policy to individual controllers:
[EnableCors("CorsPolicy")]
[ApiExceptionFilter]
public class AlbumViewerApiController : Controller
Thank You
The answer in the following link fixed my issue.
Web API 2 CORS IIS Express Debug and No Access-Control-Allow-Origin header
It appears that if there is no origin header in the request the server will not respond with the corresponding Access-Control-Allow-Origin response. Also with aurelia-fetch-client defaults I would have expected to have the origin header added by default.