SharePoint Fest – DC Wrap-up and Slides

SPFDC17PortalBadgev2I continue to feel honored that SharePoint Fest invites me to present at their conferences.  The most recent even was in DC a couple weeks ago.  The attendees were great and both of my talks were well received. As always I really enjoyed the conference and the discussions I had with attendees and the other presenters. This is one of the few times each year that I get to see a lot of my friends who live all over the world.  The next conference is in Denver in June.  I hope to see you there.

I had lots of attendees at both sessions who asked for the slides so I’ve uploaded them here.  They are also available on the SharePoint Fest DC site.  If you have any follow-up questions please email me at paul.stork@bluechip-llc.com.  You can download a copy of the slides from each talk using the links below:

BV 202 – SharePoint 2016: What’s New and Why should I Upgrade?

ECM 104 – Protecting your Content: Demystifying Data Loss Prevention (DLP) in SharePoint 2016

Restricting Anonymous Access to Specific Pages in a SharePoint Site

A question came up several months ago in one of the Developer Panel presentations at the Best Practices Conference about whether access to individual pages could be restricted on a SharePoint anonymous access site. One my friends who was on the panel replied that he didn’t think it was possible. Since I had previously researched that question for a client I pointed out that it was indeed possible, but that it was not an intuitive process. My friend then jokingly asked whether I had Blogged on how to do it and when I responded "No" he pointed out that I shouldn’t be discussing things in public that I hadn’t Blogged on. It was a joke, but he was right. I left the conference fully intending to blog about the process the next week, but never got around to it.  Its now the end of the year and things are slowing down a bit so I plan to fix that issue by blogging on several topics that have fallen by the wayside in the last year. This is just the first.

In a normal anonymous access ASP.NET web site access to specific pages can be restricted by modifying the NTFS security permissions on the specific file to exclude the IUSR_computername user from having read access to the file. But this model raises two issues when trying to do the same thing in a SharePoint anonymous access environment. First, SharePoint doesn’t make use of the IUSR_computername account specified in IIS for anonymous access, so changing the SharePoint permissions associated with this account will have no effect. Second, although security permissions can be configured at the Web site, List/Library, or item level in SharePoint anonymous access can only be configured at the first two of those levels. Adding the IUSR_computername account as a SharePoint user and restricting item level permissions for that user has no effect on the permissions granted to an anonymous user.  So on the surface there appears to be no way to configure anonymous access rights on a specific page or file to require that viewers of that page be authenticated.

But if you dig a little deeper into how anonymous access really works in SharePoint you discover that there is a way to require anonymous access for specific pages and files. First, you need to understand that anonymous access users in SharePoint are actually provided the same permissions that a user with the Limited Access permission level is given.  When you configure anonymous access at the Web site, List or Library level in SharePoint you are telling SharePoint to allow all non-authenticated users access to objects at that level as though they had the Limited Access permission level.  By default this permission level will be inherited by all objects below it in the hierarchy.  It is this Limited Access permission level that gives anonymous users access to list items and documents.  But that only works if security inheritance isn’t broken.  If you edit the specific permissions on a list item or document, that item will only have the permissions you assign to it.  Since you can’t manually assign limited access and anonymous access is not configurable at item or document level this security setting will prevent anonymous users from accessing the list item or document.  When an anonymous user tries to access a document or list item that has specific security settings they will be prompted to log in.

Set Item Security based on Content Type

I’ve seen several queries asking how to limit the items or documents that a user can view.  Audiences can be used to filter views of List items and Library documents.  But Audiences aren’t and never have been security.  If a user wants access to all the items in a list or library all they need to do is create a custom view, no matter what audience they are part of.

So if you want to limit what a user has access to you need to set specific security on each item.  Item level security defaults to inheriting the security settings of the list or library in which they are created.  A user can implement specific security but it requires an additional step on each item created.  You could create items in folders with specific permissions and let the items inherit security from the folders, but then you can’t easily display items from diferent folders in a single view.

So the question is:  How can I set specific security rights automatically based on who the user is, content type, or the value of a metadata field?

In this post I’ll explain how to create an event handler that will automatically set security permissions based on the content type used to create the item.  First, lets look at the code of the event handler.

01: public class ItemSet : SPItemEventReceiver
02: {
03:   public override void ItemAdded(SPItemEventProperties properties)
04:   {
05:     base.ItemAdded(properties);
06:     SPWeb web = properties.OpenWeb();
07:     SPList list = web.Lists[properties.ListId];
08:     SPRoleAssignmentCollection roles = list.RoleAssignments;;
09:     SPListItem addedItem = properties.ListItem;
10:     addedItem.BreakRoleInheritance(false);
11:     foreach (SPRoleAssignment r in roles)
12:     {
13:       if (r.Member.Name.ToString().StartsWith(properties.ListItem.ContentType.Name
14:         .ToString(), StringComparison.CurrentCultureIgnoreCase))
15:       {
16:         addedItem.RoleAssignments.Add(r);
17:       }
18:     }
19:     this.DisableEventFiring();
20:     addedItem.Update();
21:     this.EnableEventFiring();
22:   }
23: }
 

In lines 6-8 the event handler instantiates the Sharepoint web holding the list and walks the heirarchy to get the list instance itself.  We’ll use this later to retrieve the groups that have permission to the list.  Line 9 retrieves the list item that was just added.  Line 10 calls the BreakRoleInteritance method to set the item up with its own security listing.  Passing ‘False’ as a parameter tells Sharepoint not to copy the security settings of the list when breaking inheritance.  The foreach loop in lines 11-18 compares the Name of each user/group who has permissions in the list with the ContentType of the item being added.  If the name of the user/group begins with the name of the Content type it is added to the permissions list of the item.  For example, if the Content type of the item is named ‘TypeA’ then groups named ‘TypeAContribute’ and ‘TypeARead’ would be granted permissions on the item, but a group called ‘TypeBContribute’ would not.  Finally, in lines 19-21 the event handler temporarily suspends event processing and updates the item instance in the Sharepoint database.  Events are temporarily disabled to prevent recursive events like ItemModifying from firing as a result of the security change.

Once the event handler has been strong named, compiled, added to the GAC and activated using a Web scoped feature we are ready to test the results.  The steps are listed below:

  1. Create and add specific content types to the list/library being secured.
  2. Create Sharepoint groups in the top level site of the site collection whose names start with the name of the content type that they should have access to.  For example: TypeAContribute group would have Contribute permissions for TypeA content.
  3. Assign the Sharepoint groups appropriate permission levels to the list. 
  4. Now create a new item in the list and security will automatically be changed so that only groups whose names start with the name of the content type will have access to the item.  For example, when I created an announcement based on a content type called ‘TypeA’ the security was set as shown below:TypeA SecurityWhen a member of one of the TypeA groups logs in they see and can access only the annoncements created using the TypeA content type.�TypeA 

But when a user logs in who is a member of a group called ‘TypeBContribute’ they only see and can access announcements based on the TypeB content type.

TypeB

You could modify the basic shell of this event handler in several ways to meet the requirements of other scenarios.  For example, you could compare the groups with defined permissions in the list to the groups that the author is a member of and only add groups that the author and the list share in common.  Or you could add a custom choice field to the list with the names of sharepoint groups and let the user choose which groups to grant access to when creating the item.  Once you’ve got the basic event handler the only limits on setting security to a local list item is your own creativity.