I'm building a middleware for ASP .NET Core 2.1, that would extract some information from the context and inject it into an IService.
Currently there are several services (Profile, Users), all implementing the IService interface.
However, when post-ing to a Profile service, the other Users service is being injected in the middleware.
In the Profile controller, however, the correct service is injected, so it doesn't seem to be a DI problem.
public async Task Invoke(HttpContext context, IService theService)
{
UserInfo serInfo = await GetUserInfoAsync(context).ConfigureAwait(false);
theService.UserInfo = userInfo;
}
According to Microsoft, this should be possible.
Any ideas why this is not working?
Related
I was going through some videos and tutorials on OPA (Open Policy Agent) and found it really cool to use it for implementing Authentication and Authorization across multiple services / APIs. However I am not able to get any insights on how to install it on windows and integrate it with an ASP.Net core Web API to implement Authentication and Authorization. Can anyone help me in this ?
Thanks,
Amit Anand
Without knowing more about your use case or the platform you're running on, here's some general advice.
Architecture. Decide whether you want to run OPA as a sidecar or as a standalone service. That's an architectural question that will depend on latency, performance, and the data you need for your policies. OPA is a building-block designed as a sidecar, but you can build a service around OPA by spinning up multiple copies, load-balancing across them, adding a persistence layer, etc.
Administration. Decide how to load/update policies and log decisions to OPA and if applicable, decide how to load data into OPA.
Service Integration. If you are using a network proxy that intercepts all network traffic going to your services (e.g. Envoy, Linkerd, Kong, ...) you can configure your network proxy to call out to OPA without modifying your .Net service. If you're not using a network proxy, modify your .Net services to make HTTP callouts when your services need policy decisions, using a library where possible to minimize the impact on individual services. The integration page shows how for Java Spring and PHP.
Tim Hinrichs' answer above is on point. However, to add to it here are some specific solutions. Out of the 2 solutions below, I would recommend using the REST API and ASP.NET middleware. Also, while OPA can theoretically be used as an Authentication tool, I would advise against it. It's purpose is Authorization.
Use ASP.NET Authorization Middleware
Firstly, OPA would be running either as it's own service, as a sidecar in k8's, or in a Docker container. OPA's documentation does a good job showing examples on how to implement that so I won't go into specifics.
Here you would create a .NET service that queries OPA's Rest API.
Here is a a complete example here
Here is Microsoft's documentation on using middleware
This is what the middleware would look like.
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Authz.Opa
{
public class OpaAuthzMiddleware
{
private const string ForbiddenMessage = "Forbidden";
private readonly RequestDelegate _next;
private readonly IOpaService _opaService;
public OpaAuthzMiddleware(RequestDelegate next, IOpaService service)
{
_next = next;
_opaService= service;
}
public async Task InvokeAsync(HttpContext context)
{
var enforceResult = await _opaService.RunAuthorizationAsync(context);
if (!enforceResult)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await context.Response.WriteAsync(ForbiddenMessage);
return;
}
await _next(context);
}
}
}
and you would implement it in your startup like this
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Sample
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRouting();
services.AddSingleton<IOpaService, OpaService>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseMiddleware<OpaAuthzMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Use OPA's Wasm compilation
OPA has tooling that can compile Rego policies into executable Wasm modules. They provide documentation here.
It's currently under development, but there is an example on using this in .NET here. Looking at the discussions under that repo's Issues section, it looks like they're still working out some things.
You would need to use one of the available .NET libraries to read the compiled Wasm files, but this is considered to be the fastest evaluation method that OPA offers.
I am trying to understand how to correctly register components and dependencies with Autofac in a MVC 5 application that also uses the following:
Application Services (billing service, etc.)
Hangfire (there is a Hangfire.Autofac integration package)
SignalR (there is a Autofac.SignalR integration package)
NServiceBus (there is a NServiceBus.Autofac integration package)
Quartz.NET (there is a Quartz.Autofac integration package)
Entity Framework (all of the above may or may not need a DbContext injected)
While I understand the purpose of e.g. builder.RegisterType<MyDbContext>().InstancePerRequest() when used as per-request and injected into an MVC controller, I am unclear how the other components need to be registered.
The MVC container I register in OWIN startup.cs class with:
var resolver = new Autofac.Integration.Mvc.AutofacDependencyResolver( container );
DependencyResolver.SetResolver( resolver );
I have an extra Autofac container for SignalR, because it would not work otherwise.
So it all comes down to the question: With what lifetime scope should I register a MyDbContext that is used by a MVC Controller, a SignalR hub, an NServiceBus Message handler, and some application service at the same time?
Is it enough to register MyDbContext as .InstancePerRequest() or is it neccessary to have multiple containers, and with that, should I register MyDbContext with each container?
I am new to Autofac so I'm at a loss as to how I could control when those components are disposed, recreated, etc.
Thank you.
We are developing a website that uses the repository pattern/unit of work approach. We use Autofac to assist with the construction of objects between these tiers of abstraction.
I've written an AutoFac authentication filter that currently grabs Basic Auth headers and creates an IPrincipal object and assigns it to HttpContext.Current.User
In our custom DbContext class I want Autofac to get a copy of this IPrinipal object without having to look into System.Web.HttpContext (in an effort to keep this decoupled)
Does anyone have any hints on how I can get AutoFac to grab this IPrincipal and inject it into
my custom DbContext class on each Web API call?
Any help is appreciated
I am wondering if there is a way to create a class library that contains web API, so I can use the dll as a plug-in, to inject into the MVC application.
Thank you in advance for your help.
Web API methods are called over HTTP, so calling a Web API service requires it to be hosted somewhere and called using a suitable client as detailed in #David's link. You can self-host Web API, so in theory you could have an assembly local to an MVC application which contained a class which set up and then called a self-hosted Web API service.
You would inject the Web API service behind an interface, something like this:
public interface IProductsService
{
IEnumerable<Product> GetAllProducts();
}
...implemented something like this:
public class SelfHostedWebApiProductsService
{
public SelfHostedWebApiProductsService()
{
// Set up a self-hosted Web API service
}
public IEnumerable<Product> GetAllProducts()
{
// Call your self-hosted WebApi to get the products
}
}
Configure your DI container to use SelfHostedWebApiProductsService for the IProductsService interface, and away you go. This article details how to set up and call a self-hosted Web API.
As the SelfHostedWebApiProductsService sets up the self-hosted Web API in its constructor - a relatively expensive operation - you might want to consider giving this class a singleton lifetime in your DI container.
You could Self-Host a Web API:
http://www.asp.net/web-api/overview/hosting-aspnet-web-api/self-host-a-web-api
You can put all your controllers in a Class Library project.
Then use Autofac to resolve the dependencies in your host project:
https://code.google.com/p/autofac/wiki/WebApiIntegration
Disclaimer: I have a fair bit of experience with DI containers but am quite new to Unity.
I have an MVC project that is all wired up with Unity DI using constructor injection and works great. But I now have a service that I want to inject into my controllers (and maybe places other than controllers at some point) and this service needs access to ASP.NET session state. The service's purpose is to manage a list in session and I don't want the list mechanics in my controller.
I realize I could add a Setup method to the service (and it's interface) that my controller could call, passing in a reference to the Session, before using the service, but I don't like that as I may want to make an implementation of the service that uses something other than Session for my state management and also it is implementation specifics leaking into my interface. I also realize I can use HttpContext.Current in my service but I don't want to do that for many reasons, particularly for the issues it creates for unit testing.
Can Unity inject a reference to HttpSessionState into the service's constructor?
There's a couple ways to do this. The easiest is probably to use an injection factory:
container.RegisterType<HttpSessionState>(
new InjectionFactory(c => { return HttpContext.Current.Session; }));
Then anywhere you have a dependency on the HttpSessionState in the graph, the delegate given will run and pull it out of HttpContext.Current.
Of course, this only works if you're doing a new resolve per request.