Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self-hosted WebApi Custom Authorization Filter/Attribute using IAutofacAuthorizationFilter #66

Closed
briangullo opened this issue Jun 12, 2022 · 4 comments

Comments

@briangullo
Copy link

Hello,

I've read the Autofac Filter DI documentation several times. There is something I'm missing or not understanding.

I've created a authorization filter :

public class CustomAuthorizationAttribute : AuthorizeAttribute,  IAutofacAuthorizationFilter
    {
        private SettingsManager _settingsManager;       
        public CustomAuthorizationAttribute(SettingsManager settingsManager)
        {           
            _settingsManager = settingsManager;
        }


        public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
        {          
            //do some checking?
            actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "You are not authorized.");
            return Task.FromResult(0);
        }
    }

I wired it up in my Startup.cs like this:


           var builder = new ContainerBuilder();

            HttpListener listener =
            (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
            listener.AuthenticationSchemes =
            AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous;

            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration(); 
               
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());      
            builder.RegisterWebApiFilterProvider(config);

            builder.RegisterType<CustomAuthorizationAttribute>()
             .AsWebApiAuthorizationFilterFor<MyController>(c => c.MyMethod(default(string)))
             .InstancePerRequest();

            builder.RegisterType<SettingsManager>();        

            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
          
            appBuilder.UseAutofacMiddleware(container);
            appBuilder.UseAutofacWebApi(config);
            appBuilder.UseWebApi(config);

I presumed the above would call my Custom filter every time the method was called in my controller. It did not. It ignored my filter.

I tried adding [Authorize] to MyMethod, but that would result in an immediate 401, and never step into my filter.

I tried adding [CustomAuthorize] to MyMethod, that would trigger my filter, but I can't have constructor with parameters using the .NET attribute classes. This pushes me towards using the service locator inside of CustomAuthorize attribute instead of the runtime injection.

So I have 2 question:

  1. Does my code above look correct?
  2. When would a filter using IAutofacAuthorizationFilter be useful, if the above is not possible. What would trigger it?

Thanks!
Brian

.NET Framework 4.8
Autofac 6.2.0
Autofac OWIN 6.0.1
Autofac.WebApi2 6.0.0
Autofac.WebApi2.Owin 6.0.0

@tillig
Copy link
Member

tillig commented Jun 12, 2022

While I don't see anything obvious, I'm on my mobile at the moment and am not doing heavy research. Since I mostly dev on Mac nowadays, it will take a while to be able to set something up to troubleshoot.

This is sort of why the "new issue" page directs "how do I?" questions to Stack Overflow - there are folks doing this stuff all the time that can quickly answer the questions, and the Autofac team monitors there. For issues, only the Autofac team (of, like, three total people) watch, and it means answers may be slow.

I might recommend:

  • See if you can get any type of Autofac filter to work - not just authorization. If you can't get any filter to work, you might be setting something up wrong. For example, sometimes folks think they're using OWIN but are still referencing the global dependency resolver. (Not saying you're doing that, just giving an example.)
  • Look at examples in our Examples repo. Any examples there showing filter usage?
  • Look at the unit tests in this repo. Anything show what you're doing?
  • Are you actually using it as an attribute? Web API makes attributes singletons. I think we touch on that in the docs. What happens if you implement the Autofac interface but don't derive from the attribute?

Anyway, these are the steps I'd have to go through to figure it out. Sadly, I just can't keep every detail of every integration in my head anymore so I don't have these answers at my fingertips. Again, that's why we rely on Stack Overflow - to get more eyes from the community on questions, so we can focus on reproducible issues in the repos.

If you figure it out, post back here so we can close the issue. If you don't... It may take a bit before I can personally come in and figure this out.

@alistairjevans
Copy link
Member

I've taken a quick peek at the code; nothing obvious jumps out at me either. I'd consider:

  • Enabling Autofac Diagnostics, and seeing if Autofac ever resolves an IEnumerable<Meta<Lazy<IAutofacAuthorizationFilter>>>. If it does, then you know that we're actually looking for those filters, and you can hopefully see subsequently in the diagnostics that one item gets loaded from that set.

  • If that doesn't yield anything, consider putting together a minimal recreating project of an Authorization filter not working, outside of any of your other project behaviour. As @tillig said, this sort of stuff, particularly in the OWIN world, can be easily caused by something wrong somewhere else.

@briangullo
Copy link
Author

Thanks @tillig and @alistairjevans . Let me work on your suggestions, and I will report back my findings The first thing I'm going to try is setting up a simple action filter and see if I can get that to work. I'll keep this thread posted. Thanks!

@briangullo
Copy link
Author

Ok... well.. I feel like an idiot. I was working in some new code, not realizing the StartUp.cs was not being used to set up the OWIN environment. Very similar code was being wired up elsewhere in the application, so the OWIN behavior looked very similar. Once I wired up the Startup.cs I built, AutoFac started to work as designed. Sorry for the false alarm.

B

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants