asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

SharePoint Security and .NET Impersonation
By Jay Nathan
Rating: 4.1 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    Microsoft Windows SharePoint Services and SharePoint Portal Server 2003 have become very popular in recent years and have helped many businesses create an infrastructure for sharing and collaborating internal information. Out of the box, SharePoint offers an abundance of functionality that spans many vertical markets and divisions within an organization. From a development perspective, the SharePoint Services platform provides an IT organization the unique opportunity to focus almost exclusively on providing specific domain logic and value-added functionality to the businesses they support. During the process of extending SharePoint it is imperative to understand the SharePoint security model. Several techniques can be applied that will provide the optimum combination of ease of development, deployment, functionality and security. This article explains the fundamentals of SharePoint security under IIS's Windows Authentication mode (SharePoint's Domain Account mode). Custom Web parts will be used to demonstrate SharePoint's security infrastructure, and techniques will be taught for ensuring that an implementation is as secure as possible while providing a clean and consistent user experience.

    SharePoint Authentication

    To authenticate its users, SharePoint has the ability to run under any of the modes that are available in IIS. These include Anonymous, Basic, Integrated Windows or Certificates Authentication (over SSL). This article assumes that SharePoint will be running under Integrated Windows Authentication mode, which is common for internal scenarios where SharePoint is configured for the domain user account mode. Since SharePoint is built upon ASP.NET, it is configured in much the same way as a normal ASP.NET application. The following XML element which defines the authentication mode for a SharePoint installation can be found in the web.config file in the root of a SharePoint installation (c:\inetpub\wwwroot on my server):

    <authentication mode="Windows" />
    
    The <authentication> configuration element tells ASP.NET which mechanism should be used to authenticate users to the site. It is important to note that in addition to this piece of ASP.NET configuration, the SharePoint IIS Web application (Default Web Site on my server) is also configured to authenticate via Windows. The available authentication modes in ASP.NET are Windows, Forms, Passport or None and should not be confused with the authentication modes of IIS.

    Figure 1: IIS 6.0 Authentication Methods dialog box for the SharePoint web application

    Authorization

    Perhaps the most obvious use of security in SharePoint is to regulate the actions and access rights of individual users and groups of users. Integrated Windows Authentication provides a high level of security while maintaining an authentication and authorization structure that lives in harmony with a typical Windows domain.

    Individual domain users and groups can be given access rights to SharePoint sites and resources by being added to SharePoint site groups. A SharePoint site group defines a role such as "Readers", which allows read-only access to a given site. In addition to Readers, there are several more site groups built into SharePoint including Contributors, Web Designers and Administrators. By adding domain users and groups to SharePoint site groups, the authorization structure of SharePoint security begins to take shape. It is also possible to create custom site groups to encapsulate different combinations of permissions.

    As an example of typical authorization structure, consider the following: I create one domain group for my Accounting department and assign it to both the Readers and Contributors site groups on the SharePoint Accounting Web site. I do the same thing for my HR department and its SharePoint site, but I only add my HR domain group to the Readers site group of the Accounting Web site. This allows me to implicitly control membership to SharePoint content based on membership in divisional domain groups. HR has read-only access to content on the Accounting site and Account has read-only access to the HR site. Security can get much more complex than this, but this demonstrates the capabilities of SharePoint authorization as it relates to the Windows domain.

    Impersonation

    To make Windows security integration possible, SharePoint utilizes .NET impersonation. .NET Impersonation allows an application to run under the context of the client accessing an application. With ASP.NET impersonation, IIS is responsible for authenticating users against the domain and passing to ASP.NET an authenticated token, which can then act on behalf of the client. ASP.NET impersonation can be defined implicitly through configuration settings, or, as covered later in this article, explicitly through code. A close look at the web.config file for a SharePoint site reveals the implicit impersonation configuration for a SharePoint installation running under Integrated Windows Authentication mode:

    <identity impersonate="true" /> 
    
    This setting instructs ASP.NET to implicitly act on the behalf of the client who is accessing SharePoint.

    The Problem

    The time will come during a SharePoint customization project where a developer will want .NET code to perform some action that all users of the SharePoint site do not have the permission to perform. For example, accessing and displaying data from lists on other SharePoint sites and virtual servers (through the SharePoint object model), accessing Active Directory, or pushing files to a non-public shared drive. A developer may even need to access data from a SQL Server instance that requires Windows Authentication. Some users will possess the necessary permissions to perform these operations while others won't, and we certainly do not want to grant these permissions to everyone.

    In all cases where the client does not possess the proper permissions to perform any of the actions listed above, SharePoint will cause Internet Explorer to prompt the user for login credentials. To avoid this usability interruption and facilitate smooth access to privileged operations and resources, a custom impersonation solution must be implemented. The code performing these actions must be run under the context of an account that has permission to perform the necessary tasks. After the operations are performed, the security principal should revert back to the client's domain account which SharePoint was originally impersonating.

    Figure 2 - Internet Explorer's network login dialog box

    The Impersonator Class

    There are several steps involved with performing explicit impersonation, which I have wrapped up into a class called Impersonator (download here). The steps for impersonation are as follows:

    1. Authenticate a valid account which possesses the proper permissions to perform the necessary operations
    2. Create a new System.Security.Principal.WindowsIdentity instance that represents the account
    3. Begin impersonating the new Windows identity
    4. Perform actions that require higher permission level
    5. Stop impersonating and revert back to the client's identity

    The goal of wrapping these steps into one class is to write the following simple code to begin impersonation, execute code under the context of a different domain user account, and revert back to the original security context of the client:

    Impersonator i = new Impersonator("SharePointRead", "MARINER", 
    "password123").Impersonate();
    
    // Code requiring higher permissions...
    
    i.Undo();
    
    Note: Instead of hard-coding the account credentials, they should probably be stored in the SharePoint's web.config file or a SQL Server table.

    The first step is to authenticate the user account that has permission to perform the necessary operation. One way of doing this is by utilizing the Win32 LogonUser API call. To make a Win32 call from ASP.NET, we can make use of P/Inoke with the following method declaration:

    [DllImport("advapi32.dll", SetLastError=true)]
    private static extern bool LogonUser(string lpszUsername, 
    					string lpszDomain, 
    					string lpszPassword, 
    					int dwLogonType, 
    					int dwLogonProvider,
    					ref IntPtr phToken);
    
    The LogonUser API function attempts to authenticate an account to a Windows domain with the security credentials that are passed to it. Notice that in the DllImport attribute declaration we are specifying the name of the library in which the function exists and are setting the SetLastError property value equal to true. If the logon is successful LogonUser returns true and also passes a token handle back to the caller that represents the authenticated user to impersonate. This handle is stored in an IntPtr object when returned to a .NET application. If the operation fails, LogonUser returns false and the error code can be retrieved with the following line of code:
    int errorCode = Marshal.GetLastWin32Error();
    
    Marshal.GetLastWin32Error() is a static method that retrieves the last error thrown by an unmanaged P/Invoke call whose SetLastError value is set to true in the DllImport statement.

    Now that we have a token representing our authenticated user, an instance of WindowsIdentity can be created. WindowsIdentity implements the System.Security.Principal.IIdentity interface and is used to represent a Windows user in a .NET application. A WindowsIdentity instance representing the impersonation principal that is needed can be created by simply passing the token handle that was received from LogonUser to the WindowsIdentity constructor:

    WindowsIdentity winIdentity = new WindowsIdentity(handle);
    
    The Impersonator class has a public method called Impersonate() which wraps a call to the WindowsIdentity.Impersonate() method. WindowsIdentity.Impersonate() returns a System.Security.Principal.WindowsImpersonationContext instance, which is stored as a private member of the Impersonator class. The WindowsImpersonationContext instance represents a Windows user before impersonation begins and allows us to stop impersonation by calling its Undo() method. The Impersonator.Undo() method wraps the call to WindowsImpersonationContext.Undo(). Consider the following code extract from the Impersonator class:
    private WindowsImpersonationContext impersonationContext = null;
    
    public void Impersonate()
    {
    	//Logon() returns the WindowsImpersonationContext instance needed
    	this.impersonationContext = this.Logon().Impersonate();
    }
    
    public void Undo()
    {
    	this.impersonationContext.Undo();
    }
    
    Please refer to the accompanying C# files for the complete Impersonator class source code and an example of its use.

    Deployment and Code Access Security

    .NET Code Access Security (CAS) provides a security model that restricts the operations that can be performed and resources that can be accessed by managed code. The security rules imposed by CAS are applied based on a combination of facts about the origin of code and its runtime environment, not the account under which the code is executing. The full extent of CAS is well beyond the scope of this article, but do note that in order for managed code to make unmanaged calls though P/Invoke and manipulate the principal security object within ASP.NET, as the Impersonator class does, SharePoint's security policy must be altered a bit.

    For the sake of this article, let's assume that we need to deploy a Web part that utilizes the Impersonator class. Our code is compiled into an assembly named WebParts.dll, and it will be deployed to the bin directory of the root SharePoint installation (c:\inetpub\wwwroot\bin on my server). After deploying the Web part via stsadm.exe several changes need to be made to the file that defines the security context for Windows SharePoint Services. The default policy file, wss_minimaltrust.config, for WSS can be found in C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\CONFIG. You will want to make a copy of this file and call it wss_customtrust.config.

    To enable the use of unmanaged code and to exercise control over the ASP.NET security principal, the following changes will have to be made to the SharePoint security policy:

    1. Add appropriate SecurityClass references to the <SecurityClasses> element of the policy file
    2. Create a custom permission set to which our Web part assembly will belong
    3. Apply the custom permission set to our assembly by creating custom code group and assigning our assembly to it
    4. Update WSS's web.config file to point at the new security policy

    The security permission classes required for our Impersonator code to run under ASP.NET are EnvironmentPermission and SecurityPermission. SecurityPermission is referenced in the policy file by default, so the only reference we need to add is for the EnvironmentPermission. The following XML fragment should be added somewhere within the <SecurityClasses> element of wss_customtrust.config:

    <SecurityClass Name="EnvironmentPermission" 
    Description="System.Security.Permissions.EnvironmentPermission, mscorlib, 
    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    
    Next, a new permission set must be added to the custom policy file. This permission set defines a group of permissions that will eventually allow our Web part's code to perform COM interoperability and manipulate the application's security principal object. For these two security privileges, we add the UnmanagedCode and ControlPrincipal flags to the SecurityPermission definition and set the Unrestricted property of the EnvironmentPermission class equal to true:
    <PermissionSet
    class="NamedPermissionSet"
    version="1"
    Name="WebPartCustomTrust">
    <IPermission 
    class="SecurityPermission"
    version="1"
    Flags="Execution,UnmanagedCode,ControlPrincipal"
    />
    <IPermission
    class="EnvironmentPermission"
    version="1"
    Unrestricted="true"
    />
    </PermissionSet>
    
    Place this PermissionSet definition as a child under the <NamedPermissionSets> element in the wss_customtrust.config policy file.

    Now we can create a code group called WebPartCustomTrust to which the permission set above will be applied. To determine which assemblies will belong this code group, the UrlMembershipCondition is used. In our case membership will be granted exclusively to the Mariner.WebParts.dll assembly (look at the Url attribute). The following snippet should be added to the policy file as a child of the first <CodeGroup> element (code groups are hierarchical).

    <CodeGroup class="UnionCodeGroup" 
    version="1" 
    PermissionSetName="WebPartCustomTrust">
        <IMembershipCondition 
        class="UrlMembershipCondition" 
                            	    version="1" 
                            	    Url="$AppDirUrl$/bin/Mariner.WebParts.dll" />
    </CodeGroup>
    
    Save the changes to wss_customtrust.config.

    Finally, two small changes need to be made to WSS's web.config file to point it at the new security policy. Under the <SecurityPolicy> element, a new <trustLevel> element must be configured to take advantage of the policy file that we created. The new <trustLevel> element creates a reference to wss_customtrust.config and will looks like this:

    <trustLevel name="WSS_Custom" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\config\wss_customtrust.config" />

    In the <trust> element of the web.config file, change the level attribute to "WSS_Custom", thereby pointing it at the policy reference we just created. Save the web.config file.

    <trust level="WSS_Custom" originUrl="" />
    
    At this point all of the necessary configuration pieces are in place to impersonate a high-privileged user in a very secure way in SharePoint. Running iisreset from the command line will ensure that the new policy is applied to the SharePoint application.

    Conclusion

    SharePoint and ASP.NET take advantage of .NET Impersonation to manage resource access and operations privileges. When implementing custom components that require access to restricted resources, implicit impersonation must be used. By wrapping all of the steps in to the easy-to-use Impersonator class, impersonation can be accomplished in a tidy manner within code. The final step is to properly configure the SharePoint application for secure access to the extended functionality that can be found in ASP.NET. When you develop components for SharePoint remember that it is simply a robust ASP.NET application. SharePoint's is easily extensible as long as an understanding of its architecture exists.

    References

    LogonUser (advapi32.dll):
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/logonuser.asp

    CloseHandle (kernel32.dll):
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/closehandle.asp

    ASP.NET Impersonation:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspnetimpersonation.asp

    Managing Users and Cross-site Groups:
    http://www.microsoft.com/resources/documentation/wss/2/all/adminguide/en-us/stsf02.mspx

    SecurityPermissionFlag Enumeration:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritypermissionssecuritypermissionflagclasstopic.asp

    EnvironmentPermission Class
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemSecurityPermissionsEnvironmentPermissionClassTopic.asp

    Packaging and Deploying Web Parts for Microsoft Windows SharePoint Services
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_sp2003_ta/html/sharepoint_deployingwebparts.asp

    About the Author

    Jay Nathan is a Senior Consultant at Mariner, a business intelligence consulting firm headquartered in Charlotte, NC. He is a Microsoft Certified Professional and has been a Consultant, Solutions Architect and Project Team Lead delivering solutions to the power generation, telecommunications and healthcare industries. Jay's areas of expertise lie in the Microsoft .NET technologies, SQL Server, and BizTalk Server and are augmented by experience in database design, ETL and data conversion, collaborative, and reporting solutions development. Jay is currently working with Microsoft tools such as SharePoint Portal Services, Reporting Services, Analysis Services and Microsoft CRM. He can be reached at jnathan@mariner-usa.com or visit his blog.

    About the Company

    Mariner provides specialized technology products and services that help its clients increase productivity and improve decision making by applying software engineering best practices and principles to dynamic, business intelligence, data warehousing and collaborative solutions. Mariner, a certified Microsoft Gold Partner and a Business Objects Gold Partner, serves a client list that includes Lash Group, National Gypsum, US Bioservices, Transamerica, Blue Cross Blue Shield of NC, Siemens, Bank of America, Mecklenburg County and Russell Corporation. Charlotte, NC-based Mariner Helps Companies Realize their Visions with Technology. www.mariner-usa.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Supporting Products/Tools
    AspEncrypt
    Built around the Microsoft CryptoAPI, AspEncrypt helps you harness all major encryption and hashing algorithms such as DES, Triple-DES, RC2, RC4, RSA, MD5 and SHA1 in just a few lines of code. The component can be used in tandem with AspEmail to send encrypted and signed mail in the industry-standard S/MIME format, or with AspUpload to encrypt files as they are being uploaded. AspEncrypt can also be used to issue and manage X.509 digital certificates.
    [Top]
    AspPDF
    AspPDF is an ASP/ASP.NET component which enables generation and management of documents in PDF format. Features include advanced text formatting, font embedding, form fill-in, images, tables, content and page extraction, document stitching, encryption, digital signatures, and more.
    [Top]
    Other Articles
    Feb 3, 2005 - ASP.NET Mixed Mode Authentication
    In many web applications it is desirable for both intranet users and external parties to be able to seamlessly log onto the system. The problem this raises is that it is not easy to allow intranet users to log in via Windows integrated authentication while also allowing external parties to log in to the same application using standard forms authentication. This article will show you one way to achieve the best of both worlds when it comes to authentication.
    [Read This Article]  [Top]
    Dec 8, 2004 - Designing Role-Based Security Models for .NET
    In this article, Michele Leroux Bustamante discusses authentication, authorization and role-based security in .NET. Along the way, he provides some best practices for implementing role-based security in some typical .NET application scenarios including rich clients, Web applications, and Web services.
    [Read This Article]  [Top]
    Mar 10, 2004 - Intellectual Property Protection and Code Obfuscation
    Learn about the execution process of CLR-based programs and how to protect your applications from being easily disassembled back into source code.
    [Read This Article]  [Top]
    Feb 24, 2004 - How to Send Secure Mail in ASP-Based E-Commerce Applications - Part II
    Businesses that utilize encrypted e-mail may find Secure Multipurpose Internet Mail Extensions (S/MIME) to be somewhat restrictive. This article shows how to use security features in PDF as an alternative to S/MIME.
    [Read This Article]  [Top]
    Feb 2, 2004 - Fighting Spambots with .NET and AI
    Bill Gates, in a recent interview, predicted the end of spam by 2006. One of the methods he mentioned involved a challenge only a real live person could handle. Adnan Masood shows how to use AI and .NET to create a user verification scheme that incorporates similar concepts Gates alluded to.
    [Read This Article]  [Top]
    Jan 21, 2004 - Configuring .NET Code Access Security
    Code Access Security (CAS) is the .NET Framework security model that grants code permission to resources based on "evidence" pertaining to the encapsulating assembly. In this article, David Myers examines CAS and explains different configuration methods.
    [Read This Article]  [Top]
    Mar 10, 2003 - Platform Neutral and Transparent Encryption of Sensitive Customer Information
    Zhenlei Cai combines an open source C++ encryption library with SQL Server extended stored procedures to create a platform neutral, transparent encryption solution that resides at the database layer.
    [Read This Article]  [Top]
    Jan 15, 2003 - Exploring Machine.Config - User Security and More
    Christopher Spann offers a .NET configuration tip that should help ease system administrators' fears of security compromise and thus assuage growing developer demand for a .NET environment.
    [Read This Article]  [Top]
    Dec 10, 2002 - Encrypting Cookie Data with ASP.NET
    You don't have to be a cryptography expert or spend lots of money on third-party components to secure sensitive data in .NET. In this article, Wayne Plourde shows just how easy it is to encrypt cookie data using encryption classes in the .NET System.Security.Cryptography namespace.
    [Read This Article]  [Top]
    Aug 21, 2002 - Web Application Error Handling and Logging For ASP
    One of the most important aspects of an application is how well it responds to the user, and this includes response to errors. In this article, Adam Tuliper shares techniques for catching ASP errors and shows how to create a notification system that is sure to keep customers at bay.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers