Sharepoint RunWithElevatedPrivileges and Access Denied error

Hi everyone,

in this short article i try to explain most common error of Access Denied cause by misusage of SPSecurity.RunWithElevatedPrivileges() method.

Here is the wrong code sample:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    //never use like this
    SPList list = SPContext.Current.Web.Lists["SomeList"];
    SPListItem item = list.GetItemById(12);
    item["Title"] = "Some Changes";
    item.Update();
});

The code defined above cause Access Denied when a user request without privs. Beacuse SPContext still contains unpriviledged user rights.If you call any object from SPContext it work with actual user (unpriviledged) rights not the admin rights.

Now is the correct one:

Guid webID = SPContext.Current.Web.ID;
Guid siteID = SPContext.Current.Site.ID;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite site = new SPSite(siteID))
    {
        site.AllowUnsafeUpdates = true;
        using (SPWeb web = site.OpenWeb(webID))
        {
            web.AllowUnsafeUpdates = true;
            SPList list = web.Lists["SomeList"]; //attention here !!!
            SPListItem item = list.GetItemById(12);
            item["Title"] = "Some Changes";
            item.Update();
        }
    }
});

Yep its a little extra codding . I give you a good pattern for using this with more easy and shorter usage:
I created once a static class and add to my project this class named RunAsAdmin and one static method named Run which is taking a delegate method for run our  RunWithElevatedPrivileges codes.

public static class RunAsAdmin
{
    public delegate void RunWithAdminDelegate(SPSite site, SPWeb web);
    public static void Run(RunWithAdminDelegate myDelegate)
    {
        Guid webID = SPContext.Current.Web.ID;
        Guid siteID = SPContext.Current.Site.ID;
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            using (SPSite site = new SPSite(siteID))
            {
                site.AllowUnsafeUpdates = true;
                using (SPWeb web = site.OpenWeb(webID))
                {
                    web.AllowUnsafeUpdates = true;
                    myDelegate.Invoke(site ,web );
                }
            }
        });
    }
}

Usage of this code is:

RunAsAdmin.Run((site,web)=>
 {
    SPList list = web.Lists["SomeList"];
    SPListItem item = list.GetItemById(12);
    item["Title"] = "Some Changes";
    item.Update();
});

Its very useful :))
Happy coding with sharepoint 🙂


The security validation for this page is invalid.

When you working with sharepoint and  you encounter with this error:

The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again:

Solution is easy:

set “AllowUnsafeUpdates” propery true.

Example:

Guid webID = SPContext.Current.Web.ID;
Guid siteID = SPContext.Current.Site.ID;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite site = new SPSite(siteID))
    {
        site.AllowUnsafeUpdates = true;
        using (SPWeb web = site.OpenWeb(webID))
        {
            web.AllowUnsafeUpdates = true;
            //your code here...
        }
    }
}

c# LDAP can not Reset Password [SOLVED]

Hi Everyone ,

When i am working with LDAP noticed that the resetting password is very problematic . Finally i have found a solution.First of all you should configure your  activedirectory server with ssl authentication i’m not sure it isnecessary
but too many blogs and forums say to do that. Well ,to do so 🙂

And use this code to reset password in your client application

public static void ResetPassword(string dn,string userCN,string newpassword, string admin,string adminpass)
{
    //Create an active directory context
    DirectoryContext objContext = new DirectoryContext(DirectoryContextType.Domain,
        dn,
        admin,//you need admin privs.
        adminpass);
    Domain objDomain = Domain.GetDomain(objContext);
    DirectoryEntry de = objDomain.GetDirectoryEntry();
    //geting user password
    DirectoryEntry passUser = de.Children.Find("OU=PORTAL").Children.Find("CN=" + userCN);
    using (passUser)
    {
        //this is the common error line if you do not set correct configuration
        passUser.Invoke("SetPassword", new object[] { newpassword });
        passUser.CommitChanges();//don't forget to commint
    }
}

Usage is simple:

ResetPassword(“testdomain.umbrellacorp.local”, “MyTestUser”, “secret”, “testdomain\\admin”, “adminsecret”);

Someone who encounter with “Invoke SetPassword” error that possible forget to use DirectoryContext class.
DirectoryContext is the key point .This class can access server with appropriate connection settings.You dont need to
set any client configuration for example port,protocol etc.

For more information with DirectoryContext
http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.directorycontext.aspx

Happy codding …

c# LDAP Delete Active Directory user

Usage:
UserDn : ldap path of the user account which is gonna delete.
admin : Priviledged user to delete mean admin account
adminpass : you know what is this 🙂

Example:

DeleteUser(“LDAP://umbrella.com,CN=UserToDelete,OU=PORTAL,DC=TestDomain,DC=Service,DC=Local”,”TestDomain\\Admin”,”secret”);

public static void DeleteUser(string userDn, string admin, string adminpass)
{
    try
    {
        DirectoryEntry user = new DirectoryEntry(userDn, admin, adminpass);
        user.DeleteTree();
        user.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException ex)
    {
        //DoSomethingWith 
     }
}

Sharepoint set user or group to SPListItem

We are going to use a sharepoint web control to get user or groups  named “PeopleEditor” .For using these please fallow the instructions below.

Add fallowing code to top of your page:

<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Add fallowing control to your page front for get users or groups:

Note: If  you want to set or retrieve the account types that are associated with the control use attribute “SelectionSet”
and enums are:

  • User = single user
  • DL = AD distribution list
  • SecGroup = AD security group
  • SPGroup = Sharepoint group

<SharePointWebControls:PeopleEditor runat=”server” ID=”txtScope” MultiSelect=”false” MaximumEntities=”1″ ValidatorEnabled=”true” SelectionSet=”User” Width=”300px”></SharePointWebControls:PeopleEditor>

Add fallowing to your page behind:

using Microsoft.SharePoint.WebControls;
public SPFieldUserValueCollection GetSelectedUsers(PeopleEditor editor)
{
       string selectedUsers = editor.CommaSeparatedAccounts;
       // commaseparatedaccounts returns entries that are comma separated. we want to split those up
       char[] splitter = { ',' };
       string[] splitPPData = selectedUsers.Split(splitter);
       // this collection will store the user values from the people editor which we'll eventually use
       // to populate the field in the list
       SPFieldUserValueCollection values = new SPFieldUserValueCollection();
       // for each item in our array, create a new sp user object given the loginname and add to our collection
       for (int i = 0; i < splitPPData.Length; i++)
            {
                string loginName = splitPPData[i];
                if (!string.IsNullOrEmpty(loginName))
                {
                    SPUser user = SPContext.Current.Web.SiteUsers[loginName];
                    SPFieldUserValue fuv = new SPFieldUserValue(SPContext.Current.Web, user.ID, user.LoginName);
                    values.Add(fuv);
                }
            }
            return values;
        }
}

And now i describe add to listitem and update:

SPList list = SPContext.Current.Web.Lists[APPLIB];
SPListItem item = list.Items.Add();
item["ProgramAdmin"] = GetSelectedUsers(txtScope);
item.Update();

That’s all.

c# LDAP create new active directory user

public static string CreateUserAccount(string ldapPath, string userName, string userPassword)
{
    string oGUID = string.Empty;
    try
    {
        //    for example an ldap path : 
        //    10.20.12.11:389/OU=PORTAL,DC=TESTDOMAIN,DC=entptst,DC=local
        string connectionPrefix = "LDAP://" + ldapPath;
        DirectoryEntry dirEntry = new DirectoryEntry(connectionPrefix, "TESTDOMAIN\\admin", "secret");
        DirectoryEntry newUser = dirEntry.Children.Add("CN=" + userName, "user");
        newUser.Properties["samAccountName"].Value = userName;
        newUser.CommitChanges();
        oGUID = newUser.Guid.ToString();

        //If you dont have an SSL connection you can not set password
        newUser.Invoke("SetPassword", new object[] { userPassword });
        newUser.Properties["LockOutTime"].Value = 0;

        //Enable user
        int val = (int)newUser.Properties["userAccountControl"].Value;
        newUser.Properties["userAccountControl"].Value = val & ~0x2;

        newUser.CommitChanges();


        dirEntry.Close();
        newUser.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingwith --> E.Message.ToString();

    }
    return oGUID;
}