Question

I am using Windows Authentication since my ASP.NET MVC 5 application is running in the intranet (Active Directory is main claims issuer).

Due to constant 401 handshake between AD and browser on every request, site is being rather slow.

I am now looking into a way to cache claims received from AD in order to get some performance gain.

Is this doable with WIF and SessionAuthenticationModule? Will it stop subsequent requests to AD once SessionSecurityToken is generated? What is the best place to create such a token in ASP.NET pipeline?

Was it helpful?

Solution

  1. Yes it is doable with SAM
  2. Yes you wont have to hit AD each time after initial transformation

what you should do is this

  1. Implement a ClaimsAuthenticationManager on your site. This will intercept your first request and take in your initial ClaimsPrincipal. The initial ClaimsPrincipal will just contain your username and the SIDs of your AD groups.

  2. Inside your implementation of the ClaimsAuthenticationManager you will read out your application specific claims from AD and create a new transformed ClaimsPrincipal. This will then be serialized to an Auth Cookie.

  3. Subsequent requests will be intercepted by SAM and you will not be required to do the claims transformation from AD as you have already done it the first time.

This is how you do it:

  1. Create a ClaimsAuthenticationManager something like this:

    public class AdClaimsAppender : ClaimsAuthenticationManager
      {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
          if (!incomingPrincipal.Identity.IsAuthenticated)
          {
              return base.Authenticate(resourceName, incomingPrincipal);
          }
          var adClaims = GetExtraAdClaims(incomingPrincipal);
          var newClaimsIdentity = new ClaimsIdentity(adClaims, "Windows");
          var newClaimsPrincipal = new ClaimsPrincipal(newClaimsIdentity);
         return base.Authenticate(resourceName, newClaimsPrincipal);
    }
    

    } }

  2. Add the SAM module to your web config

        <system.webServer>
        <modules>
        <add name="SessionAuthenticationModule"
                type="System.IdentityModel.Services.SessionAuthenticationModule,  System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral,  PublicKeyToken=b77a5c561934e089" preCondition="managedHandler"/>
         </modules>
        </system.webServer>
    
  3. Set up your SAM cookie in your global asax

    using System.IdentityModel.Services;
     using System.IdentityModel.Services.Configuration;
    
    
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
      {
          AreaRegistration.RegisterAllAreas();
          RouteConfig.RegisterRoutes(RouteTable.Routes);
            FederatedAuthentication.FederationConfigurationCreated += FederatedAuthentication_FederationConfigurationCreated;
      }
    
    private static void FederatedAuthentication_FederationConfigurationCreated(object sender, FederationConfigurationCreatedEventArgs e)
    {
        //from appsettings...
        const string domain = "";
        const bool requireSsl = false;
        const string authCookieName = "YourSiteAuth"; //default is fedauth, i normally create my own name as it is easier to identify when you have a lot of cookies.
    
        e.FederationConfiguration.CookieHandler = new ChunkedCookieHandler
            {
                Domain = domain,
                Name = authCookieName,
                RequireSsl = requireSsl,
                PersistentSessionLifetime = new TimeSpan(0, 0, 30, 0)
            };
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top