Registering OWIN IAuthenticationManager using Castle Windsor

Since the implementation IAuthenticationManager

can be obtained from the OWIN context, but the registration of the Castle Windsor component must be done before the components are resolved, how can I register IAuthenticationManager

as a component to be inserted anywhere?

AFAIK, I have to use Component.For<IAuthenticationManager>().UsingFactoryMethod(...)

, but since I'm using OWIN / Katana, something HttpContext.Current.GetOwinContext()

doesn't seem to work (and if it does, I wouldn't want to add a dependency to System.Web

for that ...).

What's the solution for this right now?

+3


source to share


2 answers


Temporary (or permanent) solution ...

This is how I managed to solve the problem.

First of all, I have implemented simple OWIN intermediate information:

public sealed class WindsorMiddleware : OwinMiddleware
{
    public WindsorMiddleware(OwinMiddleware next) : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        CallContext.LogicalSetData("owinContext", context);

        await Next.Invoke(context);

        CallContext.FreeNamedDataSlot("owinContext");
    }
}

      

And I configured IAuthenticationManager

with ComponentRegistration<T>.UseFactoryMethod

, so I applied an extension method like this:

public static ComponentRegistration<TService> UseOwinComponentFactoryMethod<TService>(this ComponentRegistration<TService> registration)
    where TService : class
{
    return registration.UsingFactoryMethod
    (
        (kernel, componentModel, creationContext) =>
        {
            IOwinContext owinContext = CallContext.LogicalGetData("owinContext") as IOwinContext;

            Contract.Assert(owinContext != null);

            if (creationContext.RequestedType == typeof(IAuthenticationManager))
            {
                return (TService)owinContext.Authentication;
            }
            else
            {
                throw new NotSupportedException();
            }
        },
        managedExternally: true
    );
}

      



Finally, I registered IAuthenticationManager

as follows:

Component.For<IAuthenticationManager>().UseOwinComponentFactoryMethod().LifestyleTransient()

      

It smells ...

By the way, I'm not sure about the reliability of this solution, as it should work unless you try to resolve components on a thread other than the request.

Unfortunately, there must be many situations where this solution can fail. If your code implements non-blocking I / O, I expect to try adding IAuthenticationManager

from another thread from the one that sets "owinContext" to CallContext

...

I will continue to wait for other answers while I find a better and more elegant solution.

+2


source


For those that don't mind the dependency System.Web

, the following code should work (and doesn't require middleware).

private static IAuthenticationManager GetAuthenticationManager(IKernel kernel, ComponentModel componentModel, CreationContext creationContext)
{
    var owinContext = new HttpContextWrapper(HttpContext.Current).GetOwinContext();

    return owinContext.Authentication;
}

      



Then in your windsor installer of your castle:

container.Register(Component.For<IAuthenticationManager>()
                            .UsingFactoryMethod(GetAuthenticationManager, managedExternally: true)
                            .LifestyleTransient())

      

0


source







All Articles