Question

I've got an ASP.NET MVC 5 app and I'm trying to get my head round Claims authorization. I've read a bunch of stuff that always sets the ClaimsAuthorizationManager class in the web.config file.

Is it possible to set a custom ClaimsAuthorizationManager in code?

Was it helpful?

Solution

I'm answering my own question. In the ApplicationStart method in my global.asax file, use the following code:

 System.IdentityModel.Services.FederatedAuthentication.FederationConfigurationCreated += (s, e) =>
        {

            e.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager = new MyCustomClaimsAuthorizationManager();
        };

OTHER TIPS

Perhaps this slight elaboration on the answer could help someone else out, as i just went through something quite similar in MVC 5, .NET 4.5.2, and found that it's worth understanding how these components behave under the hood.

My main goal: needed to minimize .config dependency (ffwd: in the time i had available, i found ways to minimize but not completely remove)

The issue i ran in to with this answer's approach is i kept on getting an error saying i was missing config stuff. after some good old reflector-reflection, i found that this is caused by the mish-mosh, daisy chain of static getter, instance construction, and member initialization between the FederatedAuthentication, FederationConfiguation, and IdentityConfigution classes.

First, the FederatedAuthentication class's FederationConfiguration getter property lazy initializes the underlying 'FederationConfiguration' field.

public static FederationConfiguration FederationConfiguration
{
    get
    {
        if (_federationConfiguration == null)
        {
            object federationConfigurationLock = FederationConfigurationLock;
            lock (federationConfigurationLock)
            {
                if (_federationConfiguration == null)
                {
                    _federationConfiguration = CreateFederationConfiguration();
                }
            }
        }
        return _federationConfiguration;
    }
}

To summarize the initialization routine:

  1. call FederatedConfiguration default ctor (which calls in to : this(true), but i digress)
  2. fire the 'FederationConfigurationCreated' event, which your code will handle and do whatever it does
  3. light validation
  4. if not already initialized, kick off initialization chain

    private static FederationConfiguration CreateFederationConfiguration()
    {
        System.IdentityModel.Services.Configuration.FederationConfiguration federationConfiguration = new System.IdentityModel.Services.Configuration.FederationConfiguration();
            federationConfiguration = OnFederationConfigurationCreated(federationConfiguration);
            if (federationConfiguration.IsAmbiguous)
            {
                throw DiagnosticUtil.ExceptionUtil.ThrowHelperError(new ConfigurationErrorsException(System.IdentityModel.Services.SR.GetString("ID7018")));
            }
            if (!federationConfiguration.IsInitialized)
            {
                federationConfiguration.Initialize();
            }
            return federationConfiguration;
        }
    }
    

Understanding this routine is important because, it's not outwardly apparent (at least to me) that if you did hook in to the event and tried doing some off-the-reservation stuff, you need to know to call either the FederationConfig and/or IdentityConfig class' Initialize() methods to potentially avoid some of the side effects that occur if they are otherwise called for you.

There is a pattern of "if is not initialized, call Initialize" that run down the chain of objects and due to the implementation the IsInitialized properties on these classes can only be set to return true if their Initialize() methods successfully complete.

The way I was able to set my custom ConfigurationManager and avoid some errors due to .config dependency was make my event handler smart enough to preemptively call the Initialize() method on the IdentityConfiguration object - this actually changes the path of execution within the framework's IdentityModel classes.

var authZ = new MyClaimsAuthorizationManager();            

FederatedAuthentication.FederationConfigurationCreated += (s, e) =>
{
    var identityConfiguration = e.FederationConfiguration.IdentityConfiguration;

    identityConfiguration.ClaimsAuthorizationManager = authZ;

    if (!identityConfiguration.IsInitialized)
        identityConfiguration.Initialize();
    };
}

There's a few blogs/SO answers that spoke to how to programmatically set this, all of which had the simple loc: e.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager = new MyCustomClaimsAuthorizationManager(); in the event handler; unfortunately for me, this wasn't enough due to what i was trying to accomplish. hopefully this can help someone else where the "simple answer" wasn't enough.

You should be able to set it through the ServiceConfiguration class:

ServiceConfiguration.ClaimsAuthorizationManager = new MyClaimsAuthManager();

Docs: http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.configuration.serviceconfiguration.claimsauthorizationmanager.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top