<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kirk Evans Blog</title><link>http://blogs.msdn.com/b/kaevans/</link><description>.NET From a Markup Perspective</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>Create the Best App for Office 2013 in 5 Minutes</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/05/06/create-the-best-app-for-office-2013-in-5-minutes.aspx</link><pubDate>Tue, 07 May 2013 04:27:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10416514</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10416514</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/05/06/create-the-best-app-for-office-2013-in-5-minutes.aspx#comments</comments><description>&lt;p&gt;While speaking in Kuala Lumpur for the Ignite developer training, &lt;a href="http://www.grumpywookie.com/"&gt;Chris O’Connor&lt;/a&gt; (aka &lt;a href="https://twitter.com/grumpywookie"&gt;@grumpiewookie&lt;/a&gt;) jokingly said that the whole apps for Office thing needed something catchy, something nostalgic.&amp;#160; We need some obscure JavaScript library to do something interesting, something entertaining yet educational.&lt;/p&gt;  &lt;p&gt;Something like Clippy.&lt;/p&gt;  &lt;p&gt;I searched for all of 30 seconds, and sure enough someone built &lt;a href="https://www.smore.com/clippy-js"&gt;a JavaScript library that lets you put Clippy in a web page&lt;/a&gt;!&amp;#160; I love their tagline, “Our research shows that people love two things: failed Microsoft technologies and obscure Javascript libraries. Naturally, we decided to combine the two.”&lt;/p&gt;  &lt;p&gt;&lt;a href="https://www.smore.com/clippy-js"&gt;&lt;img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3771.image_5F00_39D1B38E.png" width="244" height="106" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;During the lunch hour, I worked on a funny app (with the help of Keenan Newton) and moments later, demo’d an app that featured Clippy.&amp;#160; This is not just an image, Clippy is actually animated, makes sounds, and prints whatever message you feed him to the screen!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0636.image_5F00_7525194C.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1033.image_5F00_thumb_5F00_05BD143B.png" width="244" height="199" /&gt;&amp;#160;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There are a number of actions you can provide the agents, such as moveTo, animate, speak, congratulate, and a bunch of other tricks that you can use to amuse your fellow geeks.&lt;/p&gt;  &lt;p&gt;Creating a Clippy app is ridiculously easy.&amp;#160; There are a few steps, but only a handful of lines of code… the rest is just deployment goo.&amp;#160; We’ll even go one step further by deploying our app for Office as part of a SharePoint document library so that when someone creates a new document we can be sure that Clippy will be there.&lt;/p&gt;  &lt;h2&gt;Create a Document in Excel&lt;/h2&gt;  &lt;p&gt;This demonstration requires Excel 2013 to support the new app model.&amp;#160; Open Excel 2013 and create a document.&amp;#160; This document will be the template used for our app (we could use a blank Excel document, but that doesn’t look as nice in screen shots now does it?)&amp;#160; In Excel 2013 go to the File tab, click New, and choose the Expense Report template.&amp;#160; Save the document somewhere on your hard drive.&lt;/p&gt;  &lt;h2&gt;Creating the Project&lt;/h2&gt;  &lt;p&gt;There are four steps that we need to perform to create the Clippy app.&amp;#160; First, we create a SharePoint-hosted app.&amp;#160; Next, we add an App for Office project item to the app.&amp;#160; We then add a document library that uses the document as its template, and finally we add Clippy to the App for Office.&lt;/p&gt;  &lt;h3&gt;Creating the SharePoint Hosted App&lt;/h3&gt;  &lt;p&gt;This is the really easy part.&amp;#160; In Visual Studio 2012, create a new App for SharePoint 2013 named “MyExpenseReportApp” and click OK.&amp;#160; Give the project a name, URL for debugging, and changed the hosting model to “SharePoint-hosted”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7485.image_5F00_7E31A4CD.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2625.image_5F00_thumb_5F00_729BE78E.png" width="244" height="179" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Done with that step.&lt;/p&gt;  &lt;h3&gt;Add an App for Office&lt;/h3&gt;  &lt;p&gt;Right-click the project node in Visual Studio 2012 and choose Add / New Item.&amp;#160; Choose the “App for Office” project item type and name it “ExpenseReportApp”.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4278.image_5F00_5D3E3226.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8078.image_5F00_thumb_5F00_318D682A.png" width="244" height="182" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;On the next page, uncheck Word and PowerPoint, leaving the option for creating a Task pane app in Excel.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6318.image_5F00_1510764A.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7485.image_5F00_thumb_5F00_3B725995.png" width="244" height="206" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;On the next page, choose the option to insert the app into an existing document, and browse to your expense report document that you just created.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5430.image_5F00_68F37958.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7870.image_5F00_thumb_5F00_2F706961.png" width="244" height="206" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Click Finish.&lt;/p&gt;  &lt;h3&gt;Add a Document Library to the SharePoint App&lt;/h3&gt;  &lt;p&gt;We now need a document library that will use the App for Office as its template for new documents.&amp;#160; Right-click the project node in Visual Studio 2012 and choose “Add / New Item”.&amp;#160; Choose the “List” project item and name it “ExpenseReports”.&amp;#160; Choose the option to create a customizable list template and a list instance using the Document Library content type.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2210.image_5F00_1A12B3F9.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5430.image_5F00_thumb_5F00_4793D3BC.png" width="244" height="180" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Choose Next.&lt;/p&gt;  &lt;p&gt;On the next screen in the wizard, choose the option to use the following document as the template for this library.&amp;#160; Click the browse button, and you should be in the folder that contains your app.&amp;#160; There is a child folder, “OfficeDocuments”, that contains the expense report Excel document that was bound to your app for Office.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4278.image_5F00_6023710C.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8156.image_5F00_thumb_5F00_06855458.png" width="244" height="147" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Once you choose the file, click Finish in Visual Studio.&amp;#160; You now have a document template that contains an app as the template for a document library.&amp;#160; When someone creates a new document for that library, they will see your app.&lt;/p&gt;  &lt;p&gt;The document library will be created in the SharePoint app web, the only way that users will be able to access it is if you provide them the URL or add a UI element like a ribbon button.&amp;#160; Another easy way to get to the document library is simply to update the app manifest to point to the document library.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3386.image_5F00_582BCEAA.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3683.image_5F00_thumb_5F00_70BB6BFA.png" width="244" height="186" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When the app starts, it will be on the all items view for your document library.&lt;/p&gt;  &lt;h3&gt;Add Clippy&lt;/h3&gt;  &lt;p&gt;Now for a little developer ingenuity.&amp;#160; Visit &lt;a title="https://www.smore.com/clippy-js" href="https://www.smore.com/clippy-js"&gt;https://www.smore.com/clippy-js&lt;/a&gt; and download Clippy from GitHub.&amp;#160; There are several folders in the ZIP file that you download, the only ones you need are the 3 files in the Build folder.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4760.image_5F00_2C0ED1B9.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7180.image_5F00_thumb_5F00_0B879207.png" width="244" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Extract those 3 files and add them to Visual Studio 2012 in the Home folder for your App for Office.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8463.image_5F00_24172F57.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7002.image_5F00_thumb_5F00_23AAFC62.png" width="226" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Once you have the files, the rest is easy.&amp;#160; Open the Home.html file.&amp;#160; Add the following CSS reference in the HEAD section.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;link&lt;/span&gt; &lt;span class="attr"&gt;rel&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;clippy.css&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;media&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;You can see where I included it:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8407.image_5F00_4A0CDFAD.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7180.image_5F00_thumb_5F00_14941D88.png" width="244" height="117" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, go to the bottom of the Home.html page and add the implementation details.&amp;#160; &lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;clippy.min.js&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    
    &amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
    clippy.load(&lt;span class="str"&gt;'Clippy'&lt;/span&gt;, &lt;span class="kwrd"&gt;function&lt;/span&gt; (agent) {
        agent.moveTo(0, 200);
        agent.show();
    });
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
Here is a screen shot that again shows where I placed it in my code.

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1538.image_5F00_0C304831.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4784.image_5F00_thumb_5F00_1F70FED0.png" width="244" height="136" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Finally, hit F5 to debug your project.&amp;#160; If you followed along, the app should open to your “ExpenseReports” document library in your app web.&amp;#160; Go to the Files tab and choose New Document / ExpenseReportsContentType.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8562.image_5F00_3008F9BE.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2630.image_5F00_thumb_5F00_5D8A1981.png" width="244" height="193" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That will open Excel using the Expense Report template.&amp;#160; The document contains a reference to our App for Office, so when the app opens we will see Clippy.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2627.image_5F00_0F158717.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5857.image_5F00_thumb_5F00_75AD83DC.png" width="210" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can’t you just imagine their surprise when they open the new expense report app that you’ve been laboring over, and they are delighted that it comes with a built-in help system!&lt;/p&gt;

&lt;h2&gt;For More Information&lt;/h2&gt;

&lt;p&gt;&lt;a title="https://www.smore.com/clippy-js" href="https://www.smore.com/clippy-js"&gt;https://www.smore.com/clippy-js&lt;/a&gt; – source and documentation for Clippy.js&lt;/p&gt;

&lt;p&gt;&lt;a href="http://dev.office.com"&gt;http://dev.office.com&lt;/a&gt; – Learn to build apps for Office 2013&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10416514" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Life+at+Microsoft/">Life at Microsoft</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Microsoft+Office/">Microsoft Office</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Apps/">Apps</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2012/">Visual Studio 2012</category></item><item><title>Clarifying Guidance on SharePoint Security Groups versus Active Directory Domain Services Groups</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/05/06/clarifying-guidance-on-sharepoint-security-groups-versus-active-directory-domain-services-groups.aspx</link><pubDate>Mon, 06 May 2013 18:59:30 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10416422</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10416422</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/05/06/clarifying-guidance-on-sharepoint-security-groups-versus-active-directory-domain-services-groups.aspx#comments</comments><description>&lt;p&gt;I received the following question on the SPYam group on Yammer, and decided to share the information with the broader audience via my blog.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;For SharePoint security Microsoft always recommended to use Active directory group inside SharePoint group. But this guidance now changed Microsoft now recommend:&lt;/p&gt;    &lt;p&gt;&amp;quot;&lt;em&gt;We do not recommend SharePoint groups to assign permissions to sites. When a SharePoint group is used to assign permissions, a full crawl of the index occurs. Instead, we recommend Active Directory Domain Services (AD DS) groups&lt;/em&gt;.&amp;quot;&lt;/p&gt;    &lt;p&gt;[from &lt;a href="http://technet.microsoft.com/en-us/library/ff758656(v=office.14).aspx"&gt;http://technet.microsoft.com/en-us/library/ff758656(v=office.14).aspx&lt;/a&gt;]&lt;/p&gt;    &lt;p&gt;Can someone from Microsoft confirm this please?!&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Happy to try &lt;img class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6765.wlEmoticon_2D00_smile_5F00_6434DD03.png" /&gt;&lt;/p&gt;  &lt;h2&gt;Configuring the Environment&lt;/h2&gt;  &lt;p&gt;To demonstrate the effect of adding a user to a SharePoint group, adding an Active Directory group, and adding users to an Active Directory group, I want to isolate any changes as much as possible from the rest of my environment.&amp;#160; I configured my environment with a new web application CrawlDemo.Contoso.local, and a root site collection using the Team Site template.&amp;#160; The site collection administrator is a single user, “contoso\administrator”.&amp;#160; &lt;/p&gt;  &lt;p&gt;In order to isolate the effect of search crawls to just this web application, I configured a new content source that contains my new web application’s URL.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0160.image_5F00_6AE7E686.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5466.image_5F00_thumb_5F00_155417A4.png" width="244" height="178" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This lets me isolate any crawls to just that one web application.&amp;#160; The rest of the settings for the content source:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Crawl Settings: Crawl everything under the hostname for each start address&lt;/li&gt;    &lt;li&gt;Crawl Schedules: Enable Incremental Crawls&lt;/li&gt;    &lt;li&gt;Content Source Priority: Normal&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I do not have continuous crawls configured for this environment, and none of my content sources are currently scheduled, so I can be sure that crawl information will be isolated to this single web application.&amp;#160; &lt;/p&gt;  &lt;p&gt;Before continuing, I make sure that the crawl account has Full Read permission to the web application by checking the User Policy for the web application in Central Administration.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6763.image_5F00_5BD107AC.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3716.image_5F00_thumb_5F00_0232EAF8.png" width="244" height="142" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Note the text in red:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#ff0000"&gt;Adding or updating Web application policy with new users or groups will trigger a SharePoint Search crawl over all content covered by that policy. This can reduce search crawl freshness and increase crawl load. Consider using security groups at the policy level and add/remove users from security groups to avoid this.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We’ll come back to that later in this post as it is directly relevant to what we are discussing.&lt;/p&gt;  &lt;p&gt;Once everything is configured, I initiate a full crawl of the content source.&amp;#160; Reviewing the Crawl Health report in Central Administration for Crawl Rate, I see that all 37 items were crawled.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7534.image_5F00_7D30314A.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6545.image_5F00_thumb_5F00_3C21B1E6.png" width="244" height="174" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If we focus our attention on the Summary table to the right of the screen, we can see the total items crawled was 37 items.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6866.image_5F00_69A2D1A9.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5468.image_5F00_thumb_5F00_224D7BB7.png" width="179" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This means that the full number of items crawled was 37 items.&amp;#160; When we run an incremental crawl, we should only crawl the changed items and not every item.&amp;#160; The rest of this post focuses on the impact that security changes have on crawling.&lt;/p&gt;  &lt;h2&gt;A Note on Performance&lt;/h2&gt;  &lt;p&gt;I am in no way indicating that my demonstrations in this post be used for any type of performance benchmarking.&amp;#160; I am running all of these tests on a single laptop on a single drive using virtualized images that are not optimized for performance.&amp;#160; Further, I have other processes running on the machine, so the numbers that I show do not represent a production environment.&amp;#160; That said, we can make some general assumptions based on the data represented.&lt;/p&gt;  &lt;h2&gt;Understanding the EventCache &lt;/h2&gt;  &lt;p&gt;In each content database, there is a table named “EventCache” which contains a change log for everything in that content database.&amp;#160; Once the crawl is complete, I query it using the following SQL statement:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;select&lt;/span&gt; EventType, ObjectType, EventTime
&lt;span class="kwrd"&gt;from&lt;/span&gt; EventCache &lt;span class="kwrd"&gt;with&lt;/span&gt; (nolock)
&lt;span class="kwrd"&gt;where&lt;/span&gt; EventTime &amp;gt; &lt;span class="str"&gt;'2013-05-06 16:37:36.750'&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;Note that it is &lt;/em&gt;&lt;a href="http://support.microsoft.com/kb/841057/en-us"&gt;&lt;em&gt;unsupported to query SharePoint’s databases directly&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and should not be done in production without the direct involvement of a Microsoft support engineer.&amp;#160; To minimize any potential effects of the query, I use the &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms187373.aspx"&gt;&lt;em&gt;SQL NOLOCK hint&lt;/em&gt;&lt;/a&gt;&lt;em&gt; to read uncommitted records and avoid introducing a table lock.&amp;#160; &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Initially this query returns zero results because the time stamp used in the query is the last time stamp from when I created the site collection.&amp;#160; Let’s add a few documents to the Documents library in our new site.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1050.image_5F00_1AC28848.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8004.image_5F00_thumb_5F00_080D8E91.png" width="244" height="137" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We query the table again, and this time we see results in the EventCache table in the content database where the documents were added.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4300.image_5F00_209D2BE1.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4606.image_5F00_thumb_5F00_52289976.png" width="244" height="220" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That makes complete sense, 4 documents added, 4 rows in the database.&amp;#160; We initiate an incremental crawl (not a full crawl) and wait for it to complete.&amp;#160; Once complete, click the Crawl Health Reports link in the search service application in Central Administration.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5857.image_5F00_4A9D2A09.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6740.image_5F00_thumb_5F00_45BA764D.png" width="244" height="157" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important part to call out is the Summary table on the right of the screen that shows 12 items were crawled during this incremental crawl, none of which were security items.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8400.image_5F00_305CC0E5.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1638.image_5F00_thumb_5F00_7DF8ED65.png" width="168" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the search crawler tries to determine what changes were applied, it reads the information in the EventCache table to calculate what needs to be crawled. The thing to learn from this section is that there is a table, EventCache, which the crawler uses to determine changes from each of the content databases.&amp;#160; &lt;/p&gt;

&lt;p&gt;I run another incremental crawl, and the number of items decreases to 6 crawled items, and another decreases it to 5 items crawled.&amp;#160; No new rows were in the EventCache table, so SharePoint is simply crawling the top level pages to determine if any content changes appear.&lt;/p&gt;

&lt;h2&gt;Effect of Adding a User to a SharePoint Group&lt;/h2&gt;

&lt;p&gt;Let’s add a single domain user to the “Crawl Demo Members” group.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8081.image_5F00_6F4E4180.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7002.image_5F00_thumb_5F00_5C9947C9.png" width="244" height="146" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now run our SQL query and see that a row has been added to the EventCache table.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4774.image_5F00_7528E519.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1641.image_5F00_thumb_5F00_54A1A567.png" width="240" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new value, EventType 2097152, indicates a change where a member was added to a group (actually, 3 new rows were added, but I am only showing the relevant new row).&amp;#160; Recall that the search crawler reads the information in the EventCache table to calculate what needs to be crawled.&amp;#160; We run another incremental crawl and then inspect the health reports to see what happened.&amp;#160; Notice the red bar that now shows, the legend for the chart indicates this is a “security only” crawl.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0068.image_5F00_13FF58F8.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5355.image_5F00_thumb_5F00_411445C6.png" width="244" height="169" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because we added a user to the group, everything in the site needs to be crawled in order to re-calculate the ACLs for the site.&amp;#160; Focusing on the Summary table at the right, we see that 36 security items were crawled simply because we added a user to a group.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3704.image_5F00_44B260A3.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7411.image_5F00_thumb_5F00_2B4A5D69.png" width="169" height="227" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We next turn to the crawl log to inspect a summary of our crawls so far.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4760.image_5F00_71C74D71.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1651.image_5F00_thumb_5F00_6A3BDE04.png" width="244" height="129" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the value in the “Type” column has a letter “F” (indicating full crawl) or “I” (indicating incremental crawl).&amp;#160; The time for the incremental crawl went from 2:30 to 2:10 to 1:40 before we added a user to the group.&amp;#160; When we added the user to the group, it jumped up to 2:50 again because the ACLs for the items had to be recalculated.&amp;#160; The entire index had to be crawled to calculate ACLs.&lt;/p&gt;

&lt;p&gt;In a large SharePoint environment with many documents, adding a user to a SharePoint group can have a significant impact on crawl performance.&lt;/p&gt;

&lt;h2&gt;Effect of Adding an Active Directory Group to a SharePoint Group&lt;/h2&gt;

&lt;p&gt;We just saw what happens when adding Active Directory Domain Services users to a SharePoint group.&amp;#160; Now let’s see the impact of adding an Active Directory group to a SharePoint group.&amp;#160; The effect will be less educational than before because the results will look nearly identical to what we just saw.&amp;#160; I create a new AD group, “MyCrawlGroup1” and add 12 users to the group in Active Directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1538.image_5F00_69CFAB0F.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0167.image_5F00_thumb_5F00_025F4860.png" width="210" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I add “MyCrawlGroup1” to the “Crawl Demo Members” SharePoint group.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6332.image_5F00_28C12BAB.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7485.image_5F00_thumb_5F00_1D2B6E6C.png" width="244" height="146" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then go to the EventCache table to see what the changes were.&amp;#160; I get 3 new rows, the most important one is highlighted.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7506.image_5F00_40E49606.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0068.image_5F00_thumb_5F00_354ED8C7.png" width="241" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we saw before, this change indicates that a member was added to a group.&amp;#160; We initiate an incremental crawl again, and just like before we see that we have the same number of security-only updates in the index.&amp;#160; Notice the red bar again.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3386.image_5F00_46BF399F.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5736.image_5F00_thumb_5F00_2CEB0370.png" width="244" height="168" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Focusing on the Summary table, we see that we again have 36 security items, the same number as when we added a single user to a SharePoint group.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0552.image_5F00_457AA0C0.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7506.image_5F00_thumb_5F00_1316CD41.png" width="157" height="234" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we check the crawl times, we can see that the time increased again.&amp;#160; This time, the time increased because SharePoint had to calculate the ACLs for the members of the domain group.&amp;#160; While the difference between the time spent calculating the members of the domain group versus adding a user directly is not statistically relevant (the difference of 10 seconds can be attributed to a number of factors), the fact that adding a domain group caused a security crawl is significant.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4278.image_5F00_2BA66A91.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1122.image_5F00_thumb_5F00_241AFB24.png" width="244" height="183" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;The point to understand in this section is that any time you add users or AD groups to SharePoint groups, your next incremental crawl causes the entire index to be crawled in order to calculate the ACLs.&amp;#160; &lt;/p&gt;

&lt;h2&gt;Effect of Adding an Active Directory Group to a Site&lt;/h2&gt;

&lt;p&gt;This should be predictable by now.&amp;#160; We will add an Active Directory group directly to a site instead of adding to a SharePoint group.&amp;#160; This time, I create a group with 12 different users in it called “MyCrawlGroup2”.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8176.image_5F00_519C1AE7.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8463.image_5F00_thumb_5F00_6A2BB837.png" width="209" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will add the group directly to the site, granting this domain group Edit permissions just like the “Crawl Demo Members” group has.&amp;#160; When I go into “Site settings / Site permissions” and click the “Grant Permissions” button, an interesting thing happens, highlighted below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2703.image_5F00_108D9B83.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8176.image_5F00_thumb_5F00_291D38D3.png" width="244" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SharePoint defaults to adding the new user or AD group to an existing SharePoint group.&amp;#160; Since we already proved what happens when you add a domain group to a SharePoint group, let’s change the drop-down to “Edit” instead of “Crawl Demo Members [Edit]”, meaning the group now is added to the site with the same level of permissions as the SharePoint group.&lt;/p&gt;

&lt;p&gt;We query the EventCache table and highlight the interesting row.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1526.image_5F00_76B96553.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5417.image_5F00_thumb_5F00_0F4902A4.png" width="239" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EventType 524288 indicates “change assignment add”, and object type 4 means “Web”, so we are changing the permission on the web itself.&amp;#160; As expected, we run the incremental crawl, and you can guess what happens… a security crawl again.&amp;#160; Notice the red bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7802.image_5F00_07BD9337.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4846.image_5F00_thumb_5F00_54ED8CC2.png" width="244" height="167" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4834.image_5F00_588BA79F.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7484.image_5F00_thumb_5F00_2627D420.png" width="159" height="234" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspecting the crawl log, we see that the time increased again.&amp;#160; Hopefully not statistically relevant, but the time has increased a bit in our crawl logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8561.image_5F00_53A8F3E3.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8176.image_5F00_thumb_5F00_4C1D8476.png" width="244" height="140" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should come as no surprise, adding a security object directly to the site permissions will cause the entire index to be crawled to calculate the ACLs.&lt;/p&gt;

&lt;h2&gt;Effect of Adding Users to Active Directory Groups&lt;/h2&gt;

&lt;p&gt;By now, you’re hopefully wondering, where’s the payoff for trudging through this post and all the pictures and data so far?&amp;#160; Well, you’re here!&amp;#160; Let’s see what happens when I add 12 more users to the security group “MyCrawlGroup1”, testing if adding users to a domain group that is contained within a SharePoint group causes security crawls.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1526.image_5F00_4BB15181.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0131.image_5F00_thumb_5F00_122E418A.png" width="211" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, we query the EventCache table to see if any changes were recorded since the last record was written.&amp;#160; Nope!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2671.image_5F00_0AA2D21D.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3757.image_5F00_thumb_5F00_23326F6D.png" width="240" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With no changes in the EventCache table, our new users will be able to access the site because we added them to the Active Directory group, but no changes were recorded to SharePoint to trigger a security crawl.&amp;#160; We check the report, and see that the “Security only” red bar no longer shows in the graph.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3362.image_5F00_30988273.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4353.image_5F00_thumb_5F00_01D2C9D1.png" width="244" height="166" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further, looking at the crawl log, our crawl time significantly decreased from 3:31 to just 1:50.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5482.image_5F00_484FB9D9.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3660.image_5F00_thumb_5F00_40C44A6C.png" width="244" height="134" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lesson to learn is that adding users to an Active Directory group that already has permission in a SharePoint group does not trigger a full crawl of the index to calculate changes in permissions.&lt;/p&gt;

&lt;p&gt;Now let’s try adding users to our “MyCrawlGroup2”, testing to see if adding users to an Active Directory group that already has permissions to the site causes a full crawl of the index.&amp;#160; I add 12 users to the AD group.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0624.image_5F00_07413A75.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4745.image_5F00_thumb_5F00_664DC7CD.png" width="211" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, there are no new records in SQL.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1780.image_5F00_77BE28A5.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7462.image_5F00_thumb_5F00_253F4869.png" width="240" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And our incremental crawl runs again.&amp;#160; The time stays consistent with zero security updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1614.image_5F00_1DB3D8FC.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1373.image_5F00_thumb_5F00_4415BC47.png" width="244" height="128" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lesson here is that adding users to an Active Directory group that has already been granted permission to a SharePoint site directly does not initiate a full crawl of the index to calculate security changes.&lt;/p&gt;

&lt;h2&gt;Bonus Material: Adding a User Policy to the Web Application&lt;/h2&gt;

&lt;p&gt;By now, you’ve seen that adding a user or AD group to a SharePoint group or site causes a full index to calculate the permissions.&amp;#160; At the beginning of this post, I called out the User Policy button in Central Administration, noting the text in red:&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000"&gt;Adding or updating Web application policy with new users or groups will trigger a SharePoint Search crawl over all content covered by that policy.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Let’s see what happens when we try to add a user.&amp;#160; In a previous post, I covered &lt;a href="http://blogs.msdn.com/b/kaevans/archive/2012/06/02/setting-object-cache-accounts-in-sharepoint-2010.aspx"&gt;PowerShell that configures the object cache accounts&lt;/a&gt;.&amp;#160; Configuring the object cache accounts requires that you add Full Read permission to the Portal Super Reader and Full Control to the Portal Super Reader account.&amp;#160; I add the two accounts as part of the configuration steps necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0121.image_5F00_5CA55997.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6560.image_5F00_thumb_5F00_6E15BA6F.png" width="244" height="187" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I check SQL. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4747.image_5F00_4D8E7ABD.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6472.image_5F00_thumb_5F00_7B0F9A80.png" width="240" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EventType 8192 means change or modify, and object type 2048 means Security Policy.&amp;#160; As you can reasonably expect by now, this causes a full index to calculate permissions as described in the red text on that page.&amp;#160; Notice the red bar is back.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7633.image_5F00_0875AD87.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8055.image_5F00_thumb_5F00_40B4249F.png" width="244" height="140" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lesson to learn is that it is important that you configure the object cache accounts so they have permission to the cache (see my blog posting &lt;a href="http://blogs.msdn.com/b/kaevans/archive/2012/06/02/setting-object-cache-accounts-in-sharepoint-2010.aspx"&gt;Setting Object Cache Accounts in SharePoint 2010&lt;/a&gt;, the same steps apply for SharePoint 2013) while understanding the impact that adding the permission can have on crawl performance.&amp;#160; Adding a user policy to the web application causes a full index to calculate permissions of all objects covered by that policy.&amp;#160; You still need to configure the object cache accounts, but make sure that you plan for the potential impact on crawl performance when you apply this change.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Hopefully this post shed some light on how security works with SharePoint and the effect that adding users or Active Directory groups can have on crawl performance. Adding users to Active Directory groups that have already been granted permissions to SharePoint does not affect crawl performance.&amp;#160; Adding users to Active Directory groups is the recommendation for managing security permissions in SharePoint.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10416422" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Active+Directory/">Active Directory</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Search/">Search</category></item><item><title>How to Allow Only Users Who Have a Community Badge to Your SharePoint 2013 Site</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/04/22/how-to-allow-only-users-who-have-a-community-badge-to-your-sharepoint-2013-site.aspx</link><pubDate>Mon, 22 Apr 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10412789</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10412789</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/04/22/how-to-allow-only-users-who-have-a-community-badge-to-your-sharepoint-2013-site.aspx#comments</comments><description>&lt;p&gt;This post will show how you can secure a web site based on if a user has been given a badge in a SharePoint 2013 community site.&lt;/p&gt;
&lt;h2&gt;Badges and Reputation in SharePoint 2013 Community Sites&lt;/h2&gt;
&lt;p&gt;SharePoint 2013 Community Sites provide a new set of features to implement game theory, or gamification.&amp;nbsp; One feature is called &amp;ldquo;reputation&amp;rdquo;, where participation earns you points.&amp;nbsp; As you earn points, you earn achievements that are reflected as your reputation.&amp;nbsp; The settings for reputation allow you to define your own points system, defining the points earned for creating a post, replying to a post, having a post marked with 4 or 5 stars or &amp;ldquo;liked&amp;rdquo;, and having a post marked as &amp;ldquo;Best Reply&amp;rdquo;.&amp;nbsp; You further define the number of points per level, and whether the achievements are represented as an image or as text.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1682.image_5F00_27B553A6.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6560.image_5F00_thumb_5F00_344300C2.png" alt="image" width="244" height="206" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The second feature to point out is called a Gifted Badge.&amp;nbsp; The site owner will define a set of badges that allow you to define the name of each badge.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1185.image_5F00_05E97B15.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1682.image_5F00_thumb_5F00_65623B62.png" alt="image" width="244" height="189" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This allows a community site owner to define a set of badges and assign them to community members.&amp;nbsp; For instance, you might want to create a badge that calls out if someone has achieved a particular certification level.&amp;nbsp; Just highlight a community site member and the &amp;ldquo;Give Badge&amp;rdquo; button will be enabled in the ribbon in the Moderation tab.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8228.image_5F00_3708B5B5.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2656.image_5F00_thumb_5F00_564B5C88.png" alt="image" width="244" height="92" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once users have been assigned badges, they appear on the front page of the Community site in the &amp;ldquo;Top contributors&amp;rdquo; web part.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3833.image_5F00_23E78909.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2843.image_5F00_thumb_5F00_314D9C0F.png" alt="image" width="222" height="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When I first saw the new Community Sites in SharePoint 2013, I was excited.&amp;nbsp; Of course, there are a ton of things that I would like to see improved, but this is a decent start.&amp;nbsp; To me, the ability to assign badges seemed really cool and I saw a bunch of opportunities such as assigning badges when employees are on-boarded and they complete training courses.&amp;nbsp; Out of the box, all you can do with them is either earn them or assign them.&amp;nbsp; What would be really cool is if you could somehow use them to protect content such that only people who have a specific badge are allowed to use a site.&amp;nbsp; For instance, I could create a badge called &amp;ldquo;Microsoft Certified Professional&amp;rdquo; and only users who have that badge are allowed into the &amp;ldquo;MCPs Only&amp;rdquo; web site.&amp;nbsp; That would allow me to do this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5481.image_5F00_62D909A4.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5086.image_5F00_thumb_5F00_34135102.png" alt="image" width="244" height="181" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That is exactly what we are going to build.&lt;/p&gt;
&lt;h2&gt;Wanna Come In?&amp;nbsp; Show Me Your Badge!&lt;/h2&gt;
&lt;p&gt;Badges are simply items in a list, so how would you use that in order to allow or deny someone access to a site?&amp;nbsp; The solution is a custom claims provider.&amp;nbsp;&amp;nbsp; A claims provider is used to augment a user&amp;rsquo;s claims and to provide name resolution.&amp;nbsp; Augmenting claims simply means adding more claims into the user&amp;rsquo;s token.&amp;nbsp; For instance, I can add a claim that says what the user&amp;rsquo;s favorite basketball team is, what their hair color is, whatever information I want to add to their user token.&amp;nbsp; Here is a screen shot where I added a new claim type &amp;ldquo;http://Microsoft.PFE.Claims/Badges&amp;rdquo; with a value &amp;ldquo;Microsoft Certified Master&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5383.image_5F00_33A71E0D.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6557.image_5F00_thumb_5F00_6EFA83CB.png" alt="image" width="244" height="136" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When the user logs in, our custom claim provider will augment the user&amp;rsquo;s claim set by adding an additional claim indicating if the user has been assigned a badge.&amp;nbsp; If the user has not been assigned a badge, then no claim is added.&lt;/p&gt;
&lt;p&gt;This scenario could be adapted for many other scenarios.&amp;nbsp; Perhaps you have a document library that contains your company&amp;rsquo;s intellectual property, and only people who have authored intellectual property have access to a special site.&amp;nbsp; Maybe you require people to complete training courses before allowing them access to content.&amp;nbsp; There are many ways that you can adapt this scenario.&lt;/p&gt;
&lt;h2&gt;The Badge Custom Claims Provider&lt;/h2&gt;
&lt;p&gt;There are a number of claim providers already registered out of the box, and you can register more than one claim provider to augment claims.&amp;nbsp; Using the Get-SPClaimProvider cmdlet in PowerShell, we can see the claim providers that have been registered.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0677.image_5F00_40A0FE1E.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0284.image_5F00_thumb_5F00_467BA1B7.png" alt="image" width="244" height="52" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Start by creating a new SharePoint 2013 farm solution using the &amp;ldquo;SharePoint 2013 &amp;ndash; Empty Project&amp;rdquo; template.&amp;nbsp; Next, add a class that derives from Microsoft.SharePoint.Administration.Claims.SPClaimProvider.&amp;nbsp; Here is a class diagram of what we will implement.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1754.image_5F00_460F6EC2.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3718.image_5F00_thumb_5F00_6FA339F5.png" alt="image" width="244" height="220" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before we go into the claims provider, let&amp;rsquo;s get our data access layer stuff out of the way.&lt;/p&gt;
&lt;h3&gt;Reading Badges From a Community Site&lt;/h3&gt;
&lt;p&gt;The first step is to create a few classes that store the data we want to work with.&amp;nbsp; The first class is Badge that just holds the ID and Title for the badge.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Microsoft.PFE.ClaimsProviders
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Badge
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ID { get; set; }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Title { get; set; }
    }
}
&lt;/pre&gt;
&lt;p&gt;The next class is BadgeUser, which holds information about the user and the badges that they have been assigned.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Microsoft.PFE.ClaimsProviders
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BadgeUser
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LoginName { get; set; }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;Badge&amp;gt; Badges { get; set; }
    }
}
&lt;/pre&gt;
&lt;p&gt;Now that we&amp;rsquo;ve defined some classes to hold the data, let&amp;rsquo;s create a helper class that can fill them with data.&amp;nbsp; The first method allows us to search for any badges that start with a set of characters.&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 1: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.SharePoint;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 2: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 3: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 4: &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Microsoft.PFE.ClaimsProviders&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 5: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 6: &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BadgeHelper&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 7: &lt;/span&gt;    {   &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 8: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 9: &lt;/span&gt;        &lt;span class="rem"&gt;/// Get the list of badges that start with the partial name.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 10: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 11: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="partialBadgeName"&amp;gt;The characters the badge&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 12: &lt;/span&gt;        &lt;span class="rem"&gt;/// name should start with.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 13: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 14: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A list of badges that match the criteria.&amp;lt;/returns&amp;gt; &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 15: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; List&amp;lt;Badge&amp;gt; GetBadgesByPartialName(&lt;span class="kwrd"&gt;string&lt;/span&gt; partialBadgeName)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 16: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 17: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 18: &lt;/span&gt;            List&amp;lt;Badge&amp;gt; badges = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Badge&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 19: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 20: &lt;/span&gt;            &lt;span class="rem"&gt;//Use RWEP here because the user may not have &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 21: &lt;/span&gt;            &lt;span class="rem"&gt;//access to the site.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 22: &lt;/span&gt;            SPSecurity.RunWithElevatedPrivileges(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 23: &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 24: &lt;/span&gt;                &lt;span class="kwrd"&gt;using&lt;/span&gt; (SPSite site = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPSite(&lt;span class="str"&gt;"http://intranet.contoso.local"&lt;/span&gt;))&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 25: &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 26: &lt;/span&gt;                    SPWeb web = site.OpenWeb(&lt;span class="str"&gt;"Community"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 27: &lt;/span&gt;                    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 28: &lt;/span&gt;                    SPQuery query = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPQuery();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 29: &lt;/span&gt;                    query.Query = &lt;span class="str"&gt;"&amp;lt;Where&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 30: &lt;/span&gt;                                       &lt;span class="str"&gt;"&amp;lt;BeginsWith&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 31: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Title' /&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 32: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;Value Type='TEXT' &amp;gt;"&lt;/span&gt; + &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 33: &lt;/span&gt;                                               partialBadgeName + &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 34: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;/Value&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 35: &lt;/span&gt;                                       &lt;span class="str"&gt;"&amp;lt;/BeginsWith&amp;gt;"&lt;/span&gt; + &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 36: &lt;/span&gt;                                   &lt;span class="str"&gt;"&amp;lt;/Where&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 37: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 38: &lt;/span&gt;                    query.ViewFields = &lt;span class="str"&gt;"&amp;lt;FieldRef Name='ID'/&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 39: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Title'/&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 40: &lt;/span&gt;                                        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 41: &lt;/span&gt;                    SPList badgeList = web.Lists[&lt;span class="str"&gt;"Badges"&lt;/span&gt;];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 42: &lt;/span&gt;                    SPListItemCollection items = badgeList.GetItems(query);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 43: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 44: &lt;/span&gt;                    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 45: &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != items)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 46: &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 47: &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (SPListItem item &lt;span class="kwrd"&gt;in&lt;/span&gt; items)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 48: &lt;/span&gt;                        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 49: &lt;/span&gt;                            badges.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Badge &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 50: &lt;/span&gt;                            { &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 51: &lt;/span&gt;                                ID = item.ID, &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 52: &lt;/span&gt;                                Title = item.Title &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 53: &lt;/span&gt;                            });&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 54: &lt;/span&gt;                        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 55: &lt;/span&gt;                    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 56: &lt;/span&gt;                    &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 57: &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 58: &lt;/span&gt;            });&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 59: &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; badges;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 60: &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The call on line 22 is necessary because the current user may not have access to the community site that we are obtaining data from.&amp;nbsp; You can see this is a pretty simple method that just gets data from a SharePoint list. The next method looks nearly identical in that it gets a list of data based on an exact match rather than a partial match.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// A list of badges that match the exact name.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name="name"&amp;gt;The name of the badge to match.&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;A list of badges that have the exact name.&amp;lt;/returns&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; List&amp;lt;Badge&amp;gt; GetBadgesByExactName(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)
        {            
            List&amp;lt;Badge&amp;gt; badges = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Badge&amp;gt;();

            &lt;span class="rem"&gt;//Use RWEP here because the user may not have &lt;/span&gt;
            &lt;span class="rem"&gt;//access to the site.&lt;/span&gt;
            SPSecurity.RunWithElevatedPrivileges(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;()
            {
                &lt;span class="kwrd"&gt;using&lt;/span&gt; (SPSite site = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPSite(&lt;span class="str"&gt;"http://intranet.contoso.local"&lt;/span&gt;))
                {
                    SPWeb web = site.OpenWeb(&lt;span class="str"&gt;"Community"&lt;/span&gt;);

                    SPQuery query = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPQuery();
                    query.Query = &lt;span class="str"&gt;"&amp;lt;Where&amp;gt;"&lt;/span&gt; +
                                       &lt;span class="str"&gt;"&amp;lt;Eq&amp;gt;"&lt;/span&gt; + 
                                            &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Title' /&amp;gt;"&lt;/span&gt; +
                                            &lt;span class="str"&gt;"&amp;lt;Value Type='TEXT' &amp;gt;"&lt;/span&gt; + 
                                                name + 
                                            &lt;span class="str"&gt;"&amp;lt;/Value&amp;gt;"&lt;/span&gt; +
                                       &lt;span class="str"&gt;"&amp;lt;/Eq&amp;gt;"&lt;/span&gt; +
                                   &lt;span class="str"&gt;"&amp;lt;/Where&amp;gt;"&lt;/span&gt;;
                    query.ViewFields = &lt;span class="str"&gt;"&amp;lt;FieldRef Name='ID'/&amp;gt;"&lt;/span&gt; +
                                        &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Title'/&amp;gt;"&lt;/span&gt;;

                    SPList badgeList = web.Lists[&lt;span class="str"&gt;"Badges"&lt;/span&gt;];
                    SPListItemCollection items = badgeList.GetItems(query);


                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != items)
                    {
                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (SPListItem item &lt;span class="kwrd"&gt;in&lt;/span&gt; items)
                        {
                            badges.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Badge
                            {
                                ID = item.ID,
                                Title = item.Title
                            });
                        }
                    }

                }
            });
            &lt;span class="kwrd"&gt;return&lt;/span&gt; badges;
        }
&lt;/pre&gt;
&lt;p&gt;The last method bears a little more explanation.&amp;nbsp; Now we want to get the badges for a particular user.&amp;nbsp; The user may not have access to the site, so we have to use RunWithElevatedPrivileges.&amp;nbsp; In fact, the user may not even be in the site users list, so we have to use EnsureUser in order to obtain a valid reference to the SPUser object for that user.&amp;nbsp;&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 1: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 2: &lt;/span&gt;        &lt;span class="rem"&gt;/// Gets the badges for a particular user&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 3: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 4: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="loginName"&amp;gt;The login name in encoded claims&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 5: &lt;/span&gt;        &lt;span class="rem"&gt;/// format. For instance, "i:0#.w|contoso\administrator".&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 6: &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The user information and badges for that user.&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 7: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; BadgeUser GetBadgesForUser(&lt;span class="kwrd"&gt;string&lt;/span&gt; loginName)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 8: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 9: &lt;/span&gt;            BadgeUser badgeUser = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 10: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 11: &lt;/span&gt;            &lt;span class="rem"&gt;//Use RWEP here because the user may not have &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 12: &lt;/span&gt;            &lt;span class="rem"&gt;//access to the site.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 13: &lt;/span&gt;            SPSecurity.RunWithElevatedPrivileges(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 14: &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 15: &lt;/span&gt;                &lt;span class="kwrd"&gt;using&lt;/span&gt; (SPSite site = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPSite(&lt;span class="str"&gt;"http://intranet.contoso.local"&lt;/span&gt;))&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 16: &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 17: &lt;/span&gt;                    SPWeb web = site.OpenWeb(&lt;span class="str"&gt;"Community"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 18: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 19: &lt;/span&gt;                    &lt;span class="rem"&gt;//The encoded claim will be in the format&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 20: &lt;/span&gt;                    &lt;span class="rem"&gt;//0#.f|ldapmember|kirkevans. Add the i: prefix&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 21: &lt;/span&gt;                    &lt;span class="rem"&gt;//to indicate this is an identity claim.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 22: &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!loginName.StartsWith(&lt;span class="str"&gt;"i:"&lt;/span&gt;))&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 23: &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 24: &lt;/span&gt;                        loginName = &lt;span class="str"&gt;"i:"&lt;/span&gt; + loginName;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 25: &lt;/span&gt;                    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 26: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 27: &lt;/span&gt;                    &lt;span class="rem"&gt;//EnsureUser will only work if the same login provider&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 28: &lt;/span&gt;                    &lt;span class="rem"&gt;//is available in this site. For example, if you are&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 29: &lt;/span&gt;                    &lt;span class="rem"&gt;//calling this from a user authenticated in another web &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 30: &lt;/span&gt;                    &lt;span class="rem"&gt;//application, and this site does not have FBA configured,&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 31: &lt;/span&gt;                    &lt;span class="rem"&gt;//the call to EnsureUser will fail.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 32: &lt;/span&gt;                    SPUser user = user = web.EnsureUser(loginName);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 33: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 34: &lt;/span&gt;                    SPQuery query = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPQuery();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 35: &lt;/span&gt;                    query.Query = &lt;span class="str"&gt;"&amp;lt;Where&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 36: &lt;/span&gt;                                    &lt;span class="str"&gt;"&amp;lt;And&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 37: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;Eq&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 38: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Member' LookupId='TRUE' /&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 39: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;Value Type='USER' &amp;gt;"&lt;/span&gt; + user.ID + &lt;span class="str"&gt;"&amp;lt;/Value&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 40: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;/Eq&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 41: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;IsNotNull&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 42: &lt;/span&gt;                                           &lt;span class="str"&gt;"&amp;lt;FieldRef Name='GiftedBadgeLookup'/&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 43: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;/IsNotNull&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 44: &lt;/span&gt;                                    &lt;span class="str"&gt;"&amp;lt;/And&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 45: &lt;/span&gt;                                  &lt;span class="str"&gt;"&amp;lt;/Where&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 46: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 47: &lt;/span&gt;                    query.ViewFields = &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Title'/&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 48: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;FieldRef Name='Member'/&amp;gt;"&lt;/span&gt; +&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 49: &lt;/span&gt;                                        &lt;span class="str"&gt;"&amp;lt;FieldRef Name='GiftedBadgeLookup'/&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 50: &lt;/span&gt;                    SPList memberList = web.Lists[&lt;span class="str"&gt;"Community Members"&lt;/span&gt;];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 51: &lt;/span&gt;                    SPListItemCollection items = memberList.GetItems(query);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 52: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 53: &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (items.Count &amp;gt; 0)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 54: &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 55: &lt;/span&gt;                        badgeUser = &lt;span class="kwrd"&gt;new&lt;/span&gt; BadgeUser&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 56: &lt;/span&gt;                        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 57: &lt;/span&gt;                            LoginName = user.LoginName,&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 58: &lt;/span&gt;                            Name = items[0].Title&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 59: &lt;/span&gt;                        };&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 60: &lt;/span&gt;                        List&amp;lt;Badge&amp;gt; badges = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Badge&amp;gt;();&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 61: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 62: &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (SPListItem item &lt;span class="kwrd"&gt;in&lt;/span&gt; items)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 63: &lt;/span&gt;                        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 64: &lt;/span&gt;                            SPFieldLookupValue badgeName =&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 65: &lt;/span&gt;                                &lt;span class="kwrd"&gt;new&lt;/span&gt; SPFieldLookupValue(item[&lt;span class="str"&gt;"GiftedBadgeLookup"&lt;/span&gt;].ToString());&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 66: &lt;/span&gt;                            &lt;span class="rem"&gt;//The current data structure only allows&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 67: &lt;/span&gt;                            &lt;span class="rem"&gt;//one badge, but we may want to add badges&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 68: &lt;/span&gt;                            &lt;span class="rem"&gt;//from another system in the future.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 69: &lt;/span&gt;                            badges.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Badge&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 70: &lt;/span&gt;                            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 71: &lt;/span&gt;                                ID = badgeName.LookupId,&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 72: &lt;/span&gt;                                Title = badgeName.LookupValue&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 73: &lt;/span&gt;                            });&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 74: &lt;/span&gt;                        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 75: &lt;/span&gt;                        badgeUser.Badges = badges;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 76: &lt;/span&gt;                    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 77: &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 78: &lt;/span&gt;            });&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 79: &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; badgeUser;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 80: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 81: &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 82: &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The call to &lt;strong&gt;EnsureUser&lt;/strong&gt; requires that the provider used to authenticate the user is available to this web application.&amp;nbsp; If we are in one web application that uses FBA claims and then we make a call to another web site (in this case &lt;a href="http://intranet.contoso.local/"&gt;http://intranet.contoso.local&lt;/a&gt;), then both web applications must provide the same authentication capabilities.&amp;nbsp; If one web application uses FBA, the site you are calling &lt;strong&gt;EnsureUser&lt;/strong&gt; for must also be configured to use the same FBA provider.&lt;/p&gt;
&lt;h2&gt;Implementing the Badge Claim Provider&lt;/h2&gt;
&lt;p&gt;Now that we have the data access stuff out of the way, let&amp;rsquo;s focus on the really cool part of the solution.&amp;nbsp; We&amp;rsquo;ll start by implementing the properties as shown in the previous class diagram.&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 1: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 2: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 3: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.SharePoint.Administration;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 4: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.SharePoint.Administration.Claims;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 5: &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.SharePoint.WebControls;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 6: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 7: &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Microsoft.PFE.ClaimsProviders&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 8: &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 9: &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BadgeClaimProvider : SPClaimProvider&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 10: &lt;/span&gt;    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 11: &lt;/span&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Constructor&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 12: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; BadgeClaimProvider(&lt;span class="kwrd"&gt;string&lt;/span&gt; displayName)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 13: &lt;/span&gt;            : &lt;span class="kwrd"&gt;base&lt;/span&gt;(displayName)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 14: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 15: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 16: &lt;/span&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 17: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 18: &lt;/span&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Properties&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 19: &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProviderInternalName&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 20: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 21: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"BadgeClaimsProvider"&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 22: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 23: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 24: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 25: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 26: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; ProviderInternalName; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 27: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 28: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 29: &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProviderDisplayName&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 30: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 31: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Badges for User"&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 32: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 33: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 34: &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; BadgeClaimType&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 35: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 36: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"http://Microsoft.PFE.Claims/Badges"&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 37: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 38: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 39: &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; BadgeClaimValueType&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 40: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 41: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; Microsoft.IdentityModel.Claims.ClaimValueTypes.String; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 42: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 43: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 44: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; SupportsEntityInformation&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 45: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 46: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 47: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 48: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 49: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; SupportsHierarchy&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 50: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 51: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 52: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 53: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 54: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; SupportsResolve&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 55: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 56: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 57: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 58: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 59: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; SupportsSearch&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 60: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 61: &lt;/span&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 62: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 63: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 64: &lt;/span&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The ProviderDisplayName property on line 29 can be seen in the DisplayName property when we use the Get-SPClaimProvider cmdlet.&amp;nbsp; The BadgeClaimType (line 34) defines the URI for the claim, and the BadgeClaimValueType (line 39) defines the type of value the claim will contain.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The four properties starting with &amp;ldquo;Support&amp;rdquo; indicate to SharePoint what capabilities this provider has.&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EntityInformation &amp;ndash; provides claims augmentation for a specific user.&lt;/li&gt;
&lt;li&gt;Hierarchy &amp;ndash; used in the People Picker to create a hierarchical representation of claims.&lt;/li&gt;
&lt;li&gt;Resolve &amp;ndash; Find an exact match for the claim value.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Search &amp;ndash; Search for a value based on a partial word or search pattern.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our provider will support entity information, search, and resolve.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Claims Augmentation - Providing Entity Information&lt;/h3&gt;
&lt;p&gt;We need to add a claim to the user&amp;rsquo;s token that shows a badge that they might have earned.&amp;nbsp; To do that, we first tell SharePoint that we are going to fill a claim with a specific type (&amp;ldquo;http://Microsoft.PFE.Claims/Badges&amp;rdquo;) and what type its value will be (Microsoft.IdentityModel.Claims.ClaimValueTypes.String).&amp;nbsp; We then use the FillClaimsForEntity method to augment the claims for the current user.&amp;nbsp; This method accepts a parameter, &amp;ldquo;entity&amp;rdquo;, the value of which is the user&amp;rsquo;s identity claim (for instance, &amp;ldquo;0#.f|ldapmember|kirkevans&amp;rdquo;).&amp;nbsp; We then pass that value to our helper method GetBadgesForUser.&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 1: &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillClaimTypes(List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; claimTypes)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 2: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 3: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (claimTypes == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 4: &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"claimTypes"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 5: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 6: &lt;/span&gt;            &lt;span class="rem"&gt;// Add our claim type.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 7: &lt;/span&gt;            claimTypes.Add(BadgeClaimType);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 8: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 9: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 10: &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillClaimValueTypes(List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; claimValueTypes)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 11: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 12: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (claimValueTypes == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 13: &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"claimValueTypes"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 14: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 15: &lt;/span&gt;            &lt;span class="rem"&gt;// Add our claim value type.&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 16: &lt;/span&gt;            claimValueTypes.Add(BadgeClaimValueType);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 17: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 18: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 19: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 20: &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillClaimsForEntity(Uri context, SPClaim entity, List&amp;lt;SPClaim&amp;gt; claims)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 21: &lt;/span&gt;        {            &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 22: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (entity == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 23: &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"entity"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 24: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 25: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (claims == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 26: &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"claims"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 27: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 28: &lt;/span&gt;                        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 29: &lt;/span&gt;            var badgeUser = BadgeHelper.GetBadgesForUser(entity.Value);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 30: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 31: &lt;/span&gt;            &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 32: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != badgeUser)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 33: &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 34: &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != badgeUser.Badges)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 35: &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 36: &lt;/span&gt;                    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var badge &lt;span class="kwrd"&gt;in&lt;/span&gt; badgeUser.Badges)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 37: &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 38: &lt;/span&gt;                        claims.Add(CreateClaim(BadgeClaimType, badge.Title, BadgeClaimValueType));&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 39: &lt;/span&gt;                    }   &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 40: &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 41: &lt;/span&gt;            }                     &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 42: &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 43: &lt;/span&gt;        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 44: &lt;/span&gt;        &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 45: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 46: &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillEntityTypes(List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; entityTypes)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 47: &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 48: &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; == entityTypes)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 49: &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 50: &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"entityTypes"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 51: &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 52: &lt;/span&gt;            entityTypes.Add(SPClaimEntityTypes.FormsRole);            &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt; 53: &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Enabling the People Picker&lt;/h3&gt;
&lt;p&gt;So far, all we have done is add a claim to the user&amp;rsquo;s token.&amp;nbsp; We want to enable the scenario where someone can create a site, select Users and Groups, and use the People Picker to select our badge, allowing any users with that badge access to the site.&amp;nbsp; To do this, we need to implement a few more methods: FillSchema, FillSearch and FillResolve.&amp;nbsp; FillSchema tells the PeoplePicker what information we will display and in what format.&amp;nbsp; FillSearch accepts a string value that we use to find any badges that start with those characters.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillSchema(SPProviderSchema schema)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; == schema)
            {
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"schema"&lt;/span&gt;);
            }

            schema.AddSchemaElement(&lt;span class="kwrd"&gt;new&lt;/span&gt; SPSchemaElement(PeopleEditorEntityDataKeys.DisplayName,
                &lt;span class="str"&gt;"Display Name"&lt;/span&gt;, SPSchemaElementType.TableViewOnly));
        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillSearch(Uri context, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] entityTypes, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt; searchPattern, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt; hierarchyNodeID, 
            &lt;span class="kwrd"&gt;int&lt;/span&gt; maxCount, 
            SPProviderHierarchyTree searchTree)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!EntityTypesContain(entityTypes, SPClaimEntityTypes.FormsRole))
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt;;
            }

            List&amp;lt;Badge&amp;gt; badges = BadgeHelper.GetBadgesByPartialName(searchPattern);
            &lt;span class="kwrd"&gt;if&lt;/span&gt;(&lt;span class="kwrd"&gt;null&lt;/span&gt; != badges)
            {
                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var badge &lt;span class="kwrd"&gt;in&lt;/span&gt; badges)
                {
                    PickerEntity entity = CreatePickerEntity();
                    entity.Claim = CreateClaim(BadgeClaimType, badge.Title, BadgeClaimValueType);
                    entity.Description = badge.Title;
                    entity.DisplayText = badge.Title;
                    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] = badge.Title;
                    entity.EntityType = SPClaimEntityTypes.FormsRole;
                    entity.IsResolved = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
                    searchTree.AddEntity(entity);
                }
            }
        }&lt;/pre&gt;
&lt;p&gt;Another way you can use the People Picker is to type a value in.&amp;nbsp; When you type the value instead of using search, this calls the FillResolve method of the registered claims providers.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillResolve(Uri context, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] entityTypes, 
            SPClaim resolveInput, 
            List&amp;lt;PickerEntity&amp;gt; resolved)
        {
            FillResolve(context, entityTypes, resolveInput.Value, resolved);
        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillResolve(Uri context, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] entityTypes, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt; resolveInput, 
            List&amp;lt;PickerEntity&amp;gt; resolved)
        {
            List&amp;lt;Badge&amp;gt; badges = BadgeHelper.GetBadgesByExactName(resolveInput);
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt; != badges)
            {
                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var badge &lt;span class="kwrd"&gt;in&lt;/span&gt; badges)
                {
                    PickerEntity entity = CreatePickerEntity();
                    entity.Claim = CreateClaim(BadgeClaimType, badge.Title, BadgeClaimValueType);
                    entity.Description = badge.Title;
                    entity.DisplayText = badge.Title;
                    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] = badge.Title;
                    entity.EntityType = SPClaimEntityTypes.FormsRole;
                    entity.IsResolved = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
                    resolved.Add(entity);
                }
            }
        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FillHierarchy(Uri context, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] entityTypes, 
            &lt;span class="kwrd"&gt;string&lt;/span&gt; hierarchyNodeID, 
            &lt;span class="kwrd"&gt;int&lt;/span&gt; numberOfLevels, 
            SPProviderHierarchyTree hierarchy)
        {
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
        }
    }
}
&lt;/pre&gt;
&lt;h3&gt;Registering Your Custom Claim Provider&lt;/h3&gt;
&lt;p&gt;In Visual Studio 2012, add a new farm-scoped feature and a feature receiver.&amp;nbsp; Change the type of the feature receiver to SPClaimProviderFeatureReceiver.&amp;nbsp; You only need to override a few properties here, no need to override FeatureActivating or FeatureDeactivating.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.SharePoint.Administration.Claims;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Microsoft.PFE.ClaimsProviders.Features.BadgeClaimFeature
{
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;remarks&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// The GUID attached to this class may be used during packaging and should not be modified.&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/remarks&amp;gt;&lt;/span&gt;

    [Guid(&lt;span class="str"&gt;"99871a2c-f81a-443c-9625-d2465d2ec29c"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BadgeClaimFeatureEventReceiver : SPClaimProviderFeatureReceiver
    {


        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClaimProviderAssembly
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BadgeClaimProvider).Assembly.FullName; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClaimProviderDescription
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"A sample provider written by Kirk Evans"&lt;/span&gt;; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClaimProviderDisplayName
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; BadgeClaimProvider.ProviderDisplayName; }
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClaimProviderType
        {
            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BadgeClaimProvider).FullName; }
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;Right-click the project and choose Publish.&amp;nbsp; This will package the solution into a WSP.&amp;nbsp; Once packaged into a WSP, you can add the solution and deploy it using PowerShell.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;Add-SPSolution -LiteralPath C:\temp\claims\Microsoft.PFE.ClaimsProviders.wsp
Install-SPSolution microsoft.pfe.claimsproviders.wsp  -GACDeployment&lt;/pre&gt;
&lt;h2&gt;Securing Content Based on a Badge&lt;/h2&gt;
&lt;p&gt;Now let&amp;rsquo;s put our new claim provider through its paces. I create a new site titled &amp;ldquo;MCM Only&amp;rdquo; with unique permissions.&amp;nbsp; I then determine who to add to the group &amp;ldquo;MCM Only Members&amp;rdquo;.&amp;nbsp; When I search for &amp;ldquo;Microsoft&amp;rdquo; I see a list of the badges that start with the search term (this called our FillSearch method).&amp;nbsp; When we hover over a result, a popup shows which claim provider the information came from.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7115.image_5F00_7D094CFB.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8508.image_5F00_thumb_5F00_7511AA99.png" alt="image" width="244" height="137" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s try our FillResolve method by typing the value in.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2728.image_5F00_0996FA18.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4478.image_5F00_thumb_5F00_092AC723.png" alt="image" width="244" height="155" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When we hover over the underlined value, we choose the value that matches.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0675.image_5F00_13E81E78.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7115.image_5F00_thumb_5F00_47B014C9.png" alt="image" width="244" height="135" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once we choose a value, only users that have that claim will be granted access.&amp;nbsp; For those users that have access to the site because they match a claim, they will be granted access.&amp;nbsp; Notice that it shows in the top nav bar for a user who has the badge.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1258.image_5F00_6B693C63.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8203.image_5F00_thumb_5F00_0AABE337.png" alt="image" width="244" height="151" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I try to access the site, it succeeds.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3718.image_5F00_382D02FA.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4863.image_5F00_thumb_5F00_17A5C348.png" alt="image" width="244" height="119" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Further, SharePoint is smart enough to security trim away the site that a user doesn&amp;rsquo;t have access to based on our claim provider!&amp;nbsp; Now I am logged in as Dan Jump, who does not have a badge.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7607.image_5F00_694C3D9A.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4466.image_5F00_thumb_5F00_5DB6805B.png" alt="image" width="244" height="125" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And when I try to access the site by typing it in the URL, it fails just as we would expect.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5047.image_5F00_5D4A4D66.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5543.image_5F00_thumb_5F00_5C71E77C.png" alt="image" width="244" height="102" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Custom claim providers address a large number of scenarios that people commonly face with SharePoint, enabling the ability to add additional information into the user&amp;rsquo;s token and then using that information to secure content or assign work to users via the people picker.&amp;nbsp; There are quite a few interesting ideas on using custom claim providers.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/b/entdev/archive/2012/02/28/profile-claims.aspx"&gt;Securing SharePoint Content using Profile Attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a title="http://blogs.msdn.com/b/entdev/archive/2012/02/28/leveraging-facebook-for-sharepoint-security.aspx" href="http://blogs.msdn.com/b/entdev/archive/2012/02/28/leveraging-facebook-for-sharepoint-security.aspx"&gt;Leveraging Facebook for SharePoint Security&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/gg615945(v=office.14).aspx"&gt;Creating a Claims Provider Based on SharePoint Audiences&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ff699494(v=office.14).aspx"&gt;Creating a Hierarchical Claim Provider Based on Favorite Basketball Teams&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As I survey many of the implementations that have been done for various customers using a mix of HttpModules and code in master pages to provide less than elegant solutions to similar problems, I can see more and more scenarios that could be solved using custom claim providers.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10412789" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-41-27-89/Microsoft.PFE.ClaimsProviders.zip" length="180780" type="application/zip" /><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/-NET+Programming/">.NET Programming</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Interoperability/">Interoperability</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Enterprise+Social+Computing/">Enterprise Social Computing</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2012/">Visual Studio 2012</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Active+Directory/">Active Directory</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Claims/">Claims</category></item><item><title>How I Became a SharePoint 2010 MCM</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/04/17/how-i-became-a-sharepoint-2010-mcm.aspx</link><pubDate>Wed, 17 Apr 2013 15:54:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10411921</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10411921</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/04/17/how-i-became-a-sharepoint-2010-mcm.aspx#comments</comments><description>&lt;p&gt;I recently attained the Microsoft Certified Master for SharePoint 2010 certification.&amp;#160; I have long wanted to write about the experience, but honestly didn’t know how to begin.&amp;#160; After quite a few conversations with friends and colleagues, I thought I would share some insight about the process.&amp;#160; I am not writing this to dissuade you from pursuing MCSM… in fact, quite the opposite.&amp;#160; I think many more SharePoint professionals need to attend the program to receive the most amazing training that they will ever receive anywhere.&amp;#160; That said, you should also understand what it takes to achieve certification and what the rest of the Masters went through.&amp;#160; They didn’t just attend a training course and then get a certificate of completion, this is a true measure of your mastery of the technology.&lt;/p&gt;  &lt;h2&gt;IT WAS A LOT OF WORK&lt;/h2&gt;  &lt;p&gt;Mrs. Robertson, my high school English teacher, would scream at me for putting that heading in all caps, but I mean every single word of it: IT WAS A LOT OF WORK.&amp;#160; The MCM certification is just that, a certification.&amp;#160; You might be familiar with the Microsoft Most Valuable Professional (MVP) award which is given to recognize technical leaders who contribute to the community in a meaningful way.&amp;#160; I was lucky enough to be an MVP at one time and cannot speak highly enough about the hard work and dedication for these people.&amp;#160; Where MVP is an award that recognizes technical leadership within the community, MCM is a certification process that requires multiple tests.&amp;#160; The program requires that you pass 4 certification exams (two for IT Pro, and 2 for Developer) before you even qualify for an interview to determine if you are accepted into the MCM training program.&amp;#160; Once you complete the training program, you have to pass the mother of all written tests, by far the hardest written test I’ve ever taken (worse than my Calculus 3 final exam in college by far).&amp;#160; Finally, you sit for a qualification lab test that took every minute of 8.5 hours to complete, a test that I joke most consultants would bill at least a month of time to complete the same amount of work.&amp;#160; It was grueling, and worth every minute.&amp;#160; It was one of the most difficult and yet satisfying achievements of my career.&lt;/p&gt;  &lt;h2&gt;The Interview&lt;/h2&gt;  &lt;p&gt;My interview was with two people, both MCMs, and they grilled me on technical aspects of the product that I had never considered, let alone had any real world experience with.&amp;#160; I honestly don’t know of too many people who would have enough technical experience to approach that interview with confidence, let alone have much confidence left after the interview.&amp;#160; They asked me about some of the roughest edges in the product, how to solve problems on a global scale as well as how to solve very specific smaller complex problems.&amp;#160; I thought I knew a lot about the product, but I was seriously questioning my abilities once I got off the phone.&amp;#160; Somehow, I passed, and they gave me feedback on areas that I needed to focus on in order to be successful with the program going forward.&amp;#160; For me, unfortunately, the things that I needed to focus on were precisely the things that were emphasized and central components of the training program.&lt;/p&gt;  &lt;h2&gt;The Training&lt;/h2&gt;  &lt;p&gt;There are two formats for the technical training portion of the program: a three week immersive training course where you are on site the entire time, and a one week on site plus 10 week remote training course.&amp;#160; After talking with colleagues who had gone through the experience, they thoroughly recommended the three week course as the better option.&amp;#160; For me, I found that the three weeks on site provided me the best opportunity to succeed as I was able to work side by side with friends until the wee hours of the morning in the lab away from the distractions of work and family.&amp;#160; Yes, I said the &lt;em&gt;distractions of family&lt;/em&gt;, as much as it pains me to say that this program requires that you set aside all personal responsibilities to focus.&amp;#160; I didn’t feel that I would be disciplined enough to attend the training virtually.&lt;/p&gt;  &lt;p&gt;The material in the program covers a broad set of topics.&amp;#160; For instance, simply saying we covered “ECM” means that we covered document sets, holds, metadata navigation, document ID, retention policies, IRM, workflows, content organizer, and a bunch of other topics.&amp;#160; For each topic, we examined the timer jobs required, the interaction of processes (holds leverage search), the limitations of various capabilities, common issues that people have with various functions, and the recommended approach for applying it.&amp;#160; We covered things like the content migration API, discussing what information is retained and what is lost, and the implications of using this in various scenarios such as content deployment.&amp;#160; &lt;/p&gt;  &lt;p&gt;Monday through Friday for three weeks we arrived in the lab around 7:00 am, took a few very short breaks and an hour for lunch, and were &lt;strong&gt;bombarded&lt;/strong&gt; with incredibly deep technical training until around 6:00 pm, sometimes later.&amp;#160; The material is all 400 level, you are not introduced to things like search or user profiles, but rather it is assumed you already know how this stuff already works.&amp;#160; They teach you the deep inner workings of how things work, like a fantastic deep dive on user profiles by Spence Harbar or another incredibly deep dive on search by Neil Hodgkinson.&amp;#160; This training is an invaluable part of the program where you hear some of the most common issues and things that cause the most support cases for the product team.&amp;#160; You learn from people who know this stuff more than anyone else.&lt;/p&gt;  &lt;p&gt;For each of the modules below, we went into detail about what service applications are used, the required permissions, the implication of topology choices, services required and where they should run, how to manage them and how to troubleshoot them.&amp;#160; Below is a summary of various topics covered, I am asked quite often what kind of information is covered in the course.&amp;#160; This is not an exhaustive list, I am probably missing a few and some of these are way deeper than I suggest in this list.&amp;#160; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;ECM&lt;/strong&gt; – everything mentioned above plus WCM.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Governance&lt;/strong&gt; – creating a governance plan.&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Planning and Information Architecture&lt;/strong&gt; – planning topologies and how you might segment information based on requirements.&amp;#160; Did you know that TechNet has a bunch of information on planning?&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Multi Tenancy&lt;/strong&gt; – how to configure multi-tenancy, why you shouldn’t do this for an on-premise farm, and design considerations.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Service Applications&lt;/strong&gt; – how they work, core components, how to create your own service application.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;User Profile&lt;/strong&gt; – My Sites, social, architecture, provisioning, synchronization, troubleshooting, dependencies, interactions with managed metadata and search, enterprise considerations.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Identity&lt;/strong&gt; – Kerberos, FBA, constrained delegation, claims.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Search&lt;/strong&gt; – Everything from how to provision the search topology, what services are running where, what service accounts are used and what can be federated or delegated, how the crawler works, how search stores information and where, and what happens when you query.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Search Customization&lt;/strong&gt; – custom search pages, result refiners, extending search web parts, best bets, scopes, XSLT for core results, BDC results, people results, crawl extensibility.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Business Continuity Management&lt;/strong&gt; – recycle bin, list export and import, site backup and restore, farm backup and restore, mirroring, log shipping, SQL Server Always On.&amp;#160; How SQL backups work and what mirroring and log shipping are really doing, what databases can use log shipping and why.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Upgrades&lt;/strong&gt; – how to upgrade, best practices, things to watch out for, how to handle customizations and site definitions, how to troubleshoot.&amp;#160; How to patch, best practices for patching.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Capacity Planning&lt;/strong&gt; – how to determine the requirements for your farm and how to test your farm to determine if it can handle the load.&amp;#160; How to monitor the farm once deployed, and how to address constraints.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Developer&lt;/strong&gt; – workflows, data access technologies, schema-based deployment (declarative vs. imperative deployment), web templates, LINQ, REST, application lifecycle management, feature upgrades, management and monitoring custom solutions.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Workflow&lt;/strong&gt; – Developing, configuration, troubleshooting, performance tuning&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Business Connectivity Services&lt;/strong&gt; – capabilities, APIs, PowerShell, security, search, augmenting user profiles, custom connectors, throttles and limits, performance tuning.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pretty daunting list?&amp;#160; Admittedly, there are going to be topics you are strong at and topics you are not as strong at.&amp;#160; Prior to attending the training, you should spend quite a bit of time with the &lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US&amp;amp;EventID=1032509426&amp;amp;CountryCode=US"&gt;pre-reading materials&lt;/a&gt;.&amp;#160; We joked that it is basically, “read all of TechNet and all of Steve Peschka’s and Spence Harbar’s blog.”&amp;#160; From the list above, that’s not far from the truth.&amp;#160; The one thing that I didn’t write but is common to all of the modules: &lt;strong&gt;PowerShell&lt;/strong&gt;.&amp;#160; You need to know PowerShell, and if you aren’t comfortable with it before training, you sure the heck will be afterwards.&lt;/p&gt;  &lt;p&gt;Keep in mind that this was what we covered for SharePoint 2010 MCM, the list of materials has changed since then.&amp;#160; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032545330&amp;amp;culture=en-us"&gt;Latest Program Overview Webcast&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-03-53-16-38/MCSM-SharePoint-Overview.xps"&gt;Current Course Topics List&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/learning/en/us/mcsm-sharepoint-certification.aspx"&gt;Program Home Page&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I was a good student in college, I achieved Dean’s List for the last 2 years of college and generally was able to get by with taking notes, memorizing for tests, and then forgetting most of what I learned after finals.&amp;#160; This simply won’t work for this program: you must bring a broad set of experiences with you or the training will be over your head.&amp;#160; This is a test of experience and stamina.&amp;#160; Being attentive for 9-10 hours per day to deep technical content is exhausting and you get to the point where you start trying to figure out “do I really need to listen here or can I zone out for a minute, can this possibly be on the test?”&amp;#160; The answer is yes: this is probably on the test.&amp;#160; The information presented in class covers topics that you are expected to already know, just with more detail than you might already know.&amp;#160; For instance, you might already know a thing or two about ECM, but do you know all the services required to make everything work as expected?&amp;#160; The more familiar you are with search, user profiles, identity and authentication and claims, and service application federation before you attend the class, the more you will get out of the class.&amp;#160; If you are hearing a topic for the first time (admittedly, much of it was brand new to me), then you are going to struggle. The MCM certification is just as much a test of what you learned in class as it is your own experience, and it’s really difficult to master a concept you just learned about.&lt;/p&gt;  &lt;h2&gt;The Hands on Labs&lt;/h2&gt;  &lt;p&gt;You are given an environment to practice hands on labs to bolster the training that you receive during the day.&amp;#160; The training lectures runs Monday through Friday from around 8:00 am to 6:00 pm, so you spend as much time nights and weekends working on the labs as you can.&amp;#160; There are some labs that are relatively short, only taking a few hours to complete, while others may never be completed.&amp;#160; We were often in the lab until midnight or 1am working on problems, surviving on little sleep while knowing we needed to be alert during the training lectures.&amp;#160; Weekends were consumed with these labs as well as studying for the written test.&amp;#160; You have to balance your time practicing the things you think you know with the things you are not as strong with.&amp;#160; &lt;/p&gt;  &lt;p&gt;These labs are not detailed walkthroughs, they are often just a description of a task that you need to accomplish that may seem deceptively easy yet take days to complete.&amp;#160; At first, I was frustrated at the lack of direction in the labs and how open-ended they were, but I came to love this about the training course.&amp;#160; Rather than show you one way to accomplish a task, you are forced to learn how to do the task on your own and understand various aspects of it.&amp;#160; The second-to-last sentence in the lab was usually “verify that a document shows up” or “verify that the search result shows this”.&amp;#160; The last sentence was usually a question like “what else could you do with this” or “how else could you accomplish this?”&amp;#160; &lt;/p&gt;  &lt;p&gt;Here are the HOL topics that were covered.&amp;#160; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Logical architecture and governance&lt;/li&gt;    &lt;li&gt;Topology &lt;/li&gt;    &lt;li&gt;ECM&lt;/li&gt;    &lt;li&gt;WCM&lt;/li&gt;    &lt;li&gt;Content migration&lt;/li&gt;    &lt;li&gt;Basic upgrades&lt;/li&gt;    &lt;li&gt;Complex upgrades&lt;/li&gt;    &lt;li&gt;Patching&lt;/li&gt;    &lt;li&gt;Business Continuity Management&lt;/li&gt;    &lt;li&gt;Capacity Planning and Performance&lt;/li&gt;    &lt;li&gt;Custom service applications&lt;/li&gt;    &lt;li&gt;Visual Studio workflows&lt;/li&gt;    &lt;li&gt;Authentication&lt;/li&gt;    &lt;li&gt;Platform security&lt;/li&gt;    &lt;li&gt;Schema based development&lt;/li&gt;    &lt;li&gt;Search topology&lt;/li&gt;    &lt;li&gt;Search customization&lt;/li&gt;    &lt;li&gt;Business Connectivity Services&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;My favorite lab was the Topology lab.&amp;#160; You are handed this lab on the first day, and wow is it trial by fire.&amp;#160; Given a set of servers, provision various services with a desired topology.&amp;#160; This lab took me almost two weeks to complete because I was stuck on one problem and couldn’t solve it. Time management is a huge part of this course, spending 2 weeks on that one lab was, in hindsight, stupid because I should have spent more time on the other labs making sure I was prepared for the qualification lab.&amp;#160; However, I now have a very firm grasp on user profiles and will never forget that the user profile service must be started before provisioning tenants!&amp;#160; You need to work through the hands on labs in order to prepare yourself to pass the written test or the qual lab, it is vital that you work through as much of the labs as possible.&amp;#160; Time management is key.&lt;/p&gt;  &lt;p&gt;I rarely ate dinner out, opting to have food delivered just so that I could get more time in the lab.&amp;#160; On weekends, I would try to start a load of laundry while studying notes and then I’d go back to the lab so that I could work with peers, asking for help on some of the more difficult assignments.&amp;#160; It is a delicate balance of sleep deprivation and will power.&amp;#160; I attended during fall, during college football season, and I just wanted to go to a bar and watch an NFL game or the Georgia Bulldogs play but instead I buried my face in the glow of the computer monitor to keep practicing, keep studying.&amp;#160; Those who know how much I love football know this took tremendous willpower.&lt;/p&gt;  &lt;h2&gt;The Commitment&lt;/h2&gt;  &lt;p&gt;To put in the work required means you really have to put aside all other commitments.&amp;#160; You aren’t going to be effective if you are having to excuse yourself for a conference call when the instructor is going over material that you really need to hear.&amp;#160; You really need to make sure that you can excuse yourself from work during the course duration.&amp;#160; The hard part means that you need to stay off email, Facebook, and everything else.&amp;#160; I was lucky to have a very supportive group of friends at work who covered for me while I was gone, sent reassuring emails telling me that everything was going great and to keep working hard, and chastised me to get the heck off Facebook and Twitter.&amp;#160; I can’t thank you guys enough Chad and Eric.&lt;/p&gt;  &lt;p&gt;I have a loving wife and two young children.&amp;#160; Every day with them is precious to me, and I fight to create work and life balance, although that often means that I am working from home and they know to find me in my home office.&amp;#160; I travel frequently, but usually only for a few days at a time.&amp;#160; For the MCM program, I got an apartment near campus and lived there for 3 weeks by myself.&amp;#160; There was a 2-hour time difference that meant when I woke up at 6:00 am (recall the sleep deprivation that I emphasized before), my kids were already at school.&amp;#160; When I was eating lunch, they weren’t yet home from school, and when training was done at night they were already in bed.&amp;#160; I missed my kids so much it hurt.&amp;#160; By the end of the second week, I damned near had a breakdown when I checked my voicemail and a tearful daughter said “I miss you daddy.”&amp;#160; It gets really hard to focus on listening to technical training all day and then working all night in a lab when all you want to do is to hear your family say I love you.&amp;#160; My wife was fantastic, she wouldn’t tell me about any of the times the kids got in trouble, when the oven broke, about a tax audit letter we received, she just wanted me to focus.&amp;#160; We usually spend so much time talking to each other every night that this was something we both very much missed while I was away at the program, she didn’t have me to share her highs and lows every day and that really made an impact on her.&lt;/p&gt;  &lt;p&gt;On weekends, we tried to use Skype, and it was wonderful to see everyone’s faces and hear their voices… but it was only fleeting.&amp;#160; I have to admit that this was something I fully didn’t realize how much it would impact me.&amp;#160; I didn’t realize at all how much it would impact my family.&lt;/p&gt;  &lt;p&gt;The commitment isn’t just you, it’s your family as well.&amp;#160; &lt;/p&gt;  &lt;h2&gt;The Written Test&lt;/h2&gt;  &lt;p&gt;Once the three weeks of training have concluded, there is a written test.&amp;#160; This is not like any other Microsoft certification test that I have ever taken.&amp;#160; &lt;/p&gt;  &lt;p&gt;I have long questioned the value of Microsoft certification tests, there are so many stories of young kids passing tests or, worse, people passing tests who have never used the technology before.&amp;#160; A friend of mine decided to see how many certifications he could achieve within 2 months, most he had little or no experience with, and he achieved 6 of the 8 he attempted.&amp;#160; Simply put: this test is &lt;em&gt;nothing&lt;/em&gt; like that.&amp;#160; During the lectures, I would often listen to the lecture and try to think of what questions could be asked on the test.&amp;#160; I made up my own set of questions that I thought could be fair game on the test.&amp;#160; Not even close.&lt;/p&gt;  &lt;p&gt;The questions were way harder, and often required you to put multiple complex concepts together to arrive at an answer.&amp;#160; There should be a camera outside the door as people leave the written test just to see their reactions, many F bombs are dropped by even the most experienced and attentive students.&amp;#160; You are under NDA, so you cannot talk about what’s on the test to each other or compare notes, you can only acknowledge each others’ frustrations.&amp;#160; You can’t even blow off steam by going to a bar and drinking too many beers because you are now looking forward to the next day where you take the qualification lab.&amp;#160; &lt;/p&gt;  &lt;p&gt;Many people do not pass the written test on the first try.&amp;#160; To me, this is the hardest one to retake because it requires that you study all of your notes and re-read TechNet and Peschka’s blog and Spence’s blog making sure you understand the finer points, realizing you aren’t getting the same test a second time.&amp;#160; One strategy is to do a brain dump of as many questions and topics that you saw and what you aren’t sure if you got right and make sure you study those concepts.&amp;#160; You really do not want to put off the retake for too long because it becomes increasingly hard to find the time to study like this.&lt;/p&gt;  &lt;p&gt;My strategy during the program was to focus my attention towards studying for the written test as much as I could because I knew that would be harder for me to attempt a second time.&amp;#160; I passed the written test on the first try, and I was admittedly shocked to see that I passed it.&amp;#160; &lt;/p&gt;  &lt;h2&gt;The Qualification Lab&lt;/h2&gt;  &lt;p&gt;You are given a lab environment and a set of tasks to complete in 8.5 hours.&amp;#160; The test was open-internet, so you could research whatever you needed to, but honestly if you were looking it up in the first place your chances of passing are very slim.&amp;#160; It’s nothing that an average SharePoint professional couldn’t reasonably achieve in a month’s time, but you are given just 8.5 hours and are graded on your ability to complete the tasks as described.&amp;#160; &lt;/p&gt;  &lt;p&gt;Let me emphasize here… a month’s worth of work in 8.5 hours, done accurately.&amp;#160; Either you know it or you don’t.&amp;#160; If you know it, you can do it quickly and accomplish it within the time limit, if you are unsure then you are going to waste a bunch of time trying to figure it out.&amp;#160; The clock is ticking.&lt;/p&gt;  &lt;p&gt;A boxed lunch was served, although I didn’t eat much of it because I didn’t want to lose any focus on completing the tasks.&amp;#160; It is stressful, because we all know how easy it is to forget a seemingly small step only to spend hours troubleshooting something.&amp;#160; Forget one timer job, and you can find yourself beating your head on the keyboard.&amp;#160; This is where it is vitally important to have paid attention in class as well as having experience.&lt;/p&gt;  &lt;p&gt;I failed the qualification lab.&amp;#160; Twice.&amp;#160; It was that hard, and from speaking with many others who have attempted the course, they agree that the combination of the written test and qualification lab are more than an accurate measure of the level of competency expected of an MCM.&amp;#160; It is stressful, realizing how many times you are trying to accomplish the task as written and fumbling on things you &lt;em&gt;know&lt;/em&gt; how to do, things you do every day for work.&amp;#160; I remember thinking during my first attempt at the test that I had a reasonable shot at passing… yeah, not even close.&amp;#160; The three weeks of lecture and demos, the late nights in the lab, the 16+ hour days on weekends, all that bolsters what you are expected to already know, it doesn’t teach to the test, and there’s only so much partial credit given for incomplete tasks.&amp;#160; Simply put, it was by far the hardest test I have ever taken because you had to be both thorough and fast.&amp;#160; &lt;/p&gt;  &lt;p&gt;The first time I took the test I honestly wasn’t prepared.&amp;#160; I did horrible, but that was my strategy the whole time was to focus on the written test and then plan to retake the qual lab.&amp;#160; The second time I took the qual lab, I failed by only a few points and it was completely time management that did me in.&amp;#160; I knew all the material, I just took too long to do some of the tasks and the clock ran away from me.&lt;/p&gt;  &lt;p&gt;I finally passed the qualification lab on my third and final attempt.&amp;#160; The first time you take the qualification lab, you are in a room with the proctor.&amp;#160; Your retakes can be done remotely while a proctor monitors you.&amp;#160; &lt;/p&gt;  &lt;h2&gt;The Aftermath&lt;/h2&gt;  &lt;p&gt;Maybe it took more for me to accomplish this certification than it would for you, maybe you have more experience than I did going in and you wouldn’t struggle as much.&amp;#160; Plenty of people pass the written and qual labs during rotation.&amp;#160; You should be prepared for what happens if you don’t and understand that if you didn’t pass the first time, you are really going to have to apply yourself to be able to pass the second time.&lt;/p&gt;  &lt;p&gt;Many people do not pass one or both of the tests on the first attempt.&amp;#160; Some of the MCMs that I look up to most (including some of the instructors) failed one or both parts on the first attempt.&amp;#160; Some of the SharePoint hardcore geeks that I look up to did not pass and decided not to even attempt a retake.&amp;#160; It’s hard to think about making such a huge time investment (pre-reading study, independent lab practice, three weeks of very long days of lectures and labs, two grueling tests) and then having to make yet another huge time investment afterward.&amp;#160; For some, they recognize that they don’t have it to give.&amp;#160; For me, I wasn’t about to give up.&amp;#160; &lt;/p&gt;  &lt;p&gt;After attending the program in person, you have 2 retake attempts before you have to repeat the entire program.&amp;#160; I know quite a few people who attempted it and decided not to pursue it after failing the first time, recognizing the amount of work that it would take to prepare for a retake.&amp;#160; &lt;/p&gt;  &lt;p&gt;Prior to attending, I spent quite a few long hours at my desk at work trying to understand search and user profiles.&amp;#160; I spent about a week (which is way too short) studying the pre-reading list.&amp;#160; After attending the training program, I studied nights and weekend for over a year.&amp;#160; I gained new experiences through working with the product day in and out with customers, bolstering my experience with the product.&amp;#160; I presented on some of the material at conferences, and made sure that I was able to cover the areas that I did poorly on.&amp;#160; I studied nights, weekends, holidays.&amp;#160; I was lucky that many of the customer issues I was handling for work were directly related to the material that I was studying and that gave me additional experience.&amp;#160; I felt like I lived, breathed, ate, slept, and dreamed of SharePoint.&amp;#160; I drove my family crazy by sitting in my office making up scenarios with the product and trying to solve them to make sure I knew how things worked instead of enjoying time with them outside.&amp;#160; On vacations I was distracted, I spent an absurd amount of time focusing on making sure that I was ready for my third and final attempt.&amp;#160; I rarely blogged, and when I did I tried to blog about the topics that I was studying.&amp;#160; Yes, I worked nights and weekends and busted my tail preparing for my 2nd qualification lab attempt.&amp;#160; For my 2nd attempt at the qualification lab, I thought I was ready… I barely failed, but it was still a failure.&amp;#160; That only strengthened my resolve that I was going to finish what I started.&lt;/p&gt;  &lt;p&gt;For the third qualification lab attempt, I worked nights and weekends and holidays and on vacation.&amp;#160; The problem was that it was getting tougher to focus.&amp;#160; I still had a day job, and I was now focusing less on SharePoint 2010 and more on SharePoint 2013.&amp;#160; I was traveling all over the world teaching developers about the new features in SharePoint 2013 for the Ignite program.&amp;#160; I was recording videos for MSDN, editing them, reviewing them, and re-recording them and doing much of that during nights and weekends.&amp;#160; That stuff helped me study through experience, but it threatened to reduce the amount of studying that I could do to prepare for the third attempt.&amp;#160; I finally had to put everything else on hold and focus for a few weeks solid to prepare.&amp;#160; Yes, I took vacation just to study for MCM.&lt;/p&gt;  &lt;p&gt;This is the part that many don’t plan on, the aftermath of the program.&amp;#160; If you don’t pass the first time, it takes a dedicated effort to make sure that you are ready for the next attempt.&amp;#160; It takes quite a bit of sacrifice.&amp;#160; It’s sometimes hard to explain to my non-technical friends that I sacrificed a significant amount of family time in order to pass a certification exam.&amp;#160; This program consumed my life for most of 18 months to the point that I questioned what possible benefit could I receive to justify all this hard work other than a title to add to my resume.&amp;#160; I thought several times about quitting, but I just couldn’t quit, that’s not who I am.&amp;#160; Instead I sacrificed quite a bit to accomplish a goal that I had set for myself.&lt;/p&gt;  &lt;p&gt;I failed the first and second attempt at the qualification lab, and finally passed on my third and final attempt.&amp;#160; Funny enough, I am glad I had the opportunity to take the lab three times as I was able to see a wide number of real-world scenarios that made me go back to my lab at home and work on them to completely understand them for the next test attempt.&amp;#160; Even if I didn’t understand them enough to pass the test the first time, I sure the heck understand them now!&amp;#160; The level of experience that I took away from just the qual labs and studying is invaluable.&lt;/p&gt;  &lt;h2&gt;The Reward&lt;/h2&gt;  &lt;p&gt;This was a personal goal, a way to prove to myself that I could take my skills to the next level.&amp;#160; Looking back on where I was before I started this program, I can say it was definitely worth my time to better myself as a SharePoint professional.&amp;#160; I learned so much throughout the program and made so many friends through the experience that professionally it was worth the investment.&amp;#160; I can now speak much more confidently about how the product works.&amp;#160; I now have a network of peers who went through the same certification process and passed, and I have this incredibly rich network of professionals to draw from.&amp;#160; I can sit in a room with the lead architect of a Fortune 50 company and provide factual guidance on how something should or should not be implemented.&amp;#160; I gained the respect of my peers because I showed so much dedication to finishing what I started.&amp;#160; &lt;/p&gt;  &lt;p&gt;For me, this was much more than trying to just get a promotion at work.&amp;#160; Actually, I haven’t yet realized any monetary rewards and I’m not sure that I will, but I have gained a few new opportunities that otherwise I would not have had.&amp;#160; For me, the real payoff was the sense of accomplishment, something I can show my kids that I didn’t give up and that I worked extremely hard to achieve a goal.&amp;#160; Not everyone will appreciate just what it took for me to accomplish this goal, but my family knows.&lt;/p&gt;  &lt;p&gt;I did it.&amp;#160; I set a goal, I worked hard but not hard enough, then I buckled down and really pushed through.&amp;#160; I am proud of myself, and not at all ashamed to tell anyone how hard I worked towards this goal.&amp;#160; I don’t brag about being an MCM and don’t flaunt my credentials, in fact it was a tremendously humbling experience.&amp;#160; That said, I am not at all bashful about telling you how hard I worked to get there.&amp;#160; And I certainly am telling my kids.&lt;/p&gt;  &lt;p&gt;There is nothing more valuable to me than being able to show my kids that it was tough, but if you work hard you can achieve your goals.&amp;#160; Once you accomplish your goals, sit back, reflect, and appreciate the hard work that you put into it and share that with others.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;img alt="Microsoft Certified Master, SharePoint 2010" src="http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31/2664.MCM_2800_rgb_29005F00_1406.png" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10411921" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/-NET+Programming/">.NET Programming</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/XML/">XML</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/XML+Web+Services/">XML Web Services</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/XML+Schemas/">XML Schemas</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/VSTS/">VSTS</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Mobile+Development/">Mobile Development</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Windows+Workflow+Foundation/">Windows Workflow Foundation</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Architecture/">Architecture</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Silverlight/">Silverlight</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2008/">Visual Studio 2008</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/WCF/">WCF</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/IIS7/">IIS7</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Windows+Server+2008/">Windows Server 2008</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Internet+Explorer/">Internet Explorer</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/LINQ/">LINQ</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Interoperability/">Interoperability</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Enterprise+Social+Computing/">Enterprise Social Computing</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Microsoft+Office/">Microsoft Office</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/VSeWSS/">VSeWSS</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Expression+Studio/">Expression Studio</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SQL+Server+2008/">SQL Server 2008</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/hyper_2D00_v/">hyper-v</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/tfs/">tfs</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2010/">Visual Studio 2010</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/REST/">REST</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/PowerShell/">PowerShell</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Active+Directory/">Active Directory</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Exchange/">Exchange</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/MCM/">MCM</category></item><item><title>Inside SharePoint 2013 OAuth Context Tokens</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/04/05/inside-sharepoint-2013-oauth-context-tokens.aspx</link><pubDate>Fri, 05 Apr 2013 17:43:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10408073</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10408073</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/04/05/inside-sharepoint-2013-oauth-context-tokens.aspx#comments</comments><description>&lt;p&gt;This post will show you how to inspect the SharePoint 2013 context token to better understand how OAuth is used in SharePoint 2013 apps.&lt;/p&gt;  &lt;h2&gt;First, Some Context&lt;/h2&gt;  &lt;p&gt;In order to use a context token with SharePoint 2013 apps, you will need to create a provider-hosted app that uses a client ID and a client secret.&amp;#160; This requires that the target SharePoint farm has a trust configured to Azure Access Control Services, or ACS.&amp;#160; Office365 automatically configures this trust for you, so if you create your app using Office365 then this works just fine.&amp;#160; If you create your app using your own SharePoint farm, then you will need to &lt;a href="http://blogs.msdn.com/b/besidethepoint/archive/2012/12/10/sharepoint-low-trust-apps-for-on-premises-deployments.aspx"&gt;configure low-trust apps for on-premises deployments&lt;/a&gt; in order to establish a trust with Azure ACS for your SharePoint farm.&lt;/p&gt;  &lt;p&gt;When you use a client ID and a client secret to build your app, you are using Azure ACS as the authentication server.&amp;#160; The OAuth flow looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3515.image_5F00_211375A6.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4274.image_5F00_thumb_5F00_469CF307.png" width="244" height="122" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is what I jokingly refer to as “the scary slide”.&amp;#160; It’s not really that scary once you understand it.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;User makes a request to SharePoint&lt;/li&gt;    &lt;li&gt;SharePoint requests the context token from Azure ACS&lt;/li&gt;    &lt;li&gt;The signed context token is returned&lt;/li&gt;    &lt;li&gt;The HTML markup for the SharePoint page is sent to the client&lt;/li&gt;    &lt;li&gt;If the SharePoint page contents contain a client app part, then a request is sent to the remote web server for the IFrame’s contents.&amp;#160; If the user simply clicked on the app to launch it, then a page in SharePoint called appredirect.aspx is used to redirect to the app’s start URL.&amp;#160; In either case, a context token is sent along with that page request in a form parameter called SPAppToken.&amp;#160; &lt;/li&gt;    &lt;li&gt;The context token is a &lt;a href="http://openid.net/specs/draft-jones-json-web-token-07.html"&gt;JWT token&lt;/a&gt;.&amp;#160; The JWT token is a set of base64 encoded claims.&amp;#160; One claim is named “refreshtoken” that has a base64 encoded value.&amp;#160; One of the claims is “appctx” which contains a child object, one of the properties is SecurityTokenServiceUri with a value &lt;a title="https://accounts.accesscontrol.windows.net/tokens/OAuth/2" href="https://accounts.accesscontrol.windows.net/tokens/OAuth/2"&gt;https://accounts.accesscontrol.windows.net/tokens/OAuth/2&lt;/a&gt;.&amp;#160; Your app uses the TokenHelper.cs class to extract the refreshtoken and then send it to the SecurityTokenServiceUri to request an access token.&lt;/li&gt;    &lt;li&gt;The access token is retrieved from ACS.&lt;/li&gt;    &lt;li&gt;The access token is passed to the SharePoint site in the HTTP header Authorization that has a value beginning with “Bearer” and has your access token.&amp;#160; This token is passed in the HTTP header to the CSOM endpoint _vti_bin/client.svc/ProcessQuery when you use the CSOM.&lt;/li&gt;    &lt;li&gt;If the app is authorized, SharePoint returns the data requested.&lt;/li&gt;    &lt;li&gt;Finally, the app server returns the requested HTML markup as a response.&amp;#160; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The really important thing to understand is what’s passed to your app, the context token.&amp;#160; The context token contains a few key pieces of information necessary for the rest of the plumbing to function.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;What’s In Your Wallet?&lt;/h2&gt;  &lt;p&gt;Now that we’ve walked through the steps of the OAuth dance, let’s take a look at what’s in that context token that is critical to the whole process.&amp;#160; When you use Visual Studio to create a provider-hosted app, the boiler plate code looks like this:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="rem"&gt;// The following code gets the client context and Title property by using TokenHelper.&lt;/span&gt;
    &lt;span class="rem"&gt;// To access other properties, you may need to request permissions on the host web.&lt;/span&gt;

    var contextToken = TokenHelper.GetContextTokenFromRequest(Page.Request);
    Response.Write(contextToken + &lt;span class="str"&gt;&amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);
    var hostWeb = Page.Request[&lt;span class="str"&gt;&amp;quot;SPHostUrl&amp;quot;&lt;/span&gt;];

    &lt;span class="kwrd"&gt;using&lt;/span&gt; (var clientContext = TokenHelper.GetClientContextWithContextToken(hostWeb, contextToken, Request.Url.Authority))
    {
        clientContext.Load(clientContext.Web, web =&amp;gt; web.Title);
        clientContext.ExecuteQuery();
        Response.Write(clientContext.Web.Title);
    }
}&lt;/pre&gt;


&lt;p&gt;Reading that code, you can see that the context token is passed to your app, but it is a base64 encoded string that is unintelligible.&amp;#160; I added a Response.Write statement to write the context token to the page, but you can also see it in Fiddler.&amp;#160; In the following screen shot, I highlighted the SPAppToken HTTP form variable where the context token is passed.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8877.image_5F00_0D19E310.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6811.image_5F00_thumb_5F00_55F05516.png" width="244" height="186" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have that context token, you have the base64 encoded value of the context token, which is a JWT token.&amp;#160; The &lt;a href="http://openid.net/specs/draft-jones-json-web-token-07.html"&gt;JWT token format&lt;/a&gt; is pretty straightforward, and the TokenHelper.cs class in Visual Studio simply parses that JWT token for you.&amp;#160; However, for the curious who want to see what it looks like, you can use a tool like &lt;a title="http://openidtest.uninett.no/jwt" href="http://openidtest.uninett.no/jwt"&gt;http://openidtest.uninett.no/jwt&lt;/a&gt; to inspect the JWT token.&amp;#160; Copy the context token string into the “Encoded JWT” text box and the client secret into the “Secret” text box, and then press decode.&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4657.image_5F00_2A3F8B1A.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0028.image_5F00_thumb_5F00_0F92EF01.png" width="244" height="135" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is returned is the following JSON object, which is a JWT token that contains a set of claims.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;
  &lt;pre class="csharpcode"&gt;{
    &lt;span class="str"&gt;&amp;quot;aud&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;4c2df2aa-3d14-4d84-8a79-5a75135e98d0/localhost:44346@d341a536-1d82-4267-87e6-e2dfff4fa325&amp;quot;&lt;/span&gt;,
    &lt;span class="str"&gt;&amp;quot;iss&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;00000001-0000-0000-c000-000000000000@d341a536-1d82-4267-87e6-e2dfff4fa325&amp;quot;&lt;/span&gt;,
    &lt;span class="str"&gt;&amp;quot;nbf&amp;quot;&lt;/span&gt;: 1365177964,
    &lt;span class="str"&gt;&amp;quot;exp&amp;quot;&lt;/span&gt;: 1365221164,
    &lt;span class="str"&gt;&amp;quot;appctxsender&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;00000003-0000-0ff1-ce00-000000000000@d341a536-1d82-4267-87e6-e2dfff4fa325&amp;quot;&lt;/span&gt;,
    &lt;span class="str"&gt;&amp;quot;appctx&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;{\&amp;quot;CacheKey\&amp;quot;:\&amp;quot;em1/saZohTOS4nOUZHXMb8QJgyNbkEO86TSe5j9WYmo=\&amp;quot;,
\&amp;quot;SecurityTokenServiceUri\&amp;quot;:\&amp;quot;https://accounts.accesscontrol.windows.net/tokens/OAuth/2\&amp;quot;}&amp;quot;&lt;/span&gt;,
    &lt;span class="str"&gt;&amp;quot;refreshtoken&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;IAAAANc8bAVMWZceOsdfgsdfggbfm7oU_aM7D2qofUpQstMsdfgsdfgfYS0OtbZ-
eY9UQGvlYSl5kpPi913G1AwIVBMxoCux8-bhcCCiaGVo-vuFzrXetdhRGPftQdHh-
1rS5cvDuuQ_bw_mjySIyuHNGSavEs8HUgHY9BOVc3pTGZtZ_nS-
1NbDLYObjnznasdfasdfasdfQreLAeeOpVRY1PGsdfgsdfgOITA3BKhjJFz_40YJMubdHmY2OTS
nqwNnUe-rBBCtfvKt4xFWvdRzTzwfW&amp;quot;&lt;/span&gt;,

    &lt;span class="str"&gt;&amp;quot;isbrowserhostedapp&amp;quot;&lt;/span&gt;: &lt;span class="str"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;
}&lt;/pre&gt;
  You can now see that the context token contains the refresh token as a base64 encoded value.&lt;/p&gt;

&lt;h2&gt;What are the claims in the context token?&lt;/h2&gt;

&lt;p&gt;The following shows the properties for the context token.&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="2" width="552" border="0"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;aud&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Short for “audience”, means the principal the token is intended for. The format is &amp;lt;&lt;em&gt;client ID&lt;/em&gt;&amp;gt;/&amp;lt;&lt;em&gt;target URL authority&lt;/em&gt;&amp;gt;@&amp;lt;&lt;em&gt;target realm&lt;/em&gt;&amp;gt;. Based on this information, you can determine the client ID for your app and the realm.&amp;#160; In an on-premise environment, there is typically just one realm, and its identifier matches your farm ID.&amp;#160; For Office 365, this is your tenant ID.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;iss&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Short for “issuer”, this is the principal that issued the token, in the form of &amp;lt;&lt;em&gt;principal ID&amp;gt;@&amp;lt;realm&amp;gt;&lt;/em&gt;.&amp;#160; The principal ID value &lt;strong&gt;00000001-0000-0000-c000-000000000000&lt;/strong&gt; is ACS.&amp;#160; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;nbf&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Short for “not before”, this is the number of seconds after January 1, 1970 (part of the JWT specification) that the token &lt;em&gt;starts&lt;/em&gt; being valid.&amp;#160; &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;exp&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Short for “expires”, represents the number of seconds after January 1, 1970 that the token &lt;em&gt;stops&lt;/em&gt; being valid.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;appctxsender&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;The sender of the token in the form &amp;lt;sender ID&amp;gt;@&amp;lt;realm&amp;gt;.&amp;#160; The value &lt;strong&gt;00000003-0000-0ff1-ce00-000000000000&lt;/strong&gt; is the identifier for SharePoint.&amp;#160; For trivia:

        &lt;br /&gt;

        &lt;br /&gt;

        &lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;
            &lt;tr&gt;
              &lt;td valign="top" width="85"&gt;&lt;strong&gt;ACS&lt;/strong&gt;&lt;/td&gt;

              &lt;td valign="top" width="315"&gt;&lt;strong&gt;00000001-0000-0000-c000-000000000000&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;

            &lt;tr&gt;
              &lt;td valign="top" width="85"&gt;&lt;strong&gt;Exchange &lt;/strong&gt;&lt;/td&gt;

              &lt;td valign="top" width="315"&gt;&lt;strong&gt;00000002-0000-&lt;font style="background-color: rgb(255, 255, 0);"&gt;0ff1-ce&lt;/font&gt;00-000000000000&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;

            &lt;tr&gt;
              &lt;td valign="top" width="85"&gt;&lt;strong&gt;SharePoint&lt;/strong&gt;&lt;/td&gt;

              &lt;td valign="top" width="315"&gt;&lt;strong&gt;00000003-0000-&lt;font style="background-color: rgb(255, 255, 0);"&gt;0ff1-ce&lt;/font&gt;00-000000000000&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;

            &lt;tr&gt;
              &lt;td valign="top" width="85"&gt;&lt;strong&gt;Lync&lt;/strong&gt;&lt;/td&gt;

              &lt;td valign="top" width="315"&gt;&lt;strong&gt;00000004-0000-&lt;font style="background-color: rgb(255, 255, 0);"&gt;0ff1-ce&lt;/font&gt;00-000000000000&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;

            &lt;tr&gt;
              &lt;td valign="top" width="85"&gt;&lt;strong&gt;Workflow&lt;/strong&gt;&lt;/td&gt;

              &lt;td valign="top" width="315"&gt;&lt;strong&gt;00000005-0000-0000-c000-000000000000&lt;/strong&gt;&lt;/td&gt;
            &lt;/tr&gt;
          &lt;/tbody&gt;&lt;/table&gt;

        &lt;br /&gt;The realm will be the tenant ID for Office 365, or the farm ID for your on-premise deployment.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;appctx&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Contains two properties, CacheKey and SecurityTokenServiceUri.
        &lt;br /&gt;&lt;strong&gt;CacheKey:
          &lt;br /&gt;&lt;/strong&gt;UserNameId + &amp;quot;,&amp;quot; + UserNameIdIssuer + &amp;quot;,&amp;quot; + ApplicationId + &amp;quot;,&amp;quot; + Realm

        &lt;br /&gt;This is provided so that you can cache the value in a cookie or in session to identify that the user has already authenticated.

        &lt;br /&gt;

        &lt;br /&gt;&lt;strong&gt;SecurityTokenServiceUri:
          &lt;br /&gt;&lt;/strong&gt;The URL for Azure ACS where the token is to be validated.&amp;#160; The URL is &lt;a href="https://accounts.accesscontrol.windows.net/tokens/OAuth/2"&gt;https://accounts.accesscontrol.windows.net/tokens/OAuth/2&lt;/a&gt;.&amp;#160; &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;refreshtoken&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;The contents of the refresh token that are sent to Azure ACS.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="142"&gt;isbrowserhostedapp&lt;/td&gt;

      &lt;td valign="top" width="408"&gt;Indicates if the request initiated from a user interacting with the browser and not an app event receiver&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;p&gt;During Ignite training, I tell the attendees that the most important thing you can understand when building apps for SharePoint is OAuth.&amp;#160; You need to understand the OAuth dance, the reason for the context token, and it is invaluable to understand what the TokenHelper.cs is doing for you when it does things like &lt;strong&gt;GetClientContextFromContextToken&lt;/strong&gt;.&amp;#160; This post goes into some of the details on why this is such an important piece to understand when troubleshooting apps.&amp;#160; You can also see why it is mandatory for apps to SSL due to the nature of information being sent in HTTP.&amp;#160; &lt;/p&gt;

&lt;p&gt;You can find more information about the context token, calculating &lt;strong&gt;nbf&lt;/strong&gt; and &lt;strong&gt;exp&lt;/strong&gt; claim values, and links to additional articles at &lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx"&gt;http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx&lt;/a&gt;.&amp;#160; &lt;/p&gt;

&lt;h2&gt;For More Information &lt;/h2&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/b/besidethepoint/archive/2012/12/10/sharepoint-low-trust-apps-for-on-premises-deployments.aspx"&gt;configure low-trust apps for on-premises deployments&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://openid.net/specs/draft-jones-json-web-token-07.html"&gt;JWT token format&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx"&gt;Tips and FAQs: OAuth and remote apps for SharePoint 2013&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10408073" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/-NET+Programming/">.NET Programming</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Architecture/">Architecture</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Apps/">Apps</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2012/">Visual Studio 2012</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/OAuth/">OAuth</category></item><item><title>Access 2013–Not Your Father’s Access</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/04/02/access-2013-not-your-father-s-access.aspx</link><pubDate>Tue, 02 Apr 2013 15:20:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10406953</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10406953</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/04/02/access-2013-not-your-father-s-access.aspx#comments</comments><description>&lt;p&gt;I worked this weekend to prepare for a presentation this week at the &lt;a href="http://www.sharepointtechfest.com/"&gt;Dallas SharePoint TechFest&lt;/a&gt;, “Access Services 2013 – Not Your Father’s Access!”&amp;#160; I am covering the new features of Access 2013 as an app designer for SharePoint 2013.&amp;#160; While presenting on Access, I frequently say that while Access has changed drastically, Access remains familiar because key parts of the UI have barely changed since 1993.&amp;#160; As proof, I installed Windows XP and Access 2.0 and took some screen shots for comparison.&lt;/p&gt;  &lt;p&gt;Creating a table:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0167.image_5F00_06376B22.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1050.image_5F00_thumb_5F00_37C2D8B7.png" width="244" height="163" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3288.image_5F00_7E3FC8BF.png"&gt;&lt;img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1651.image_5F00_thumb_5F00_24A1AC0B.png" width="244" height="185" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Creating a query:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2630.image_5F00_041A6C59.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6428.image_5F00_thumb_5F00_6AB2691E.png" width="244" height="154" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3201.image_5F00_54E880C1.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1663.image_5F00_thumb_5F00_4D5D1154.png" width="244" height="185" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Even the wizards to create tables have pretty much the same elements as they did back in Access 2.0 with the ability to choose from out of box templates.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6740.image_5F00_41C75415.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1641.image_5F00_thumb_5F00_012507A6.png" width="244" height="162" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0488.image_5F00_2786EAF1.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1157.image_5F00_thumb_5F00_0B09F911.png" width="244" height="182" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The thing that is drastically different is the ability for end users to use Access 2013 with Access Services 2013 to create apps for SharePoint 2013.&amp;#160; That’s the part that I am very excited about because it provides the ability for end users to create composite applications without requiring developers.&amp;#160; Looking forward to speaking at the event!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10406953" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Microsoft+Office/">Microsoft Office</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Access/">Access</category></item><item><title>New Features in Microsoft Office Developer Tools for Visual Studio 2012</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/04/01/new-features-in-microsoft-office-developer-tools-for-visual-studio-2012.aspx</link><pubDate>Mon, 01 Apr 2013 14:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10406484</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10406484</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/04/01/new-features-in-microsoft-office-developer-tools-for-visual-studio-2012.aspx#comments</comments><description>&lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-US/office/apps/fp123627"&gt;Microsoft Office Developer Tools for Visual Studio 2012&lt;/a&gt; have been released and have some fantastic new additions in them for building apps.&amp;#160; This blog post covers some of the new features that you’ll want to be familiar with.&lt;/p&gt;  &lt;h2&gt;New Project Item Templates&lt;/h2&gt;  &lt;p&gt;There are a few project item templates that have been added since the Preview 2 tools.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0537.image_5F00_6FD4946C.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6404.image_5F00_thumb_5F00_7D3AA772.png" width="214" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Search Configuration Project Item &lt;/h3&gt;  &lt;p&gt;An interesting addition is the new Search Configuration project item template.&amp;#160; To use this, create a search center and then go to Site Settings / Search / Configuration Export.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4426.image_5F00_0EAB084B.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2604.image_5F00_thumb_5F00_2E59E213.png" width="244" height="224" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This will export the search settings as an XML file.&amp;#160; When you use the Search Configuration project item in Visual Studio, it prompts you for this XML file.&amp;#160; This enables you to deploy search settings such as ranking models and managed properties as part of your app!&amp;#160; For more information on deploying search customizations, see the MSDN topic &lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/dn194077.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/dn194077.aspx"&gt;How to: Deploy custom search configurations by using Visual Studio&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;App for Office Project Item&lt;/h3&gt;  &lt;p&gt;Another project item to notice is the App for Office project item that can be added to a SharePoint hosted app or a provider hosted app. This project item enables you to define your app and bind it to a document, which can then be used in your project to set as the default template of a document library.&amp;#160; Add the new App for Office to a SharePoint hosted app:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2262.image_5F00_74D6D21B.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5482.image_5F00_thumb_5F00_0D666F6C.png" width="244" height="206" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The next screen asks if you want to create a new document or use an existing document:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5327.image_5F00_68D4E1E7.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8547.image_5F00_thumb_5F00_53772C7F.png" width="244" height="205" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Add a new list to the project, creating a customizable list based on the Document Library type.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8154.image_5F00_00F84C43.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7870.image_5F00_thumb_5F00_008C194E.png" width="244" height="179" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here’s the really cool part.&amp;#160; Prior to the RTM version of the tools, this is where things stopped, and you had to do some work with the element manifest files to deploy the document and set it as the document template.&amp;#160; Visual Studio now saves you this extra step, allowing you to choose the document created in the previous step that has a reference to your app.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3757.image_5F00_6B2E63E5.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3364.image_5F00_thumb_5F00_6AC230F0.png" width="244" height="178" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To test, I changed the start URL of my app to ~appWebUrl/Lists/MyDocs?{StandardTokens} and press F5.&amp;#160; The app opens to my new document library, and the content type is available in the New menu.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6813.image_5F00_6A55FDFB.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8547.image_5F00_thumb_5F00_45C47077.png" width="244" height="241" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Create a new “MyDocsContentType” document, and when the document is opened, it will have your app already in it!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8176.image_5F00_253D30C5.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3264.image_5F00_thumb_5F00_1DB1C158.png" width="244" height="186" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Personally, I love this feature.&amp;#160; There used to be many more steps involved in this, and this makes the entire process so incredibly simple.&amp;#160; Even better, the content for your app is being served from SharePoint, so there’s no need to go search for somewhere to host your app for Office.&amp;#160; &lt;/p&gt;  &lt;p&gt;For more information on deploying an App for Office as part of your SharePoint app, see the MSDN topic &lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/fp179815.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/fp179815.aspx"&gt;How to: Create an app for SharePoint that contains a document template and a task pane app&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Debugging Remote Event Receivers&lt;/h2&gt;  &lt;p&gt;One of my favorite additions in the tools is the ability to use Windows Azure Service Bus for debugging remote event receivers.&amp;#160; This was a challenge with previous releases of the tools because remote event receivers are basically HTTP calls made from the SharePoint server.&amp;#160; If you develop an autohosted app, add a remote event receiver, add a breakpoint and press F5 in Visual Studio, your event receiver will not fire because your web application is running as the address localhost, the remote server cannot resolve “localhost” to your machine.&amp;#160; The new developer tools make this simple by leveraging Windows Azure Service Bus.&amp;#160; Start by logging into the Azure Portal and add a new namespace. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5824.image_5F00_1D458E63.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1207.image_5F00_thumb_5F00_6AE1BAE3.png" width="244" height="173" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Once the namespace is created, you can use the “Access Key” button to discover the connection string for your service bus endpoint. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0647.image_5F00_759F1238.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1538.image_5F00_thumb_5F00_5C370EFE.png" width="244" height="233" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now go to the properties / SharePoint tab for your app manifest project and paste the Windows Azure Service Bus connection string.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6013.image_5F00_22B3FF07.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2781.image_5F00_thumb_5F00_2D71565C.png" width="244" height="64" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Add a breakpoint, hit F5, and watch the goodness as the web site containing your remote event receiver service is running under localhost and the breakpoint is still hit!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3660.image_5F00_41F6A5DA.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/1122.image_5F00_thumb_5F00_2B545793.png" width="244" height="214" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To learn more about remote event receivers in SharePoint 2013, see the MSDN topic &lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/jj220048.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/jj220048.aspx"&gt;Handling events in apps for SharePoint&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;App for Office Validation&lt;/h2&gt;  &lt;p&gt;I was very happy to see that a new feature has been added when publishing your app for Office… validation!&amp;#160; This validation is representative of some of the checks that will be made when you submit your app to the Office marketplace.&amp;#160; Simply check the checkbox to “Validate my app for the Office Store” on the publish window and choose Finish.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0243.image_5F00_0ACD17E1.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6406.image_5F00_thumb_5F00_514A07E9.png" width="244" height="185" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Your app will then be validated and a report shown of various issues that could prevent your app from successfully being submitted to the Office Store.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0636.image_5F00_45B44AAA.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0647.image_5F00_thumb_5F00_5E43E7FA.png" width="244" height="129" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To learn more about the validation policies for apps submitted to the Office Store, see the MSDN topic &lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/jj220035.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/jj220035.aspx"&gt;Validation policies for the apps submitted to the Office Store (version 1.3)&lt;/a&gt;.&lt;/p&gt;      &lt;h2&gt;For More Information&lt;/h2&gt;  &lt;p&gt;Download &lt;a href="http://msdn.microsoft.com/en-US/office/apps/fp123627"&gt;Microsoft Office Developer Tools for Visual Studio 2012&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/dn194077.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/dn194077.aspx"&gt;How to: Deploy custom search configurations by using Visual Studio&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/fp179815.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/fp179815.aspx"&gt;How to: Create an app for SharePoint that contains a document template and a task pane app&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/jj220048.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/jj220048.aspx"&gt;Handling events in apps for SharePoint&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/office/apps/jj220035.aspx" href="http://msdn.microsoft.com/en-us/library/office/apps/jj220035.aspx"&gt;Validation policies for the apps submitted to the Office Store (version 1.3)&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10406484" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Apps/">Apps</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2012/">Visual Studio 2012</category></item><item><title>SharePoint 2013 App Only Policy Made Easy</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/02/23/sharepoint-2013-app-only-policy-made-easy.aspx</link><pubDate>Sat, 23 Feb 2013 16:12:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10396454</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10396454</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/02/23/sharepoint-2013-app-only-policy-made-easy.aspx#comments</comments><description>&lt;p&gt;This post demonstrates the app only policy for SharePoint 2013 app development and show how to create SharePoint 2013 apps using OAuth tokens with either a trust to ACS as well as S2S.&amp;#160; I show how to request the &lt;strong&gt;AllowAppOnlyPolicy&lt;/strong&gt; permission and how to execute actions that the current user is not authorized to perform directly.&lt;/p&gt;  &lt;h2&gt;Background&lt;/h2&gt;  &lt;p&gt;As developers start working with SharePoint 2013 apps, you quickly realize how permissions with apps work when performing work on behalf of a user.&amp;#160; I can log in as the site collection administrator, and execute an app that writes to a list and see the action fail because permission was denied.&amp;#160; The reason it was denied is because the app did not request write permissions to the list it was trying to write to.&amp;#160; Similarly, I can log in as a user who only has read permission to a list and invoke an app that has full control permission and see an attempt to write to a list fail because permission was denied.&amp;#160; The reason this time is that even though the app had permissions, the user did not. &lt;/p&gt;  &lt;p&gt;This is explained in the following diagram.&amp;#160; The app is making a call into SharePoint, and it does so by providing the OAuth access token.&amp;#160; SharePoint sees that no user credentials were provided in the request and an OAuth access token is present.&amp;#160; When acting on behalf of a user, the token will include user information, so the context will be the App+User context.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6840.image_5F00_68B8261A.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3884.image_5F00_thumb_5F00_6EFEFCA8.png" width="244" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is exactly the scenario I just described.&amp;#160; The App+User policy is applied, and both the user and the app must have sufficient permission to write to the list.&lt;/p&gt;  &lt;h2&gt;Can I Elevate Privileges?&lt;/h2&gt;  &lt;p&gt;When presenting this material to developers, this is usually right about the time someone asks me about the RunWithElevatedPrivileges API.&amp;#160; It should be renamed to “RunWithScissors”, because so many developers use it but don’t quite understand what the API is doing, and it is this confusion that usually generates support calls on how to properly use the API in a predictable manner.&amp;#160; The new app model does away with this impersonation confusion and makes things quite a bit more straightforward because there is no impersonation capability in the API.&lt;/p&gt;  &lt;p&gt;And when I say this to developers looking at apps for the first time, they usually want to throw things at me.&amp;#160; How the heck am I supposed to get things done?!?&amp;#160; Give users permissions to everything?!?&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;Let’s analyze the requirement instead of focusing on how we arrive at the solution.&amp;#160; We need to perform an action that the user is not entitled to.&amp;#160; OK, now that we agree on semantics, how, then, do I use the new app model to perform actions when the user doesn’t have permission?&amp;#160; In the scenario presented earlier, how can I create an app that has privileges to do something such as writing to a list even though the current user does not have permissions to write to the list?&amp;#160; The answer is the App Only Policy.&amp;#160; &lt;/p&gt;  &lt;p&gt;Don’t think of this as impersonation or elevation of the current user’s privileges, it’s not.&amp;#160; In fact, we are not going to use the permissions of the current user at all.&lt;/p&gt;  &lt;h2&gt;The App Only Policy&lt;/h2&gt;  &lt;p&gt;In the previous diagram, we highlighted a flow where an app is calling into SharePoint using the CSOM.&amp;#160; Our new scenario of an app performing work that the user does not have permission to means we will use the app only policy.&amp;#160; Following the flow diagram from the Start node, there is no user credential provided, an OAuth access token is present, and this time the token does not contain user information.&amp;#160; In this case, we are solely evaluating permissions based on the permission of the app and not on the user.&amp;#160; &lt;/p&gt;  &lt;p&gt;Doing this is actually pretty straightforward.&amp;#160; The first step is to request permission to use the app only policy in your app manifest by adding the &lt;strong&gt;AllowAppOnlyPolicy&lt;/strong&gt; attribute to the AppPermissionRequests node with a value of true.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3480.image_5F00_59A14740.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8267.image_5F00_thumb_5F00_5935144B.png" width="244" height="54" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;When your app requests this permission, a subtle change is reflected in the trust dialog.&amp;#160; You now see the text “&lt;strong&gt;Let it share its permissions with other users&lt;/strong&gt;.”.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/4370.image_5F00_58C8E156.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0753.image_5F00_thumb_5F00_585CAE61.png" width="244" height="127" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This text is letting you know that the app is requesting permission to perform actions that the user may not have permission to.&amp;#160; In this dialog, the app will be granted Write permission (which means read, create, edit, or delete items) in the Announcements list and will be able to do so whether the user has permission or not.&lt;/p&gt;  &lt;p&gt;This capability is only available to provider-hosted and Azure auto-hosted apps.&amp;#160; It is not available to SharePoint-hosted apps.&amp;#160; In a SharePoint-hosted app, there is necessarily always an app+user context.&amp;#160; &lt;/p&gt;  &lt;h2&gt;App Only Context with S2S&lt;/h2&gt;  &lt;p&gt;Creating a provider-hosted app that leverages only policy using S2S is actually very easy.&amp;#160; The first step is to make sure that you add the &lt;strong&gt;AllowAppOnlyPolicy&lt;/strong&gt; attribute in the app manifest.&amp;#160; The next step is to use the &lt;strong&gt;TokenHelper::GetS2SAccessTokenWithWindowsIdentity&lt;/strong&gt; method, passing a null for the WindowsIdentity parameter.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; appOnlyAccessToken = 
   TokenHelper.GetS2SAccessTokenWithWindowsIdentity(_hostWeb, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;/pre&gt;


&lt;p&gt;If the app manifest has the AllowAppOnlyPolicy attribute set to true, this call will succeed and return a valid OAuth access token that does not contain user information.&amp;#160; Once you have the access token, then you can use the &lt;strong&gt;TokenHelper::GetClientContextWithAccessToken&lt;/strong&gt; method to obtain a CSOM client context.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (ClientContext clientContext = 
    TokenHelper.GetClientContextWithAccessToken(_hostWeb.ToString(), appOnlyAccessToken))
{
    List list = clientContext.Web.Lists.GetByTitle(&lt;span class="str"&gt;&amp;quot;Announcements&amp;quot;&lt;/span&gt;);
    ListItemCreationInformation info = &lt;span class="kwrd"&gt;new&lt;/span&gt; ListItemCreationInformation();
    Microsoft.SharePoint.Client.ListItem item = list.AddItem(info);
    item[&lt;span class="str"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;Created from CSOM&amp;quot;&lt;/span&gt;;
    item[&lt;span class="str"&gt;&amp;quot;Body&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;Created from CSOM &amp;quot;&lt;/span&gt; + DateTime.Now.ToLongTimeString();

    item.Update();
    clientContext.Load(item);
    clientContext.ExecuteQuery();
}&lt;/pre&gt;


&lt;p&gt;To test this, deploy the app and then log on as a user that only has read permission to the list.&amp;#160; Execute the code, and a new item is created even though the user does not have permission to create items in the list.&amp;#160; The Created By and Modified By fields in the list will reflect that it was only the app’s permissions that were used to create the item.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6136.image_5F00_53E62D9A.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/8015.image_5F00_thumb_5F00_5EA384EF.png" width="244" height="89" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we had included a user identity (as the code generated by Visual Studio does by default), then the created by and modified by fields would look a little different, showing that code was executed &lt;strong&gt;on behalf of&lt;/strong&gt; an individual.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/5037.image_5F00_2C3FB170.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/2311.image_5F00_thumb_5F00_4BEE8B38.png" width="244" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;App Only Context with ACS&lt;/h2&gt;

&lt;p&gt;Creating an app-only context with a provider-hosted app using a trust to ACS is just slightly more involved.&amp;#160; A trust to ACS is automatically established when you create your O365 tenant.&amp;#160; If you are self-hosting your SharePoint farm, then &lt;a href="http://blogs.msdn.com/b/besidethepoint/archive/2012/12/10/sharepoint-low-trust-apps-for-on-premises-deployments.aspx"&gt;a trust to ACS can be established between your SharePoint farm and ACS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We use a similar approach as before, but this time we need to extract the context token string and validate the token in order to retrieve information such as the authentication realm.&amp;#160; Provided this information, we can now request an app-only token using &lt;strong&gt;TokenHelper::GetAppOnlyAccessToken&lt;/strong&gt;.&amp;#160; Once we have the access token, we can now obtain the client context using &lt;strong&gt;TokenHelper::GetClientContextWithAccessToken&lt;/strong&gt;.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; _hostWeb = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(Request.QueryString[&lt;span class="str"&gt;&amp;quot;SPHostUrl&amp;quot;&lt;/span&gt;]);
&lt;span class="kwrd"&gt;string&lt;/span&gt; _contextTokenString = TokenHelper.GetContextTokenFromRequest(Page.Request);

&lt;span class="rem"&gt;//Get context token.&lt;/span&gt;
SharePointContextToken contextToken =
    TokenHelper.ReadAndValidateContextToken_contextTokenString, Request.Url.Authority);

&lt;span class="rem"&gt;//Get app only access token.&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; appOnlyAccessToken = 
    TokenHelper.GetAppOnlyAccessToken(contextToken.TargetPrincipalName, 
            _hostWeb.Authority, contextToken.Realm).AccessToken;

Response.Write(&lt;span class="str"&gt;&amp;quot;&amp;lt;h2&amp;gt;Valid app-only access token retrieved&amp;lt;/h2&amp;gt;&amp;quot;&lt;/span&gt;);
Response.Write(&lt;span class="str"&gt;&amp;quot;&amp;lt;p&amp;gt;&amp;quot;&lt;/span&gt; + appOnlyAccessToken + &lt;span class="str"&gt;&amp;quot;&amp;lt;/p&amp;gt;&amp;quot;&lt;/span&gt;);
Response.Flush();

&lt;span class="kwrd"&gt;using&lt;/span&gt; (ClientContext clientContext = 
    TokenHelper.GetClientContextWithAccessToken(_hostWeb.ToString(), appOnlyAccessToken))
{
    List list = clientContext.Web.Lists.GetByTitle(&lt;span class="str"&gt;&amp;quot;Announcements&amp;quot;&lt;/span&gt;);
    ListItemCreationInformation info = &lt;span class="kwrd"&gt;new&lt;/span&gt; ListItemCreationInformation();
    Microsoft.SharePoint.Client.ListItem item = list.AddItem(info);
    item[&lt;span class="str"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;Created from CSOM&amp;quot;&lt;/span&gt;;
    item[&lt;span class="str"&gt;&amp;quot;Body&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;Created from CSOM &amp;quot;&lt;/span&gt; + DateTime.Now.ToLongTimeString();

    item.Update();
    clientContext.Load(item);
    clientContext.ExecuteQuery();
}&lt;/pre&gt;


&lt;p&gt;The result is the same as before… a user that does not have write permission to a list is able to execute the app, which has been granted the &lt;strong&gt;AllowAppOnlyPolicy&lt;/strong&gt; in the permission requests in the app manifest, and the write to list operation now succeeds.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h2&gt;For More Information&lt;/h2&gt;

&lt;p&gt;&lt;a title="http://technet.microsoft.com/en-us/subscriptions/downloads/fp179892.aspx" href="http://msdn.microsoft.com/en-us/library/fp179892.aspx"&gt;App authorization policy types in SharePoint 2013&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title="http://blogs.msdn.com/b/besidethepoint/archive/2012/12/10/sharepoint-low-trust-apps-for-on-premises-deployments.aspx" href="http://blogs.msdn.com/b/besidethepoint/archive/2012/12/10/sharepoint-low-trust-apps-for-on-premises-deployments.aspx"&gt;SharePoint Low-Trust Apps for On-Premises Deployments&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10396454" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Interoperability/">Interoperability</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Apps/">Apps</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Visual+Studio+2012/">Visual Studio 2012</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/OAuth/">OAuth</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/S2S/">S2S</category></item><item><title>Configuring LDAP for FBA in SharePoint 2010 or SharePoint 2013 with PowerShell</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/01/31/configuring-ldap-for-fba-in-sharepoint-2010-or-sharepoint-2013-with-powershell.aspx</link><pubDate>Thu, 31 Jan 2013 18:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10390023</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10390023</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/01/31/configuring-ldap-for-fba-in-sharepoint-2010-or-sharepoint-2013-with-powershell.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This post provides PowerShell script to easily configure forms based authentication using LDAP in SharePoint 2010 or 2013.&lt;/p&gt;
&lt;p&gt;A long time ago, I wrote a post that shows how to configure the &lt;a href="http://blogs.msdn.com/b/kaevans/archive/2010/07/09/sql-server-provider-for-claims-based-authentication-in-sharepoint-2010.aspx"&gt;SQL Server Provider for FBA in SharePoint 2010&lt;/a&gt;.&amp;nbsp; I also wrote an accompanying post on how to &lt;a href="http://blogs.msdn.com/b/kaevans/archive/2012/08/29/setting-up-fba-and-sql-membership-in-sharepoint-2010-with-powershell.aspx"&gt;automate configuring FBA with SqlMembershipProvider in SharePoint 2010 using PowerShell&lt;/a&gt;.&amp;nbsp; Those posts also apply to SharePoint 2013 as well, you just need to change the path to the STS web.config to point to the path in SharePoint 2013.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Today I was troubleshooting a configuration that uses LDAP to authenticate users using the LdapMembershipProvider, enabling LDAP authentication in SharePoint using FBA.&amp;nbsp; Admittedly, I stumbled a few times due to the slight differences between the settings in Central Administration, the STS, and the application&amp;rsquo;s web.config settings.&amp;nbsp; Once I got it working, I decided to create a PowerShell script that would let me easily configure an LDAP provider for SharePoint 2010 or SharePoint 2013 and take the guesswork out of it while making the process less error-prone.&lt;/p&gt;
&lt;h2&gt;What Does It Do?&lt;/h2&gt;
&lt;p&gt;The code isn&amp;rsquo;t terribly difficult, and follows the directions from the TechNet article &lt;a title="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx" href="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx"&gt;Configure forms-based authentication for a claims-based Web application (SharePoint Server 2010)&lt;/a&gt; closely.&amp;nbsp; It uses PowerShell to update the web.config for the web application, Central Administration, and the STS for every server in your farm.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;main&amp;rdquo; part of the script is at the bottom of the page. This is where we ask for all servers in the farm that are application servers (not SQL, Active Directory, or Exchange servers) and iterate through all of them. Note that the currently logged in account must have read-write permissions to all of the servers in the farm and have access to the C drive on each.&amp;nbsp; Also notice that a backup file is created in the directory using the form &amp;ldquo;yyyy MM dd HH mm.web.config.bak&amp;rdquo; so that, should something go wrong, you can easily revert back to a previous version of the configuration file.&lt;/p&gt;
&lt;p&gt;I did not edit the script to overwrite previous changes, I leave that as an exercise to the reader.&amp;nbsp; The good news is that you can just go back to a previous backup file (one of the .bak files that this script creates) and simply rename it to web.config and you are back to where you started.&lt;/p&gt;
&lt;h2&gt;What Do I Need to Change?&lt;/h2&gt;
&lt;p&gt;The only part of the script that you should need to change are the variables at the bottom of the page.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;#Update with path to Central Administration web.config &lt;/span&gt;
$pathToCentralAdminConfig = &lt;span class="str"&gt;"c:\inetpub\wwwroot\wss\VirtualDirectories\37552\web.config"&lt;/span&gt; 
&lt;span class="rem"&gt;#Update with path to web application's web.config &lt;/span&gt;
$pathToWebApplicationConfig = &lt;span class="str"&gt;"c:\inetpub\wwwroot\wss\VirtualDirectories\DevTeam.Contoso.lab80\web.config"&lt;/span&gt; 
&lt;span class="rem"&gt;#Update with the correct LDAP server &lt;/span&gt;
$ldapServer = &lt;span class="str"&gt;"dc.contoso.lab"&lt;/span&gt;
&lt;span class="rem"&gt;#Update with the correct container name&lt;/span&gt;
$userContainer = &lt;span class="str"&gt;"OU=EMPLOYEES,DC=CONTOSO,DC=LAB"&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;The article &lt;a title="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx" href="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx"&gt;Configure forms-based authentication for a claims-based Web application (SharePoint Server 2010)&lt;/a&gt; has a good walkthrough of the settings and changes.&amp;nbsp; The ldapServer variable is the LDAP server that you will authenticate against, and the userContainer variable is the container that holds your users.&lt;/p&gt;
&lt;p&gt;If you want to find out what the correct container name is, Mirjam van Olst provides a great trick in her blog post &amp;ldquo;&lt;a title="http://sharepointchick.com/archive/2010/05/06/configuring-claims-and-forms-based-authentication-for-use-with-an.aspx" href="http://sharepointchick.com/archive/2010/05/06/configuring-claims-and-forms-based-authentication-for-use-with-an.aspx"&gt;Configuring claims and forms based authentication for use with an LDAP provider in SharePoint 2010&lt;/a&gt;&amp;rdquo;.&amp;nbsp; Just go to Active Directory Users and Computers, right-click the container name and choose All Tasks / Resultant Set of Policy (Planning).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/0066.image_5F00_0B58FEB3.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3582.image_5F00_thumb_5F00_4AB6B243.png" alt="image" width="238" height="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The resulting screen will provide the container name.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3681.image_5F00_10C76F57.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7206.image_5F00_thumb_5F00_29570CA7.png" alt="image" width="244" height="210" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The configuration for SharePoint 2010 and SharePoint 2013 are identical, except the path to the STS web.config. If you are using SharePoint 2013, you will also want to update the path to the STS web.config in the Main function within the script.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;$stsConfigPath = "\\$name\c$\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\WebServices\SecurityToken\web.config" &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note also that the script assumes a membership provider name of &amp;ldquo;LdapMember&amp;rdquo; and role provider name of &amp;ldquo;LdapRole&amp;rdquo;.&amp;nbsp; These are the values you will enter into Central Administration when configuring FBA.&lt;/p&gt;
&lt;h2&gt;Show Me The Code!&lt;/h2&gt;
&lt;p&gt;The code is available as an attachment to this post as well.&amp;nbsp; As usual, this code is provided as-is, no warranties, use at your own risk.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; CreateBackupFile($xmlDoc, $path)
{
    $date = Get-Date    
    $dateString = $date.ToString(&lt;span class="str"&gt;"yyyy MM dd H mm"&lt;/span&gt;)
    $backupPath = $path.Replace(&lt;span class="str"&gt;"web.config"&lt;/span&gt;, &lt;span class="str"&gt;"$dateString.web.config.bak"&lt;/span&gt;)
    $xmlDoc.Save($backupPath)
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; AddPeoplePickerWildcard($xmlDoc)
{    
    
    
    $newPeoplePickerNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/SharePoint/PeoplePickerWildcards/add[@key='LdapMember']"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$newPeoplePickerNode)
    {

        $peoplePickerNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/SharePoint/PeoplePickerWildcards"&lt;/span&gt;)
        $newPeoplePickerMemberNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;, &lt;span class="str"&gt;"add"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;)
        
        $peoplePickerKeyAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"key"&lt;/span&gt;);
        $peoplePickerKeyAttr.Value = &lt;span class="str"&gt;"LdapMember"&lt;/span&gt;;
        $newPeoplePickerMemberNode.Attributes.Append($peoplePickerKeyAttr)
        
        $peoplePickerValueAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"value"&lt;/span&gt;);
        $peoplePickerValueAttr.Value = &lt;span class="str"&gt;"*"&lt;/span&gt;        
        $newPeoplePickerMemberNode.Attributes.Append($peoplePickerValueAttr)
        
        $peoplePickerNode.AppendChild($newPeoplePickerMemberNode)
        
        $newPeoplePickerRoleNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"add"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
        
        $peoplePickerKeyAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"key"&lt;/span&gt;);
        $peoplePickerKeyAttr.Value = &lt;span class="str"&gt;"LdapRole"&lt;/span&gt;;
        $newPeoplePickerRoleNode.Attributes.Append($peoplePickerKeyAttr)
        
        $peoplePickerValueAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"value"&lt;/span&gt;);
        $peoplePickerValueAttr.Value = &lt;span class="str"&gt;"*"&lt;/span&gt;        
        $newPeoplePickerRoleNode.Attributes.Append($peoplePickerValueAttr)        
        
        $peoplePickerNode.AppendChild($newPeoplePickerRoleNode)
        
    }
    
}


&lt;span class="kwrd"&gt;function&lt;/span&gt; AddMembership($xmlDoc, $ldapServer, $userContainer, $userFilter)
{
    $membershipAddNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/membership/providers/add[@name='LdapMember']"&lt;/span&gt;)
    
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$membershipAddNode)
    {
        &lt;span class="rem"&gt;#The membership node doesn't exist&lt;/span&gt;
        $membershipNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/membership"&lt;/span&gt;)
        $providerNode = $null
        
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$membershipNode)
        {
            $membershipNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;, &lt;span class="str"&gt;"membership"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;)        
            $providerNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"providers"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
            $membershipNode.AppendChild($providerNode)
            $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web"&lt;/span&gt;).AppendChild($membershipNode)                
        }
        
        $providerNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/membership/providers"&lt;/span&gt;)
        $membershipAddNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"add"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
        
        $membershipNameAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"name"&lt;/span&gt;)
        $membershipNameAttr.Value = &lt;span class="str"&gt;"LdapMember"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipNameAttr)
        
        $membershipTypeAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"type"&lt;/span&gt;)        
        $membershipTypeAttr.Value = &lt;span class="str"&gt;"Microsoft.Office.Server.Security.LdapMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipTypeAttr)
        
        
        $membershipServerAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"server"&lt;/span&gt;)
        $membershipServerAttr.Value = $ldapServer
        $membershipAddNode.Attributes.Append($membershipServerAttr)

        $membershipPortAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"port"&lt;/span&gt;)
        $membershipPortAttr.Value = &lt;span class="str"&gt;"389"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipPortAttr)
        
        $membershipuseSSLAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"useSSL"&lt;/span&gt;)
        $membershipuseSSLAttr.Value = &lt;span class="str"&gt;"false"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipuseSSLAttr)

        $membershipuserDNAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userDNAttribute"&lt;/span&gt;)
        $membershipuserDNAttribute.Value = &lt;span class="str"&gt;"distinguishedName"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipuserDNAttribute)
        
        $membershipuserNameAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userNameAttribute"&lt;/span&gt;)
        $membershipuserNameAttribute.Value = &lt;span class="str"&gt;"sAMAccountName"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipuserNameAttribute)
        
        
        $membershipuserContainer = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userContainer"&lt;/span&gt;)
        $membershipuserContainer.Value = $userContainer
        $membershipAddNode.Attributes.Append($membershipuserContainer)
              
        $membershipuserObjectClass = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userObjectClass"&lt;/span&gt;)
        $membershipuserObjectClass.Value = &lt;span class="str"&gt;"person"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipuserObjectClass)
        

        $membershipuserFilter = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userFilter"&lt;/span&gt;)
        $membershipuserFilter.Value = $userFilter
        $membershipAddNode.Attributes.Append($membershipuserFilter)

        $membershipScope = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"scope"&lt;/span&gt;)
        $membershipScope.Value = &lt;span class="str"&gt;"Subtree"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipScope)
        
        $membershipotherRequiredUserAttributes = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"otherRequiredUserAttributes"&lt;/span&gt;)
        $membershipotherRequiredUserAttributes.Value = &lt;span class="str"&gt;"sn,givenname,cn"&lt;/span&gt;
        $membershipAddNode.Attributes.Append($membershipotherRequiredUserAttributes)
        
        $providerNode.AppendChild($membershipAddNode)

    }
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; AddRoles($xmlDoc, $ldapServer, $userContainer, $userFilter, $groupFilter)
{
    &lt;span class="rem"&gt;#Check to see if it was already created, and if not, create it&lt;/span&gt;
    $rolesAddNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager/providers/add[@name='LdapRole']"&lt;/span&gt;)
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$rolesAddNode)
    {
        $rolesNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager"&lt;/span&gt;)
        $providerNode = $null
        
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$rolesNode)
        {
            $rolesNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;, &lt;span class="str"&gt;"roleManager"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;)        
            $providerNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"providers"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
            $rolesNode.AppendChild($providerNode)
            $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web"&lt;/span&gt;).AppendChild($rolesNode)                
        }
        $rolesNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager"&lt;/span&gt;)
        $rolesEnabledAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"enabled"&lt;/span&gt;);
        $rolesEnabledAttr.Value = &lt;span class="str"&gt;"true"&lt;/span&gt;;
        $rolesNode.Attributes.Append($rolesEnabledAttr)
        
        $providerNode = $xmlDoc.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager/providers"&lt;/span&gt;)
        $rolesAddNode = $xmlDoc.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"add"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
        
        $roleNameAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"name"&lt;/span&gt;)
        $roleNameAttr.Value = &lt;span class="str"&gt;"LdapRole"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($roleNameAttr)
        
        $roleTypeAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"type"&lt;/span&gt;)
        $roleTypeAttr.Value = &lt;span class="str"&gt;"Microsoft.Office.Server.Security.LdapRoleProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($roleTypeAttr)

        
        $rolesserverAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"server"&lt;/span&gt;)
        $rolesserverAttr.Value = $ldapServer
        $rolesAddNode.Attributes.Append($rolesserverAttr)

        $rolesPortAttr = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"port"&lt;/span&gt;)
        $rolesPortAttr.Value = &lt;span class="str"&gt;"389"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesPortAttr)
        
        $rolesuseSSL = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"useSSL"&lt;/span&gt;)
        $rolesuseSSL.Value = &lt;span class="str"&gt;"false"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesuseSSL)
        
        
        $rolesgroupContainer = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"groupContainer"&lt;/span&gt;)
        $rolesgroupContainer.Value = $userContainer
        $rolesAddNode.Attributes.Append($rolesgroupContainer)        

        $rolesgroupNameAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"groupNameAttribute"&lt;/span&gt;)
        $rolesgroupNameAttribute.Value = &lt;span class="str"&gt;"cn"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesgroupNameAttribute)           

        $rolesgroupNameAlternateSearchAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"groupNameAlternateSearchAttribute"&lt;/span&gt;)
        $rolesgroupNameAlternateSearchAttribute.Value = &lt;span class="str"&gt;"samAccountName"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesgroupNameAlternateSearchAttribute)    
        
        $rolesgroupMemberAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"groupMemberAttribute"&lt;/span&gt;)
        $rolesgroupMemberAttribute.Value = &lt;span class="str"&gt;"member"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesgroupMemberAttribute)    
                
                
        $rolesuserNameAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userNameAttribute"&lt;/span&gt;)
        $rolesuserNameAttribute.Value = &lt;span class="str"&gt;"sAMAccountName"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesuserNameAttribute)    
        
        $rolesdnAttribute = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"dnAttribute"&lt;/span&gt;)
        $rolesdnAttribute.Value = &lt;span class="str"&gt;"distinguishedName"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesdnAttribute)            


        $rolesgroupFilter = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"groupFilter"&lt;/span&gt;)
        $rolesgroupFilter.Value = $groupFilter
        $rolesAddNode.Attributes.Append($rolesgroupFilter)     
                                
        $rolesuserFilter = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"userFilter"&lt;/span&gt;)
        $rolesuserFilter.Value = $userFilter
        $rolesAddNode.Attributes.Append($rolesuserFilter)    

        $rolesscope = $xmlDoc.CreateAttribute(&lt;span class="str"&gt;"scope"&lt;/span&gt;)
        $rolesscope.Value = &lt;span class="str"&gt;"Subtree"&lt;/span&gt;
        $rolesAddNode.Attributes.Append($rolesscope)    
                                        
                                        
        $providerNode.AppendChild($rolesAddNode)
    }
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; ProcessCentralAdmin($path, $ldapServer, $userContainer)
{

    $content = Get-Content -Path $path
    [System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
    $xd.LoadXml($content)

    CreateBackupFile $xd $path
    

    
    &lt;span class="rem"&gt;#Add People Picker Wildcard&lt;/span&gt;
    AddPeoplePickerWildcard $xd
    
    &lt;span class="rem"&gt;#Add Roles&lt;/span&gt;
    AddRoles $xd $ldapServer $userContainer &lt;span class="str"&gt;"((ObjectClass=person)"&lt;/span&gt; &lt;span class="str"&gt;"((ObjectClass=group)"&lt;/span&gt;
    $roleNode = $xd.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager"&lt;/span&gt;)
    $defaultRoleProviderAttr = $xd.CreateAttribute(&lt;span class="str"&gt;"defaultProvider"&lt;/span&gt;)
    $defaultRoleProviderAttr.Value = &lt;span class="str"&gt;"AspNetWindowsTokenRoleProvider"&lt;/span&gt;
    $roleNode.Attributes.Append($defaultRoleProviderAttr)
            
    &lt;span class="rem"&gt;#Add Membership&lt;/span&gt;
    AddMembership $xd $ldapServer $userContainer &lt;span class="str"&gt;"(ObjectClass=person)"&lt;/span&gt;
    
    $membershipNode = $xd.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/membership"&lt;/span&gt;)
    $defaultMembershipProviderAttr = $xd.CreateAttribute(&lt;span class="str"&gt;"defaultProvider"&lt;/span&gt;)
    $defaultMembershipProviderAttr.Value = &lt;span class="str"&gt;"LdapMember"&lt;/span&gt;
    $membershipNode.Attributes.Append($defaultMembershipProviderAttr)        
       
    $xd.Save($path)
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; ProcessWebApplication($path, $ldapServer, $userContainer)
{
    $content = Get-Content -Path $path
    [System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
    $xd.LoadXml($content)

    CreateBackupFile $xd $path  

    
    &lt;span class="rem"&gt;#Add People Picker Wildcard&lt;/span&gt;
    AddPeoplePickerWildcard $xd
            
    &lt;span class="rem"&gt;#Add Membership&lt;/span&gt;
    AddMembership $xd $ldapServer $userContainer &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=person))"&lt;/span&gt;
    
    &lt;span class="rem"&gt;#Add Roles&lt;/span&gt;
    AddRoles $xd $ldapServer $userContainer &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=person))"&lt;/span&gt; &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=group))"&lt;/span&gt;
    
    $xd.Save($path)
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; ProcessSTS($path, $ldapServer, $userContainer)
{
    $content = Get-Content -Path $path
    [System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
    $xd.LoadXml($content)
    
    CreateBackupFile $xd $path
       
    
    &lt;span class="rem"&gt;#People picker wildcard is not necessary in STS config&lt;/span&gt;
            
    &lt;span class="rem"&gt;#Check to see if the system.web element exists, and if not, create it &lt;/span&gt;
    $sysWebNode = $xd.SelectSingleNode(&lt;span class="str"&gt;"/configuration[system.web]"&lt;/span&gt;)
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(!$sysWebNode)
    {
        $config = $xd.SelectSingleNode(&lt;span class="str"&gt;"/configuration"&lt;/span&gt;);
        $sysWebNode = $xd.CreateNode(&lt;span class="str"&gt;"element"&lt;/span&gt;,&lt;span class="str"&gt;"system.web"&lt;/span&gt;,&lt;span class="str"&gt;""&lt;/span&gt;)
        $config.AppendChild($sysWebNode)
    }
    
    &lt;span class="rem"&gt;#Add Membership&lt;/span&gt;
    AddMembership $xd $ldapServer $userContainer &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=person))"&lt;/span&gt;
    
    &lt;span class="rem"&gt;#Set LdapMember as default in STS&lt;/span&gt;
    $membershipNode = $xd.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/membership"&lt;/span&gt;)
    $defaultMembershipProviderAttr = $xd.CreateAttribute(&lt;span class="str"&gt;"defaultProvider"&lt;/span&gt;)
    $defaultMembershipProviderAttr.Value = &lt;span class="str"&gt;"LdapMember"&lt;/span&gt;
    $membershipNode.Attributes.Append($defaultMembershipProviderAttr)        
    
    &lt;span class="rem"&gt;#Add Roles&lt;/span&gt;
    AddRoles $xd $ldapServer $userContainer &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=person))"&lt;/span&gt; &lt;span class="str"&gt;"(&amp;amp;(ObjectClass=group))"&lt;/span&gt;
    
    &lt;span class="rem"&gt;#Set LdapRole as default in STS&lt;/span&gt;
    $roleNode = $xd.selectSingleNode(&lt;span class="str"&gt;"/configuration/system.web/roleManager"&lt;/span&gt;)
    $defaultRoleProviderAttr = $xd.CreateAttribute(&lt;span class="str"&gt;"defaultProvider"&lt;/span&gt;)
    $defaultRoleProviderAttr.Value = &lt;span class="str"&gt;"LdapRole"&lt;/span&gt;
    $roleNode.Attributes.Append($defaultRoleProviderAttr)

    $xd.Save($path)
}

&lt;span class="kwrd"&gt;function&lt;/span&gt; Main($pathToWebApplicationConfig, $pathToCentralAdminConfig, $ldapServer, $userContainer)
{
    $servers = Get-SPServer | ?{$_.Role &lt;span class="preproc"&gt;-eq&lt;/span&gt; &lt;span class="str"&gt;"Application"&lt;/span&gt;}
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt;($server &lt;span class="kwrd"&gt;in&lt;/span&gt; $servers)
    {
        $name = $server.Name
                        
        $webAppConfigPath = $pathToWebApplicationConfig.ToLower().Replace(&lt;span class="str"&gt;"c:\", "&lt;/span&gt;\\$name\c$\&lt;span class="str"&gt;") &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $centralAdminConfigPath = $pathToCentralAdminConfig.ToLower().Replace("&lt;/span&gt;c:\&lt;span class="str"&gt;", "&lt;/span&gt;\\$name\c$\&lt;span class="str"&gt;") &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $stsConfigPath = "&lt;/span&gt;\\$name\c$\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebServices\SecurityToken\web.config&lt;span class="str"&gt;" &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProcessWebApplication $webAppConfigPath $ldapServer $userContainer &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(Test-Path $centralAdminConfigPath) &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProcessCentralAdmin $centralAdminConfigPath $ldapServer $userContainer &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ProcessSTS $stsConfigPath $ldapServer $userContainer &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;} &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;#Update with path to Central Administration web.config &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;$pathToCentralAdminConfig = "&lt;/span&gt;c:\inetpub\wwwroot\wss\VirtualDirectories\37552\web.config&lt;span class="str"&gt;" &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;#Update with path to web application's web.config &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;$pathToWebApplicationConfig = "&lt;/span&gt;c:\inetpub\wwwroot\wss\VirtualDirectories\DevTeam.Contoso.lab80\web.config&lt;span class="str"&gt;" &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;#Update with the correct LDAP server &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;$ldapServer = "&lt;/span&gt;dc.contoso.lab&lt;span class="str"&gt;" &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;#Update with the correct container name &lt;/span&gt;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;$userContainer = "&lt;/span&gt;OU=EMPLOYEES,DC=CONTOSO,DC=LAB"



Main $pathToWebApplicationConfig $pathToCentralAdminConfig $ldapServer $userContainer
&lt;/pre&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s it!&amp;nbsp; I have used this several times in my test environment and it seems to work for either an existing or new environment, but you&amp;rsquo;ll want to test to make sure any assumptions I make in the script about availability of elements are accurate.&amp;nbsp;&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;For More Information&lt;/h2&gt;
&lt;p&gt;&lt;a title="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx" href="http://technet.microsoft.com/en-us/library/ee806890(office.14).aspx"&gt;Configure forms-based authentication for a claims-based Web application (SharePoint Server 2010)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a title="http://sharepointchick.com/archive/2010/05/06/configuring-claims-and-forms-based-authentication-for-use-with-an.aspx" href="http://sharepointchick.com/archive/2010/05/06/configuring-claims-and-forms-based-authentication-for-use-with-an.aspx"&gt;Configuring claims and forms based authentication for use with an LDAP provider in SharePoint 2010&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10390023" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-39-00-23/Update_2D00_ConfigWithLdapFBA.zip" length="2623" type="application/zip" /><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Security/">Security</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/PowerShell/">PowerShell</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Active+Directory/">Active Directory</category></item><item><title>Enable Exchange Mailboxes for All Users in an OU</title><link>http://blogs.msdn.com/b/kaevans/archive/2013/01/23/enable-exchange-mailboxes-for-all-users-in-an-ou.aspx</link><pubDate>Wed, 23 Jan 2013 23:06:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10387742</guid><dc:creator>Kirk Evans[MSFT]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/kaevans/rsscomments.aspx?WeblogPostID=10387742</wfw:commentRss><comments>http://blogs.msdn.com/b/kaevans/archive/2013/01/23/enable-exchange-mailboxes-for-all-users-in-an-ou.aspx#comments</comments><description>&lt;p&gt;This is more of a note to myself than anything, but what the heck, why not share it with everyone else?&lt;/p&gt;  &lt;p&gt;I frequently build new SharePoint farms for development and testing, and I usually create a new domain controller and populate it with users.&amp;#160; One of my favorite scripts is by Mark Rhodes, “&lt;a href="http://mrhodes.net/2011/10/25/adding-285-contoso-users-with-pictures-to-your-development-environment-active-directory/"&gt;Adding 285 Contoso Users with Pictures to your Development Environment Active Directory&lt;/a&gt;”.&amp;#160; The result is just as the title indicates:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/3817.image_5F00_2BFA5B64.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/6457.image_5F00_thumb_5F00_597B7B27.png" width="244" height="142" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Much less frequently I set up Exchange in the environment as well.&amp;#160; Usually I add the users with Mark’s script first, and then at some point later I install Exchange.&amp;#160; The problem is that now I have 285 users in the Employees OU that I want to have mailboxes, but I certainly don’t want to create them by hand.&amp;#160; Further, I don’t want the users in the Users container to have mailboxes.&amp;#160; The result?&amp;#160; A little PowerShell.&lt;/p&gt;  &lt;p&gt;Open the Exchange Management Shell, which opens an instance of PowerShell.&amp;#160; Next, use the following PowerShell (substituting, of course, your searchBase parameter.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;   &lt;pre class="csharpcode"&gt;Import-module activedirectory

$users = Get-ADUser -LDAPfilter &lt;span class="str"&gt;'(name=*)'&lt;/span&gt; -searchBase {OU=Employees,DC=contoso,DC=lab} 
&lt;span class="kwrd"&gt;foreach&lt;/span&gt;($user &lt;span class="kwrd"&gt;in&lt;/span&gt; $users)
{
   Enable-Mailbox -Identity $user.SamAccountName
}
  &lt;/pre&gt;
  That script will iterate through the users, filtered by the OU that you want using the searchBase parameter.&amp;#160; I am sure there is room for improvement here, but it works in my lab!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7534.image_5F00_720B1877.png"&gt;&lt;img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-25-31-metablogapi/7140.image_5F00_thumb_5F00_5183D8C5.png" width="244" height="100" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10387742" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/SharePoint/">SharePoint</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/PowerShell/">PowerShell</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Active+Directory/">Active Directory</category><category domain="http://blogs.msdn.com/b/kaevans/archive/tags/Exchange/">Exchange</category></item></channel></rss>