Programmatically set IIS Authentication for a page.

To use Mixed Windows Authentication one of the step is to set set authentication on one page only to be Windows Integrated, but not “allow anonymous”.(see instructions here and here). I wanted to do it from Web Setup Project. So I've created the class IISMetaDataHelper with the method SetIntegratedSecurityOnly Sample of the call is  IISMetaDataHelper.SetIntegratedSecurityOnly(Site, VDir, "Admin/Security/WinLogin.aspx")

Notice that.Net framework doesn't have classes to handle IISMetaData properties and enum for AuthFlags property value. I've created those helper types as well.

Update: to call folderRoot.RefreshCache to make EVERYTHING work

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using System.Xml;

using System.DirectoryServices;

using System.Diagnostics;

using System.IO;

using System.Reflection;

//using FSHelperLib;

namespace FSCSharpLib.IISMetadata

{

    ///

    //see also IISChameleon.INETMGRHelper

    /// Helper methods to access IIS Virtual directories

    ///

    /// Code samples used are from ASP.NET IIS Chameleon Tool(http://www.123aspx.com/redir.aspx?res=33760 and

    /// Creating Virtuals and reading Installed Sites on IIS with.Net(http://west-wind.com/weblog/posts/399.aspx )   

    public class IISMetaDataHelper

    {

        //For debugginh it is convinient to use adsutil.vbs http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d3df4bc9-0954-459a-b5e6-7a8bc462960c.mspx

        /*e.g commands

        C:\Inetpub\AdminScripts\Cscript.exe adsutil.vbs ENUM  W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        C:\Inetpub\AdminScripts\Cscript.exe adsutil.vbs CREATE  W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        C:\Inetpub\AdminScripts\Cscript.exe adsutil.vbs SET W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx/keyType IISWebFile

        C:\Inetpub\AdminScripts\Cscript.exe adsutil.vbs delete  W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        */

        ///

        /// Concat parts of the path using Site Path in format @"/LM/W3SVC/1" passed by Web Setup to path accepted by DirectoryEntry

        ///

        /// Format @"/LM/W3SVC/1"

        /// e.g vKnowledge

        /// e.g @"admin/Security/WinLogin.aspx"

        /// e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        public static void SetIntegratedSecurityOnly(string SiteMetaPath, String VDirRoot, String relPath)

        {

            string MetabasePath = IISMetaPath(SiteMetaPath, VDirRoot, relPath);

            SetIntegratedSecurityOnly(MetabasePath);

        }

        ///

        /// Concat parts of the path using Site Path in format @"/LM/W3SVC/1" passed by Web Setup to path accepted by DirectoryEntry

        ///

        /// Format @"/LM/W3SVC/1"

        /// e.g vKnowledge

        /// e.g @"admin/Security/WinLogin.aspx"

        /// e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        public static string IISMetaPath(string SiteMetaPath, String VDirRoot, String relPath)

        {

            SiteMetaPath = SiteMetaPath.Replace(@"/LM/", "localhost/");

            return @"IIS://" + SiteMetaPath + @"/root/" + VDirRoot + @"/" + relPath;

        }

        ///

        /// SetIntegratedSecurityOnly

        ///

        /// e.g IIS://localhost/W3SVC/1/root/vKnowledge/admin/Security/WinLogin.aspx

        public static void SetIntegratedSecurityOnly(string MetabasePath)

        {

            if (MetabasePath!= string.Empty)

            {

                DirectoryEntry entry = null;

                if (!DirectoryEntry.Exists(MetabasePath))

                {   //Usually files are not  explicitly added to the IIS metabase

                    //See http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic12899.aspx

                    string sFolderPath = StringHelper.LeftBeforeLast(MetabasePath, @"/");//metabasePath.Substring(0,metabasePath.LastIndexOf("/"));

                    string sEntryName = StringHelper.RightAfterLast(MetabasePath, @"/");// metabasePath.Substring(metabasePath.LastIndexOf("/") + 1);

                    DirectoryEntry folder = new DirectoryEntry(sFolderPath);

                    DebugHelper.PrintDirectoryEntryProperties(folder, sFolderPath);

                    //SchemaClassNames are listed in http://blog.crowe.co.nz/archive/2006/06/01.aspx

                    string SchemaClassName = "IIsObject";

                    //can't assign "IIsWebFile" directly, causes HRESULT: 0x8000500F exception. E_ADS_SCHEMA_VIOLATION - The attempted action violates the directory service schema rules".

                // see http://groups.google.com.au/group/microsoft.public.adsi.general/browse\_frm/thread/3b339d218e673aca/050974e5903530e3 

                    entry = folder.Children.Add(sEntryName, SchemaClassName);

//Fortunately ADSUTIL shows the WARNING: The Object Type of this object was not specified or was specified as IIsObject.

//This means that you will not be able to set or get properties on the object until the KeyType property is set.

                    entry.Properties[MetabasePropertyNames.keyType].Value = "IIsWebFile";

                    folder.CommitChanges;

                    entry.CommitChanges;

                }

                //must be created as new, even if entry was just created using Children.Add

                entry = new DirectoryEntry(MetabasePath);

                DebugHelper.PrintDirectoryEntryProperties(entry, MetabasePath);

                AuthFlags nAuthFlags =  (AuthFlags)(entry.Properties[MetabasePropertyNames.AuthFlags][0]);

                nAuthFlags = nAuthFlags & ~AuthFlags.AuthAnonymous; //clear anonymous

                nAuthFlags = nAuthFlags | AuthFlags.AuthNTLM; //Add Integrated

                entry.Properties[MetabasePropertyNames.AuthFlags][0] = nAuthFlags;

                // Chameleon sets Properties["AuthNTLM"] and ["AuthAnonymous"] -does it work?

                 //virtualDirectory.Properties["AuthNTLM"][0] = parametros.AuthNTLM;

                 //virtualDirectory.Properties["AuthAnonymous"][0] = parametros.AuthAnonymous;

                entry.CommitChanges;

             }

        }

    }//class

    public class MetabasePropertyNames

    {// from http://technet2.microsoft.com/WindowsServer/en/Library/271ae19b-853f-4672-b743-5ba126e902db1033.mspx?mfr=true

        //TODO add all Properties

     public const string AuthFlags = "AuthFlags";

     public const string keyType = "keyType";

 }

    [FlagsAttribute]

    public enum AuthFlags

    {//from http://technet2.microsoft.com/WindowsServer/en/Library/271ae19b-853f-4672-b743-5ba126e902db1033.mspx?mfr=true

        AuthAnonymous=1,

        AuthBasic=2,

        AuthNTLM = 4,

        AuthMD5 = 16,

        AuthPassport=64

    }

    //Possible exceptions from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/generic\_adsi\_error\_codes.asp

    // 0x80005006 - The property does not exist, or it does not exist at the access location where you are attempting to set it.

    //0x8000500C-The data type of the property is different than the data type to which you are attempting to set it.

    //0x8000500F exception. E_ADS_SCHEMA_VIOLATION - The attempted action violates the directory service schema rules".  

}

The class uses my DebugHelper class and My StringHelper class

.

This article is part of the GWB Archives. Original Author: Michael Freidgeim

New on Geeks with Blogs