Welcome Guest, you are in: Login

FDOT Wiki

RSS RSS

Navigation (FDOT Security STS)





Search the wiki
»

PoweredBy
For those who like granular control, but do not want to do transformations,this path is for you. This path has no dependencies on FDOT.Security.STS.Client and does not self-configure in server environments.

Gotchas

Make sure you are using SSL!
Before deploying to a new environment, contact CO-FDOTENTERPRISELIB mail group to set up an entry in the Relying Party Database.
Before deploying to a new environment, make sure the app pool identity you are mapped to has rights to read certificate.




The Example Code

Clientless Code Based Example

The Example Web Config

Web Configuration File for Clientless Code-Based Configuration

The Example Global

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using FDOT.Enterprise;

namespace FDOT.Security.STS.RPExample
{
    public class MvcApplication : HttpApplication
    {
        /// <summary>
        ///  Identity Config based Application_Start
        /// </summary>
        protected void Application_Start()
        {
            var environmentLevel = LocalSettings.EnvironmentLevel;
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            if (environmentLevel == EnvironmentLevel.WorkstationOrUnknown)
                IdentityConfig.ConfigureIdentity(IdentityConfig.StsConfiguration.devToUnit);

            else if (environmentLevel == EnvironmentLevel.Production)
                IdentityConfig.ConfigureIdentity(IdentityConfig.StsConfiguration.prod);

            else if (environmentLevel == EnvironmentLevel.SystemTest)
                IdentityConfig.ConfigureIdentity(IdentityConfig.StsConfiguration.system);

            else if (environmentLevel == EnvironmentLevel.UnitTest)
                IdentityConfig.ConfigureIdentity(IdentityConfig.StsConfiguration.unit);

        }

        private void Application_BeginRequest(object sender, EventArgs e)
        {
            if (String.Compare(Request.Path, Request.ApplicationPath, StringComparison.InvariantCultureIgnoreCase) == 0 &&
                !Request.Path.EndsWith("/"))
            {
                //  This corrects WIF error ID3206 "A SignInResponse message may only redirect within the current web application: '/NHP' is not allowed."
                //  For whatever reason, accessing the site without a trailing slash causes this error.
                if (!Request.Path.EndsWith("/"))
                {
                    Response.Redirect(Request.Path + "/");
                }
            }

            switch (Request.Url.Scheme)
            {
                case "https":
                    Response.AddHeader("Strict-Transport-Security", "max-age=300");
                    break;
                case "http":
                    var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
                    Response.Status = "301 Moved Permanently";
                    Response.AddHeader("Location", path);
                    break;
            }

        }
    }
}

The Example IdentityConfig

using System;
using System.Configuration;
using System.IdentityModel.Configuration;
using System.IdentityModel.Services;
using System.IdentityModel.Services.Configuration;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Security;

namespace FDOT.Security.STS.RPExample
{
    public static class IdentityConfig
    {
        #region Public Properties
        public static string AudienceUri { get; set; }
        public static string Realm { get; set; }
        public static string Authority { get; set; }
        public static string Issuer { get; set; }
        public static string EncryptionThumb { get; set; }
        public static string SigningThumb { get; set; }
        public static string FederationMetadataLocation { get; set; }
        #endregion

        public enum StsConfiguration
        {
            system,
            unit,
            prod,
            devToUnit
        }


        #region Public Methods

        public static void ConfigureIdentity(StsConfiguration stsConfiguration)
        {
            ConfigureIdentity(stsConfiguration.ToString());
        }

        public static void ConfigureIdentity(string configurationKeyPrefix)
        {
            if (!configurationKeyPrefix.EndsWith(":"))
                configurationKeyPrefix = string.Concat(configurationKeyPrefix, ":");

            Realm = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "Realm"));
            AudienceUri = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "AudienceUri"));
            FederationMetadataLocation = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "FederationMetadataLocation"));
            Authority = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "Authority"));
            Issuer = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "Issuer"));
            SigningThumb = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "SigningThumb"));
            EncryptionThumb = ConfigurationManager.AppSettings.Get(string.Concat(configurationKeyPrefix, "EncryptionThumb"));
            if (configurationKeyPrefix != "ida:")
            {
                ConfigurationManager.AppSettings.Set("ida:Realm",Realm);
                ConfigurationManager.AppSettings.Set("ida:AudienceUri", AudienceUri);
                ConfigurationManager.AppSettings.Set("ida:Authority", Authority);
                ConfigurationManager.AppSettings.Set("ida:Issuer", Issuer);
                ConfigurationManager.AppSettings.Set("ida:FederationMetadataLocation", FederationMetadataLocation);
                ConfigurationManager.AppSettings.Set("ida:SigningThumb", SigningThumb);
                ConfigurationManager.AppSettings.Set("ida:EncryptionThumb", EncryptionThumb);
            }
            
            AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;

            FederatedAuthentication.FederationConfigurationCreated +=
                  FederatedAuthentication_FederationConfigurationCreated;
        }
        #endregion

        #region Event Handlers
        private static void FederatedAuthentication_FederationConfigurationCreated(object sender, FederationConfigurationCreatedEventArgs e)
        {
            FederatedAuthentication.FederationConfigurationCreated -= FederatedAuthentication_FederationConfigurationCreated;
            var federationConfiguration = new FederationConfiguration();
            
            e.FederationConfiguration = Create(federationConfiguration);

        }
        #endregion

        #region Helpers
        public static FederationConfiguration Create(FederationConfiguration federationConfiguration)
        {
            var encryptionCertificate = FindCertificate(EncryptionThumb);

            if (encryptionCertificate == null && Realm != ConfigurationManager.AppSettings["devToUnit:Realm"])
            {
                throw new ArgumentOutOfRangeException("EncryptionThumb", "Encryption Certificate is required");
            }
            
            var issuingAuthority = BuildIssuingAuthority();
            var issuerNameRegistry = BuildIssuerNameRegistry(issuingAuthority);
            var identityConfiguration = BuildIdentityConfiguration(issuerNameRegistry);
            var cookieHandler = BuildCookieHandler();

            federationConfiguration.CookieHandler = cookieHandler;
            federationConfiguration.IdentityConfiguration = identityConfiguration;
            var authModesQs = string.Format("authModes={0}", ConfigurationManager.AppSettings.Get("authModes"));
            AddWsFederationConfiguration(federationConfiguration, authModesQs);
            ConfigureCertificates(federationConfiguration, encryptionCertificate);
            ConfigureSSL(federationConfiguration);
            federationConfiguration.IdentityConfiguration.SecurityTokenHandlers.AddOrReplace(
                    new MachineKeySessionSecurityTokenHandler());
            
            return federationConfiguration;
        }

        private static IssuingAuthority BuildIssuingAuthority()
        {
            IssuingAuthority issuingAuthority = new IssuingAuthority(Authority);
            issuingAuthority.Issuers.Add(Authority);
            issuingAuthority.Issuers.Add(Issuer);
            return issuingAuthority;
        }

        private static ValidatingIssuerNameRegistry BuildIssuerNameRegistry(IssuingAuthority issuingAuthority)
        {
            return new ValidatingIssuerNameRegistry(issuingAuthority);
        }

        private static void AddWsFederationConfiguration(FederationConfiguration federationConfiguration,string authModes)
        {
            var wsFederationConfiguration = new WsFederationConfiguration(Issuer,Realm) {SignInQueryString = authModes};
            federationConfiguration.WsFederationConfiguration = wsFederationConfiguration;
            federationConfiguration.WsFederationConfiguration.PassiveRedirectEnabled = true;
        }

        private static IdentityConfiguration BuildIdentityConfiguration(ValidatingIssuerNameRegistry issuerNameRegistry)
        {
            IdentityConfiguration identityConfiguration = new IdentityConfiguration();
            identityConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(Realm));
            identityConfiguration.IssuerNameRegistry = issuerNameRegistry;
            identityConfiguration.DetectReplayedTokens = true;
            return identityConfiguration;
        }
        
        private static CookieHandler BuildCookieHandler()
        {
            return new ChunkedCookieHandler();
        }

        private static void ConfigureCertificates(FederationConfiguration federationConfiguration, X509Certificate2 encryptionCertificate)
        {
            if  (Realm != ConfigurationManager.AppSettings["devToUnit:Realm"])
                federationConfiguration.ServiceCertificate = encryptionCertificate;

            var validatingRegistry = federationConfiguration.IdentityConfiguration.IssuerNameRegistry as ValidatingIssuerNameRegistry;

            if (validatingRegistry != null &&
                Realm != ConfigurationManager.AppSettings["devToUnit:Realm"])
            {
                //not test
                validatingRegistry.IssuingAuthorities.First().Thumbprints.Add(SigningThumb);
                federationConfiguration.IdentityConfiguration.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
                federationConfiguration.IdentityConfiguration.ServiceCertificate = encryptionCertificate;
            }
            else if (validatingRegistry != null &&
                Realm == ConfigurationManager.AppSettings["devToUnit:Realm"])
            {
                //test
                validatingRegistry.IssuingAuthorities.First().Thumbprints.Add(SigningThumb);
                federationConfiguration.IdentityConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
            }
        }

        private static void ConfigureSSL(FederationConfiguration federationConfiguration)
        {
            federationConfiguration.CookieHandler.RequireSsl = true;
            federationConfiguration.WsFederationConfiguration.RequireHttps = true;
        }

        private static X509Certificate2 FindCertificate(string thumb)
        {
            X509Certificate2 cert = null;
            if (!string.IsNullOrEmpty(thumb))
            {
                var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                store.Open(OpenFlags.ReadOnly);
                try
                {
                    var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, thumb, true);
                    if (certificate.Count > 0)
                    {
                        cert = certificate[0];
                    }
                }
                finally
                {
                    store.Close();
                }
                
            }
            return cert;
        }
        #endregion
    }
}



ScrewTurn Wiki version 3.0.4.560. Some of the icons created by FamFamFam.