CORS vs Autofac vs Exception handling middleware in Owin, which one goes first? - owin

I have an owin setup that among many other things, uses CORS and Autofac.
The Autofac documentation says "Register the Autofac middleware FIRST.", many people say app.UseCors should be the very first thing.
I also have an exception handling middleware, which many people also say should be the first thing so that "other middlewares (down the stacktrace) will propagate up and be caught by the try/catch block of this middleware.", and this one makes a lot of sense, since the implementation looks like:
try
{
await Next.Invoke(context);
}
catch...
which one should be first?
what is the correct order for these 3 middleware components
my current Startup Configuration looks like this:
public void Configuration(IAppBuilder app) {
// Add WebApi CORS handling to the OWIN pipeline
app.UseCors(CorsOptions.AllowAll);
// Create and register Owin HttpConfig instance
var config = new HttpConfiguration
{
IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always // Enable error details in http responses
};
// Register the Autofac middleware FIRST. This also adds Autofac-injected middleware
// registered with the container.
var container = AutofacConfig.ConfigureContainer(config);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseNLog();
// Handle exceptions from OWIN middleware components globally
app.UseExceptionHandling();
app.UseOAuth(config);
//... quite a bit more stuff after

I think when the documentation says "Register the Autofac middleware FIRST" it is in the context of stating the right order between the following three components: 1) Autofac middleware, 2) Autofac Web API middleware, and 3) the standard Web API middleware.
CORS is not a part of this list, and it should be configured first: you have to call .UseCors before calling .UseWebApi, or any other middleware that uses requests. Any request managed by any middleware should include the CORS Access-Control headers, otherwise you may get cross-origin access errors. I guess this applies also to your error handling middleware. So it should be configured after CORS (but before the other middleware components, if you want to handle their exceptions).
More info about CORS and Web API in this page. More info about CORS details here.
In fact the exact Autofac documentation comment says exactly "Register the Autofac middleware FIRST, then the Autofac Web API middleware, and finally the standard Web API middleware". In the code example in that documentation they have the standard web api setup code, and after that the OWIN web api setup (which is the section where this "First" applies).
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// STANDARD WEB API SETUP:
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Run other optional steps, like registering filters,
// per-controller-type services, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// OWIN WEB API SETUP:
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
The doc page where I got the code example is here (I guess it is the same you checked).

Related

How can I configure an Azure Function to work with dynamic configuration using Azure App Configuration?

I'm trying to write an Azure Function that works as a multi-tenant. When a clientId comes from the clients as a parameter, I need to fetch its configuration from Azure App Configuration using labels.
Let me explain in a pseudo code;
I'm using .Net 6 Azure Function Isolated.
I made configuration in Program.cs like in the below code;
new HostBuilder()
.ConfigureAppConfiguration(builder =>
{
string cs = "connection-string"; //which is actually comes from environment veriable
builder.AddAzureAppConfiguration(options =>
{
options.Connect(cs);
//options.Select(KeyFilter.Any, Environment.GetEnvironmentVariable("ClientId")); //It works that way, but I don't want to do it. I need to read the clientId while I receive the request
});
})
Let's assume that we made a middleware and a request came out
public RequestMiddleware(){
//Here I need to inject some service
}
//Invoke method of middleware
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next){
HttpRequestData requestData = await context.GetHttpRequestDataAsync();
requestData.Headers.TryGetValues("client-id", out var clientId);
var id = clientId.First();
//And here, I need to configure App Configuration to use the id as a label. As I did in the Program.cs
//like this ; options.Select(KeyFilter.Any, id);
}
Does it possible to load configuration by the label in the request lifecycle? Please keep in mind that Azure App Configuration in the standard tier has a limitation on requests, 3000 per hour. That's why it won't be a good idea to load AppConfiguration each time.
What you can do is work with a static Dictionary to 'cache' and whenever a request with some new client id arrives, you fetch the configuration add it to the dictionary for the future requests.
This document discussed strategies you should think about when using App Configuration in multi-tenant applications.
https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/service/app-configuration
From your description, it looks like you want to load tenant-specific config on-demand instead of all at once at the app startup, so you shouldn't need the code in program.cs. I would recommend using prefixes instead of labels to differentiate the config date for each tenant.
Check out the application-side caching section to learn more what options you have. I imagine, in the middleware, upon every request, you will first check if you have a cached IConfiguration instance for the tenant; if not, you will load the config for this tenant and cache it; if yes, you serve the request based on the config in your cache.

Isolated Azure Function bypass authentication middleware for Swagger UI page

I've created a new .NET 6 Isolated Azure Function.
I've added the specific Nuget package for Swagger/OpenAPI (for Isolated):
Microsoft.Azure.Functions.Worker.Extensions.OpenApi v1.3.0
I then decorate my HttpTrigger Function with the appropriate [OpenApiOperation] attribute and correctly add the ConfigureOpenApi() method inside my Program.cs like so:
using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureOpenApi()
.Build();
host.Run();
Everything works as expected and I can access my swagger UI url:
http://localhost:7001/api/swagger/ui
It's now time to protect my Az Function and add support for JWT token validation.
To do so, I followed this great article:
https://joonasw.net/view/azure-ad-jwt-authentication-in-net-isolated-process-azure-functions
Because I'm inside an Isolated Azure Function I can now leverage middleware and the article does just that. It creates two middleware. So I've added them like so:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults((context, builder) =>
{
builder.UseMiddleware<AuthenticationMiddleware>();
builder.UseMiddleware<AuthorizationMiddleware>();
})
.ConfigureOpenApi()
.ConfigureServices((context, services) =>
{
...
})
.Build();
host.Run();
QUESTION:
Whenever I launch my Azure Function and I try to access my swagger UI url http://localhost:7001/api/swagger/ui
I am now getting a 401 unauthorized since the Authentication Middleware kicks in and since I don't have an authorization header value.
I believe it is normal that I don't have an authorization header value since I'm only trying to look at a swagger UI url.
How can I ask the Authentication middleware to not look for an authorization header if I'm coming from an url that has the word "swagger" in it?
Or is there a better/different way to achieve this?
Thanks
Sincerely
Looking at the documentation, you can use the UseWhen extension method.
you will need to use at least the version 1.8.0-preview1 of the Microsoft.Azure.Functions.Worker nuget package. (See github issue)
Then in you code you should be able to do something like that:
using Microsoft.Azure.Functions.Worker.Extensions.OpenApi.Extensions;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults((hostContext, builder) =>
{
builder.UseWhen<AuthenticationMiddleware>(functionContext =>
{
// Only use the middleware if not related to swagger
// Condition could be improved tho.
return !functionContext.FunctionDefinition.Name.Contains("Swagger");
});
...
})
...
host.Run();

Change server option in middleware

In Fastify I can specify instance options while creating it, e.g.
const fastify = require('fastify')({logger:true, disableRequestLogging: false});
Is it possible to do this in a middleware registered with the instance?
e.g. if I do something like
fastify.register(myPlugin);
and instance of fastify is passed to myPlugin - can I, for example change its disableRequestLogging value while in the middleware?
The router is the what relies on disableRequestLogging to switch on/off logging for the request and the later response.
if (disableRequestLogging === false) {
childLogger.info({ req: request }, 'incoming request')
}
The router does provide a setup function that allows disableRequestLogging to be changed. You can see fastify.js uses router.setup() late in initialisation here to apply some new values.
The problem is fastify doesn't provide access to router as part of it's public API. Only functions like fastify.get/.post/.route etc which allow access to specific components of the router.
Short of modifying the source, I can't see a way. Not even something dodgey like onkeypatching a function in due to the way fastify variables are scoped. Even if you could do that, it would be delving into undefined/untested behaviours.

OWIN static files security

I'm building a SPA that will be sitting in a WebAPI/OWIN app (that will be hosted in IIS) that currently has no MVC components what so ever and the / route will just be index.html.
The whole site will need you to log into Azure AD before you can do anything and we'll then pass a bearer token to the WebAPI calls that are made.
How do you make every request to a static file (or at least, every HTML file) require you to be logged in?
I will tell you how I did it, and how it works for me.
I am using windows authentication, and here is how I configured it:
OwinHttpListener listener = appBuilder.Properties[typeof(OwinHttpListener).FullName] as OwinHttpListener;
listener.Listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
Then, according to this stackoverflow answer, put the following code between your auth middleware (or the auth code like the above code) and the components you want to protect. It will check to ensure that each request is authenticated.
app.Use(async (context, next) =>
{
var user = context.Authentication.User;
if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
{
context.Authentication.Challenge();
return;
}
await next();
});
I haven't tested this, but it is what I'd try first so I'm hoping it puts you on the right track.
Configure your app so OWIN is serving all static files via the StaticFilesMiddleware. This article talks about how to do that
Before you register the static file middleware (with the .UseStaticFiles extension method) create and register your own RequireAuthenticationMiddleware that checks if the request is authenticated and if it isn't returns the appropriate response (401, 403 or whatever). You'll want to register this RequireAuthenticationMiddleware after you configure the OWIN Auth middleware so that the auth details are in the OWIN context.
I haven't attempted that using OWIN middleware yet, but you could always fall back to using a HTTP module that checks for the presence of your auth cookie or bearer token?

Add express middleware for param validations

In a sails.js application is there a simple way of including express-middleware?
For instance extending the request object with express-validator.
Adding express-middleware in a sails application is simple.
create a new policy.
policies
|_
middleware.js / .coffee
Add Express MiddlewareYOUR_MIDDLE_WARE_FILE_NAME.js
Inside your middleware file we create the standard export for node.js
module.exports = require('middle-ware')(OPTIONS_GO_HERE) // See middleware docs for configuration settings.
Then once you have created the middleware you can apply it to all requests or a single controller by following the Sails.js convension.
Entire Applicationpolicies.js
module.exports.policies = {
'*':['middleware'] // node same name as file without extention
}
Single Controller Action policies.js
module.exports.policies = {
RabbitController:{
feed:['middleware']
}
}
First of all, #SkyTecLabs' answer is the proper way to do this. But I wanted to add that, in some cases, you may need to control your static files (images, client-side javascript, css, etc) as well (I just had to deal with this recently). In this case, you can apply middleware generically to every route.
As of Sails.js v0.9.3, you can do:
// Put this in `config/express.js`
module.exports.express = {
customMiddleware: function (app) {
app.use(require('../node_modules/sails/node_modules/express').basicAuth('balderdash', 'wickywocky'));
}
};
More here: https://gist.github.com/mikermcneil/6255295
In the case where you want middleware to run before one or more of your controllers or actions, you're definitely better served using the policy approach though!

Resources