Dependency Injection into custom ClaimsAuthenticationManager and ClaimsAuthorizationManager

How do you do Dependency Injection on a custom ClaimsAuthenticationManager and ClaimsAuthorizationManager when you use Windows Identity Foundation and Claims Based Authentication? What you want to do is set a Factory or some kind of instance Resolver for the instance creation of the two manager instances. Can this be done? (Concept page for WIF managers and OriginalIssuer)

According to The Man himself Mr. Vittorio Bertocci it was not a scenario that made the cut on the feature list for the current version of WIF:

image

If @vibronet says to try to do it who am I to say no? ;~)

Actually I’ve not done it fully the right way; I’ve cheated but in a way that mitigates the cheat and brings the power of Dependency Injection to the WIF ClaimsAuthenticationManager and ClaimsAuthorizationManager!

The challenge

The two Manager instances are created by your ASP.NET pipeline or WCF pipeline and not by you. When you get power over the instances it is too late. Dependency Injection can’t happen. Or can it? Constructor Injection can’t happen because the instance is already created. Then again all of the IoC container libraries out there have the ability to do Property Injection on already created instances. This is the approach I will use.

The Cheat

In order to do this Property Injection we have to come to a point where we can get to our instances of the managers. Since this happens when you get a request to your WIF enabled service we have to cheat. Avert your eyes! Throw salt over your shoulder and spit etc. ;~)

Note: The code and artifacts for this post are available on the AzureContrib site or with your friendly call to the NuGet package manager: PM> Install-Package AzureContrib.

using System;
using AzureContrib.WindowsAzure.Diagnostics;
using AzureContrib.WindowsAzure.Properties;
using AzureContrib.WindowsAzure.ServiceLocation;
using AzureContrib.WindowsAzure.Utils;
using Microsoft.IdentityModel.Claims;

namespace AzureContrib.WindowsAzure.AppFabric.ACS
{
    /// <summary>
    /// Simple authentication manager which delegates to the real <see cref="IAuthenticationService"/>
    /// </summary>
    public class InjectedClaimsAuthenticationManager : ClaimsAuthenticationManager
    {
        private static IBuilder builder;

        /// <summary>
        /// A hook to access the <see cref="IBuilder"/>.
        /// </summary>
        /// <remarks>Please do no abuse this power!</remarks>
        /// <remarks>The purpose is to enable Dependency Injection on classes that are not createable through a factory!</remarks>
        public static IBuilder Builder
        {
            set { builder = value; }
            internal get
            {
                if (builder == null)
                {
                    throw new Exception(Strings.BuilderIsMissing.F(typeof(InjectedClaimsAuthenticationManager)));
                }
                return builder;
            }
        }

        /// <summary>
        /// <see cref="IAuthenticationService"/>
        /// </summary>
        public IAuthenticationService AuthenticationService { protected get; set; }

        /// <summary>
        /// ctor that uses <see cref="Builder"/> to Dependency Inject this resource.
        /// </summary>
        public InjectedClaimsAuthenticationManager()
        {
            // Perhaps not the prettiest of solutions but this little module is not created through the container.
            Builder.BuildUp(this);
        }

        /// <summary>
        /// <see cref="ClaimsAuthenticationManager.Authenticate"/>
        /// </summary>
        public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
        {
            return AuthenticationService.Authenticate(resourceName, incomingPrincipal);
        }
    }
}

And the same for authorization.

namespaceAzureContrib.WindowsAzure.AppFabric.ACS
{
    /// <summary>
    ///
Simple authorization manager which delegates to the real<see cref="IAuthorizationService"/>
    /// </summary>
  
public classInjectedClaimsAuthorizationManager : ClaimsAuthorizationManager
  
{
        private staticIBuilder builder;

        /// <summary>
        ///
A hook to access the<see cref="IBuilder"/>.
      
/// </summary>
        /// <remarks>
Please do no abuse this power!</remarks>
        /// <remarks>
The purpose is to enable Dependency Injection on classes that are not createable through a factory!</remarks>
      
public staticIBuilder Builder
        {
            set{ builder = value; }
            internal get
          
{
                if(builder == null)
                {
                    throw newException(Strings.BuilderIsMissing.F(typeof(InjectedClaimsAuthenticationManager)));
                }
                returnbuilder;
            }
        }

        /// <summary>
        /// <see cref="IAuthorizationService"/>
        /// </summary>
      
publicIAuthorizationService AuthorizationService { get; set; }

        /// <summary>
        ///
ctor that uses<see cref="Builder"/>to Dependency Inject this resource.
      
/// </summary>
      
publicInjectedClaimsAuthorizationManager()
        {
            // Perhaps not the prettiest of solutions but this little module is not created through the container.
          
Builder.BuildUp(this);
        }

      
/// <summary>
        /// <see cref="ClaimsAuthorizationManager.CheckAccess"/>
        /// </summary>
      
public override bool CheckAccess(AuthorizationContext context)
        {
            returnAuthorizationService.CheckAccess(context);
        }
    }
}

As you can see when the instances of the two Manager classes are created they grab the Builder of the static. While I detest this type of code this is a means to an end. The Builder must be set in place during application start up so that it is available when the WIF pipeline is activated.

InjectedClaimsAuthenticationManager.Builder = applicationBuilder;
InjectedClaimsAuthorizationManager.Builder = applicationBuilder;

Now it seems there has to be some kind of IBuilder? What this will do is perform Dependency, or in this case Property, Injection on the Manager classes effectively resolving and injecting live instances of, IAuthenticationService and IAuthorizationService. So what about those contracts? Here they are:

The Magic contracts

The following contracts are used to enable Property Injection and Inversion of Control on the Manager classes.

namespace AzureContrib.WindowsAzure.ServiceLocation
{
    public interface IBuilder
    {
        void BuildUp(object o);
    }
}

namespace AzureContrib.WindowsAzure.AppFabric.ACS
{
    public interface IAuthenticationService
    {
        IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal);
    }
    public interface IAuthorizationService
    {
        bool CheckAccess(AuthorizationContext context);
    }
}

OK so there is not very much magic here. Perhaps a little. The IBuilder instance is a hook to our underlying IoC container and it’s .BuildUp method. The IAuthenticationService and IAuthorizationService both map exactly to the two methods in their respective "”parent” Manager class.

The whole flow

1) Configure WIF for your application and specify the two Injection enabled Manager classes.

2) Start up the application. The IoC container is instantiated and configured. Wrap up the container in an IBuilder instance and set the instance of the IBuilder on the static hook in the to Manager classes.

Now we’re ready to rumble and receive traffic which uses WIF and Claims Based Auth.

3) On an incoming call the app host environment invokes the WIF pipeline and creates the instances of the two Manager classes.

4) When they are constructed the Managers reach out and do .BuildUp on themselves.

5) The real instances that handle authentication and authorization are resolved, injected, and any subsequent calls to .Authorize or .CheckAccess is forwarded to them.

6) All that is left now is to implement the IAuthenticationService and IAuthorizationService but I’ll leave that as an exercise to the reader! ;~)

At least the two service implementations are now fully testable! An naturally you don’t have to write tests for the two Manager classes since it’s effectively three lines of code or something. But you can if you want.

Summary

Sometimes a little pragmatism is in order. I cannot test the logic in my InjectedClaimsAuthenticationManager or my InjectedClaimsAuthorizationManager. In this case it does not matter since I’ll be having a lot of integration tests which will secure those few lines of code. One annoyance that remains is of course the static. I feel dirty just mentioning it. But as stated above it is a means to an end and if not abused it’s power can be harnessed and it’s weakness be contained. The problem with statics are very many but one obvious one of the top of my head is testing. Some times statics hold on to values between tests.

The end result here is fully separable and testable logic in the WIF Claims Authentication code and that is not bad at all!

HTH!

Cheers,

M.

posted @ Tuesday, September 06, 2011 12:00 PM

Print

Comments on this entry:

No comments posted yet.

Your comment:



 (will not be displayed)


 
 
 
Please add 5 and 3 and type the answer here:
 

Live Comment Preview: