The Authentication Web Service is configured for Windows Authentication, so the credentials are automatically encrypted and validated against the Active Directory for the domain.  As we know already, though, not all of the users identified in Active Directory are meant to be users of our application: only those in the YourApplicationUsers group, who, thanks to our work with MIIS, are now in a dedicated directory partition in ADAM.  So, let us turn our attention to what happens in the Authentication Web Service. 

 

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.Web;

using System.Web.Services;

using Authorization = AZROLESLib;

using Microsoft.DeveloperAndPlatformEvangelism.Demonstrations.Service;

 

namespace Microsoft.DeveloperAndPlatformEvangelism.Demonstrations.Service

{

       public class TaskVisionII_Authentication : System.Web.Services.WebService

       {

              public TaskVisionII_Authentication()

              {

                     //CODEGEN: This call is required by the ASP.NET Web Services Designer

                     InitializeComponent();

              }

 

              #region Component Designer generated code

             

              //Required by the Web Services Designer

              private IContainer components = null;

                          

              /// <summary>

              /// Required method for Designer support - do not modify

              /// the contents of this method with the code editor.

              /// </summary>

              private void InitializeComponent()

              {

              }

 

              /// <summary>

              /// Clean up any resources being used.

              /// </summary>

              protected override void Dispose( bool disposing )

              {

                     if(disposing && components != null)

                     {

                           components.Dispose();

                     }

                     base.Dispose(disposing);         

              }

             

              #endregion

 

              private const string c_sConfigurationSection_Authorization = @"Authorization";

             

              private const string c_sKey_Authorization_Store = @"Store";

              private const string c_sKey_Authorization_Application = @"Application";

             

              private const byte c_byFlag_Authorized = 0;

 

              [WebMethod]

              public CUser rAuthenticate()

              {

                     try

                     {

                           CUser rUser = new CUser();

                           rUser.sName = this.User.Identity.Name.Split(@"\".ToCharArray(),2)[1];

                           if((rUser.sName == null)||(rUser.sName == string.Empty))

                           {

                                  throw new Exception();

                           }                          

                          

                          

                           //Authorization (as opposed to authentication code omitted . . . we'll see it later. 

                          

                           ActiveDs.IADsUser rUser_ADAM = CADAM.rGetUser(rUser.sName);

                           if(rUser_ADAM != null)

                           {

                                  rUser.sLanguage_Preferred = rUser_ADAM.Get(@"preferredLanguage").ToString();

                           }

                           else

                           {

                                  throw new Exception();

                           }

                          

                           return rUser;

                     }

                     catch(Exception rException)

                     {

                           return null;

                     }

 

                    

              }

 

             

                    

                    

             

             

 

             

       }

}

 

 

That Web Service passes the user identifier portion of the user’s credentials to the GetUser method of a class that knows how to talk to ADAM. 

 

using System;

using System.Collections;

using System.Configuration;

using System.DirectoryServices;

 

namespace Microsoft.DeveloperAndPlatformEvangelism.Demonstrations.Service

{

       public class CADAM

       {

              private const string c_sConfigurationSection_Credentials = @"ADAMCredentials";

              private const string c_sConfigurationSection_ADAMInstance = @"ADAMInstance";

 

              private const string c_sKey_Credentials_UserName = @"UserName";

              private const string c_sKey_Credentials_Password = @"Password";

              private const string c_sKey_ADAMInstance_ADsPath = @"ADsPath";

              private const string c_sKey_ADAMInstance_Server = @"Server";

              private const string c_sKey_ADAMInstance_Port = @"Port";

              private const string c_sKey_ADAMInstance_Country = @"Country";

              private const string c_sKey_ADAMInstance_ApplicationDirectoryPartition = @"ApplicationDirectoryPartition";

              private const string c_sKey_ADAMInstance_UserContainer = @"UserContainer";

             

              private const string c_sProvider = "LDAP";

 

              private CADAM()

              {

              }

 

              public static ActiveDs.IADsUser rGetUser(string sIdentifier)

              {

                     try

                     {

                           ActiveDs.IADsUser rUser = null;

 

                           System.Collections.Hashtable rConfigurationSection = null;

                          

                           rConfigurationSection = (System.Collections.Hashtable)System.Configuration.ConfigurationSettings.GetConfig(CADAM.c_sConfigurationSection_Credentials);

                           string sUserName = (string)rConfigurationSection[c_sKey_Credentials_UserName];

                           string sPassword = (string)rConfigurationSection[c_sKey_Credentials_Password];

 

                           rConfigurationSection = (System.Collections.Hashtable)System.Configuration.ConfigurationSettings.GetConfig(CADAM.c_sConfigurationSection_ADAMInstance);

                           string sServer = (string)rConfigurationSection[CADAM.c_sKey_ADAMInstance_Server];

                           string sPort = (string)rConfigurationSection[CADAM.c_sKey_ADAMInstance_Port];

                           string sCountry = (string)rConfigurationSection[CADAM.c_sKey_ADAMInstance_Country];

                           string sApplicationDirectoryPartition = (string)rConfigurationSection[CADAM.c_sKey_ADAMInstance_ApplicationDirectoryPartition];

                           string sUserContainer = (string)rConfigurationSection[CADAM.c_sKey_ADAMInstance_UserContainer];

                           try

                           {

                                  rUser = (ActiveDs.IADsUser)new DirectoryEntry(string.Format("{0}://{1}:{2}/CN={6},CN={5},O={4},C={3}",CADAM.c_sProvider,sServer,sPort,sCountry,sApplicationDirectoryPartition,sUserContainer,sIdentifier),sUserName,sPassword).NativeObject;

                           }

                           catch(Exception rException)

                           {

                                  System.Diagnostics.Debug.WriteLine(rException);

                           }

                           return rUser;

                     }

                     catch(Exception)

                     {

                           return null;

                     }

              }

       }

}

 

 

The configuration file used by this class looks like so:

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

 

       <configSections>

              <section      name="Authorization"

                                   type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral,

      PublicKeyToken=b77a5c561934e089"

              />

              <section      name="ADAMCredentials"

                                   type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral,

      PublicKeyToken=b77a5c561934e089"

              />

              <section      name="ADAMInstance"

                                   type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral,

      PublicKeyToken=b77a5c561934e089"

              />

              <section      name="Defaults"

                                   type="System.Configuration.DictionarySectionHandler,System, Version=1.0.5000.0, Culture=neutral,

      PublicKeyToken=b77a5c561934e089"

              />

       </configSections>

 

       <Authorization>

              <add key="Store" value="msxml://D:\apps\TaskVisionIIb\AuthorizationStore\TaskVisionII.xml" />

              <add key="Application" value="TaskVisionII" />

       </Authorization>

      

       <ADAMCredentials>

              <add key="UserName" value="hoiuhiouhuyiu" />

              <add key="Password" value="ghfhgrtrytfyvyt" />

       </ADAMCredentials>

      

       <Defaults>

              <add key="PreferredLanguage" value="en-CA" />

       </Defaults>

      

       <ADAMInstance>

              <add key="Server" value="DELLW2K" />

              <add key="Port" value="50000" />

              <add key="Country" value="US" />

              <add key="ApplicationDirectoryPartition" value="TaskVisionII" />

              <add key="ApplicationDirectoryPartitionDescription" value="TaskVisionII Directory Partition" />

              <add key="UserContainer" value="Users"/>

       </ADAMInstance>

    

  <system.web>

 

    <!--  DYNAMIC DEBUG COMPILATION

          Set compilation debug="true" to enable ASPX debugging.  Otherwise, setting this value to

          false will improve runtime performance of this application.

          Set compilation debug="true" to insert debugging symbols (.pdb information)

          into the compiled page. Because this creates a larger file that executes

          more slowly, you should set this value to true o_u108 ?y when debugging aÄd to

          false at all other times. For more information, refer to the documentation about

          debugging ASP.NET files.

    -->

    <compilation

         defaultLanguage="c#"

         debug="true"

    />

    <!--  CUSTOM ERROR MESSAGES

          Set customErrors mode="On" or "RemoteOnly" to enable custom error messages, "Off" to disable.

          Add <error> tags for each of the errors you want to handle.

 

          "On" Always display custom (friendly) messages.

          "Off" Always display detailed ASP.NET error information.

          "RemoteOnly" Display custom (friendly) messages only to users not running

           on the local Web server. This setting is recommended for security purposes, so

           that you do not display application detail information to remote clients.

    -->

    <customErrors

    mode="RemoteOnly"

    />

 

    <!--  AUTHENTICATION

          This section sets the authentication policies of the application. Possible modes are "Windows",

          "Forms", "Passport" and "None"

 

          "None" No authentication is performed.

          "Windows" IIS performs authentication (Basic, Digest, or Integrated Windows) according to

           its settings for the application. Anonymous access must be disabled in IIS.

          "Forms" You provide a custom form (Web page) for users to enter their credentials, and then

           you authenticate them in your application. A user credential token is stored in a cookie.

          "Passport" Authentication is performed via a centralized authentication service provided

           by Microsoft that offers a single logon and core profile services for member sites.

    -->

    <authentication mode="Windows" />

 

       <!--  AUTHORIZATION

          This section sets the authorization policies of the application. You can allow or deny access

          to application resources by user or role. Wildcards: "*" mean everyone, "?" means anonymous

          (unauthenticated) users.

    -->

 

    <authorization>

        <allow users="*" /> <!-- Allow all users -->

            <!--  <allow     users="[comma separated list of users]"

                             roles="[comma separated list of roles]"/>

                  <deny      users="[comma separated list of users]"

                             roles="[comma separated list of roles]"/>

            -->

    </authorization>

    

    <identity impersonate="true"/>

 

    <!--  APPLICATION-LEVEL TRACE LOGGING

          Application-level tracing enables trace log output for every page within an application.

          Set trace enabled="true" to enable application trace logging.  If pageOutput="true", the

          trace information will be displayed at the bottom of each page.  Otherwise, you can view the

          application trace log by browsing the "trace.axd" page from your web application

          root.

    -->

    <trace

        enabled="false"

        requestLimit="10"

        pageOutput="false"

        traceMode="SortByTime"

              localOnly="true"

    />

 

    <!--  SESSION STATE SETTINGS

          By default ASP.NET uses cookies to identify which requests belong to a particular session.

          If cookies are not available, a session can be tracked by adding a session identifier to the URL.

          To disable cookies, set sessionState cookieless="true".

    -->

    <sessionState

            mode="InProc"

            stateConnectionString="tcpip=127.0.0.1:42424"

            sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"

            cookieless="false"

            timeout="20"

    />

 

    <!--  GLOBALIZATION

          This section sets the globalization settings of the application.

    -->

    <globalization

            requestEncoding="utf-8"

            responseEncoding="utf-8"

   />

   

 </system.web>

 

 

 

 

 

</configuration>

 

That method uses the System.DirectoryServices.DirectoryEntry class of the .NET Framework to bind to ADAM and retrieve the user object for the user that is logging in, and passes back a reference to the Active Directory Services Interface for that user object.  If we refer back to the code for the Web Service we see that see that if the GetUser method failed to find a user object for the user logging in to TaskVision, the service throws an exception, thereby preventing anyone who is not one of the users of our application that we had imported into ADAM from accessing the application.  If, on the other hand, an object corresponding to the user is retrieved from ADAM, then the preferred language for that user is added to the data concerning that user that is passed back to the Smart Client.  Of course, in this context, the user’s preferred language is meant to represent the considerable quantity of data about users that real world applications must typically maintain.