{"id":249,"date":"2013-01-22T08:34:00","date_gmt":"2013-01-22T17:34:00","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/2013\/01\/22\/group-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps-4\/"},"modified":"2013-03-14T19:58:49","modified_gmt":"2013-03-15T04:58:49","slug":"group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/01\/22\/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps\/","title":{"rendered":"Group &amp; Role Claims: Use the Graph API to Get Back IsInRole() and [Authorize] in Windows Azure AD Apps"},"content":{"rendered":"<p>Welcome to a new installment of the \u201caddressing the most common questions about Windows Azure AD development\u201d series! This time I am going to tackle one question that I know is very pressing for many of you guys:<\/p>\n<p align=\"center\"><em>How do I get role and group membership claims for users signing in via Windows Azure AD?<\/em>&#160; <\/p>\n<p>Right now the tokens issued by Windows Azure AD in Web sign-on flows do not contain groups or role claims. In this post I will show you how to leverage the Graph API and the WIF extensibility model to work around the limitation; I will also take advantage of this opportunity to go a bit deeper in the use of the Graph API, which means that the post will be longer (and at times more abstract) than a simple code walkthrough. As usual, those are my personal musings and my own opinions. I am writing this on a Saturday night (morning?) hence I plan to have fun with this \ud83d\ude42 For the ones among you who are in a hurry or have low tolerance for logorrhea, please feel free to head to the product documentation on MSDN. <\/p>\n<h1>Bird\u2019s Eye View of the Solution<\/h1>\n<p>Most pre-claims authorization constructs in ASP.NET are based on the idea of roles baked in IPrincipal: namely, I am thinking of the &lt;authorization&gt; config element, the [Authorize] attribute and of course the IsInRole() method. There\u2019s an enormous amount of existing code based on those primitives, and abundant literature using those as the backbone of authorization enforcement in .NET applications.    <br \/>This state of affair was well known to the designer of the original WIF 1.0, who provided mechanisms for projecting claims with the appropriate semantic (and specifically <a href=\"http:\/\/schemas.microsoft.com\/ws\/2008\/06\/identity\/claims\/role\">http:\/\/schemas.microsoft.com\/ws\/2008\/06\/identity\/claims\/role<\/a>) as roles in IPrincipal. We even have <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh568648.aspx\">a mechanism<\/a> which allows you to specify in config a different, arbitrary claim type&#160; to be interpreted as role, should your STS use a different claim type to express roles.<\/p>\n<p>As mentioned in the opening, right now Windows Azure AD does not send anything that can be interpreted as a role claim. The good news, however, is that Windows Azure AD offers the Graph API, a complete API for querying the directory and retrieve any information stored there, for any user; that includes the signed-in user, of course, and the roles he\/she belongs to. If you need to know what roles your user is in, all you need to do (over-simplifying a bit, for now) is to perform a GET on a resource of the form <a title=\"https:\/\/graph.windows.net\/{0}\/Users(&#039;{1}&#039;)\/MemberOf\" href=\"mailto:'guido@yourtenantname.onmicrosoft.com')\/MemberOf\">https:\/\/graph.windows.net\/yourtenant.onmicrosoft.com\/Users(&#8216;guido@yourtenantname.onmicrosoft.com&#8217;)\/MemberOf<\/a>. That is pretty sweet, and in fact is just a ridiculously tiny sliver of all the great things you can do with the Graph API; however, if you\u2019d do this from your application code that would not help you to leverage the user\u2019s role information from &lt;authorization&gt; and the like. When you are in your application\u2019s code is kind of too late, as the ClaimsPrincipal representing the caller has already been assembled and that\u2019s where the info should be for those lower-level mechanisms to kick in. True, you could do something to the ClaimsPrincipal retroactively, but that\u2019s kind of brittle and messy.<\/p>\n<p>There is another solution here, which can save both goat and cabbage (can you really say this in English?:-)). The WIF processing pipeline offers plenty of opportunities for you to insert custom logic for influencing how the token validation and ClaimsPrincipal creation takes place: details in Chapter 3 of <a href=\"http:\/\/www.amazon.com\/Programming-Windows-Identity-Foundation-Dev\/dp\/0735627185\/\">Programming WIF<\/a>. Namely, there is one processing stage that is dedicated to incoming claims processing. Say that you have logic for filtering incoming claims, modifying them or extending the claims set you are getting from the STS with data from other sources. All you need to do is to derive from the ClaimsAuthenticationManager class, override the Authenticate method and add a reference to your custom class in the application\u2019s config.     <br \/>So, the solution I propose is simple: we can create a custom ClaimsAuthenticationManager that at sign-in time reaches back to the Graph, retrieves the roles information, creates roles claims accordingly and adds them to the ClaimsPrincipal. Everything else downstream from that will be able to see the roles information just like if they would have been originally issued by the STS.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3618.image_5F00_61B0D80F.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3618.image_5F00_61B0D80F.png\" width=\"550\" height=\"315\" \/><\/a> <\/p>\n<p>The code of custom ClaimsAuthenticationManager is going to be pretty simple, also thanks to the use of AAL for obtaining the necessary access token: just a tad more than 30 lines, and most of it string manipulation. In my experience, the thing that people often find tricky is the work that is necessary for enabling your Web application to invoke the Graph; furthermore, even if AAL reduces to a mere 3 the lines of code necessary for obtaining an access token, the structure of the parameters you need to pass is not always immediately clear to everybody. Here I\u2019ll do my best to explain both: they are not especially hard and I am confident you\u2019ll grok it right away. That said, I do hope we\u2019ll manage to automate A LOT of this so that in the future you won\u2019t be exposed to this complexity unless you want to change the defaults. We kind of already do this for the Web SSO part, if you use the <a href=\"http:\/\/www.asp.net\/vnext\/overview\/fall-2012-update\/windows-azure-authentication\">MVC tool<\/a> you can get a functioning MVC4 app which uses Windows Azure AD for Web SSO in no time. In fact, in this post I\u2019ll use such an app as starting point.<\/p>\n<p>Ready? Let\u2019s dive.<\/p>\n<h1>Prepping the GraphClaimsAuthenticationManager Wireframe<\/h1>\n<p>Let\u2019s get this immediately out of the way; also, it will provide structure for the rest of the work.<\/p>\n<p>As mentioned, I assume you already have an MVC4 app that you configured with the MVC tool to integrate with your Windows Azure AD tenant for sign-in. If you didn\u2019t do it yet, please head to <a href=\"http:\/\/www.asp.net\/vnext\/overview\/fall-2012-update\/windows-azure-authentication\">this page<\/a> now and follow the instructions for configuring your application. You can skip the publication to Windows Azure Web Sites, for this post we\u2019ll be able to do everything on the local box. If you want to see the tool in action, <a href=\"http:\/\/channel9.msdn.com\/Events\/Build\/2012\/3-042\">check out this BUILD talk<\/a>.     <br \/>Create a new class library (though you could just add a class to your web project) and call it something meaningful: I called mine <strong>GraphClaimsAuthenticationManager<\/strong>.     <br \/>Add a reference to System.IdentityModel, rename the class1.cs file to GraphClaimsAuthenticationManager.cs, then change the code as follows:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> GraphClaimsAuthenticationManager : ClaimsAuthenticationManager<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>{<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>   <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">override<\/span> ClaimsPrincipal <\/pre>\n<pre>            Authenticate(<span class=\"kwrd\">string<\/span> resourceName, ClaimsPrincipal incomingPrincipal)<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>   {<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>      <span class=\"kwrd\">if<\/span> (incomingPrincipal != <span class=\"kwrd\">null<\/span> &amp;&amp; <\/pre>\n<pre>                 incomingPrincipal.Identity.IsAuthenticated == <span class=\"kwrd\">true<\/span>)<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>      {                              <\/pre>\n<pre><span class=\"lnum\">   7:  <\/span>          <span class=\"rem\">\/\/ get a token for calling the Graph<\/span><\/pre>\n<pre><span class=\"lnum\">   8:  <\/span>                      <\/pre>\n<pre><span class=\"lnum\">   9:  <\/span>          <span class=\"rem\">\/\/ query the Graph for the current user's memberships<\/span><\/pre>\n<pre><span class=\"lnum\">  10:  <\/span>             <\/pre>\n<pre><span class=\"lnum\">  11:  <\/span>          <span class=\"rem\">\/\/ add a role claim for every membership found<\/span><\/pre>\n<pre><span class=\"lnum\">  12:  <\/span>&#160;<\/pre>\n<pre><span class=\"lnum\">  13:  <\/span>       }<\/pre>\n<pre><span class=\"lnum\">  14:  <\/span>       <span class=\"kwrd\">return<\/span> incomingPrincipal;<\/pre>\n<pre><span class=\"lnum\">  15:  <\/span>   }        <\/pre>\n<pre><span class=\"lnum\">  16:  <\/span>}<\/pre>\n<\/div>\n<p>This is pretty much the default ClaimsAuthenticationManager implementation: it passes through all the incoming claims to the next stage undisturbed. Our job will be to fill in the method\u2019s body following the comment placeholders I wrote there. You can make your application pick up and execute your class by adding a reference to the class library project and inseriting the proper config element to the web.config, as shown below (sci-fi formatting, you would not break strings IRL).<\/p>\n<pre class=\"csharpcode\"> <span class=\"kwrd\">&lt;<\/span><span class=\"html\">system.identityModel<\/span><span class=\"kwrd\">&gt;<\/span>\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">identityConfiguration<\/span><span class=\"kwrd\">&gt;<\/span>\n      <span class=\"kwrd\">&lt;<\/span><span class=\"html\">claimsAuthenticationManager<\/span> <br \/><span class=\"attr\">        type<\/span><span class=\"kwrd\">=&quot;GraphClaimsAuthenticationManager.GraphClaimsAuthenticationManager, <br \/>              GraphClaimsAuthenticationManager&quot;<\/span> <span class=\"kwrd\">\/&gt;<\/span><\/pre>\n<p>I\u2019d suggest hitting F5 and see if everything still works, often something silly like misspelled namespaces in the type attribute will create stumble points and you want to catch that before there will be more moving parts later on.<\/p>\n<h1>Enabling An MVC App to Invoke the Graph API<\/h1>\n<p>Alrighty, now for the first interesting part.<\/p>\n<p>The next thing we need to do is enabling your MVC application to call back into the Graph and inquiry about the user\u2019s roles. But in order to do that, we first need to understand how our MVC application is represented in Windows Azure AD and what do we need to change.<\/p>\n<p>When you run the <a href=\"http:\/\/www.asp.net\/vnext\/overview\/fall-2012-update\/windows-azure-authentication\">MVC tool<\/a> for enabling Windows Azure authentication you are basically getting lots of the steps I described <a href=\"http:\/\/blogs.msdn.com\/b\/vbertocci\/archive\/2012\/07\/12\/single-sign-on-with-windows-azure-active-directory-a-deep-dive.aspx\">here<\/a> done for you. As a quick recap, the tool<\/p>\n<ul>\n<li>asks you which directory tenant you want to work with<\/li>\n<li>gathers your admin credentials and uses them to get an access token for the Graph API<\/li>\n<li>Invokes the Graph to create a new ServicePrincipal representing your MVC app. It does so by generating a new random GUID as identifier, assigning your local IIS express and project address as return URL, and so on<\/li>\n<li>Reaches out for the WS-Federation metadata document of the tenant you have chosen, and uses it to generate the necessary WIF settings to configure your app for Windows Azure SSO with the tenant of choice<\/li>\n<\/ul>\n<p>\u2026and that\u2019s what enables you to hit F5 right after the wizard and see the SSO flow unfold in front of your very eyes, without the need of writing any code. Veeery nice.<br \/>\n  <br \/>Now, from the above you might be tempted to think that a ServicePrincipal is the equivalent of a RP role in ACS: an entry which represents an entity meant to be a token <em>recipient<\/em>. In fact, a ServicePrincipal can represent more roles than a simple RP: for example, an ServicePrincipal can also represent an applicative identity, with its own associated credential, whihc can be used for <em>obtaining<\/em> a token to be used somewhere else. Remember ACS\u2019 service identities? That\u2019s kind of the same thing.<\/p>\n<p>I guess you are starting to figure out what\u2019s the plan here. We want to use the app\u2019s ServicePrincipal credentials (in trusted subsystem fashion) to obtain a token for calling the Graph. That\u2019s a fine plan, but it cannot be implemented without a bit more work. Namely:<\/p>\n<ul>\n<li>The MVC tool does not do anything the ServicePrincipal\u2019s credentials. We must get to know them, and the only way after creation is to assign new ones. We\u2019ll do that by updating the existing ServicePrincipal via cmdlets<\/li>\n<li>Calling the Graph is a privilege reserved only to entities belonging to well known roles: Company Administrators for read\/write Directory Readers for read-only access. Needless to say, the ServicePrincipal created by the MVC tool belongs to neither. We\u2019ll use the cmdlets here as well to add the app\u2019s ServicePrincipal to the Directory Readers role. <\/li>\n<\/ul>\n<p>Luckily it\u2019s all pretty straightforward. The first thing we need to do is to retrieve a valid identifier for the ServicePrincipal, so that we can get a hold on it and modify it. That is pretty easy to do. Go to the app\u2019s web.config, in the &lt;system.identityModel&gt; sections, and you\u2019ll find the AppPrincipalId GUID in multiple places: in the identityConfiguration\/audienceUris or in the realm property of the system.identityModel.services\/federationConfiguration\/wsFederation element. Put it in the clipboard (without the \u201cSPN:\u201d!) and open the O365 PowerShell cmdlets prompt. Then, consider the following script. The formatting is all broken, of course: keep an eye on the line numbers for understanding where the actual line breaks are.<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><font color=\"#0080ff\">Connect-MsolService<\/font><\/pre>\n<pre><span class=\"lnum\">   2:  <\/span><font color=\"#0080ff\">Import-Module<\/font> msonlineextended -Force<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span><font color=\"#ff0000\">$AppPrincipalId<\/font> = <span class=\"str\">'62b4b0eb-ef3e-4c28-7777-2c7777776593'<\/span><\/pre>\n<pre><span class=\"lnum\">   4:  <\/span><font color=\"#ff0000\">$servicePrincipal<\/font> = <\/pre>\n<pre>          (<font color=\"#0080ff\">Get-MsolServicePrincipal<\/font> -AppPrincipalId <font color=\"#ff0000\">$AppPrincipalId<\/font>)<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span><font color=\"#0080ff\">Add-MsolRoleMember<\/font> -RoleMemberType <span class=\"str\">&quot;ServicePrincipal&quot;<\/span> <\/pre>\n<pre>                          -RoleName <span class=\"str\">&quot;Directory Readers&quot;<\/span> <\/pre>\n<pre>                          -RoleMemberObjectId <font color=\"#ff0000\">$servicePrincipal<\/font>.ObjectId<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>&#160;<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span><font color=\"#ff0000\">$timeNow<\/font> = <font color=\"#0080ff\">Get-Date<\/font><\/pre>\n<pre><span class=\"lnum\">   8:  <\/span><font color=\"#ff0000\">$expiryTime<\/font> = <font color=\"#ff0000\">$timeNow<\/font>.AddYears(1)<\/pre>\n<pre><span class=\"lnum\">   9:  <\/span><font color=\"#0080ff\">New-MsolServicePrincipalCredential<\/font> <\/pre>\n<pre>                   -AppPrincipalId <font color=\"#ff0000\">$AppPrincipalId<\/font> <\/pre>\n<pre>                   -Type symmetric <\/pre>\n<pre>                   -StartDate <font color=\"#ff0000\">$timeNow<\/font> <\/pre>\n<pre>                   -EndDate <font color=\"#ff0000\">$expiryTime<\/font> <\/pre>\n<pre>                   -Usage Verify <\/pre>\n<pre>                   -Value AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\/Q8=<\/pre>\n<\/div>\n<p>&#160;<\/p>\n<p>Line by line:<\/p>\n<blockquote>\n<p>Line 1: connect to the tenant. You\u2019ll be prompted for your admin user, make sure you choose the same tenant you have used to configure the MVC app \ud83d\ude42<\/p>\n<p>Line 2: it imports the O365 cmdlets, and specifically the ones about ServicePrincipals. The \u201cforce\u201d flag is mandatory on Win8 boxes.<\/p>\n<p>Line 3: I assign the AppPrincipalId from the web.config so I don\u2019t have to paste it every time.<\/p>\n<p>Line 4: retrieve the ServicePrincipal<\/p>\n<p>Line 5: add it to the \u201cDirectory Readers\u201d role<\/p>\n<p>Lines 7 and 8: get the current date and the date one year from now, to establish the valitity bopundaries of the credentials we are going to assign to the ServicePrincipal<\/p>\n<p>Line 9: create a new ServicePrincipalCredential of type symmetric key (there are other flavors, like certificate based creds) and assign it to the app\u2019s ServicePrincipal<\/p>\n<\/blockquote>\n<p>Simple, right? Well, I have to thank <strong>Mugdha Kulkarni<\/strong> from the Graph team for this script. She wrote it for me while I was prepping for the BUILD talk, though in the end I decided I didn\u2019t have enough time to show it on stage. Thank you Mugdha, told you this was going to come in handy! \ud83d\ude09<\/p>\n<p>Anyway, we\u2019ve done our first task: our app has now the right to invoke the Graph. Let\u2019s get back to the GraphClaimsAuthenticationManager and write some code to exercise that right.<\/p>\n<h1>Using AAL to Obtain an Access Token for the Graph API<\/h1>\n<p>Get back to VS and paste the following at the beginning of the if block in the Authenticate method:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"kwrd\">string<\/span> appPrincipalID = <span class=\"str\">&quot;62b4b0eb-ef3e-4c28-7777-2c7777776593&quot;<\/span>;<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span><span class=\"kwrd\">string<\/span> appKey = <span class=\"str\">&quot;AAAAAAAAAAAAAAAAAAAAAAAAAAAA\/Q8=&quot;<\/span>;<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>&#160;<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span><span class=\"kwrd\">string<\/span> upn = incomingPrincipal.FindFirst(<\/pre>\n<pre>              <span class=\"str\">&quot;http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/upn&quot;<\/span>).Value;<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span><span class=\"kwrd\">string<\/span> tenantID = incomingPrincipal.FindFirst(<\/pre>\n<pre>              <span class=\"str\">&quot;http:\/\/schemas.microsoft.com\/ws\/2012\/10\/identity\/claims\/tenantid&quot;<\/span>).Value;<\/pre>\n<\/div>\n<p>That is pretty scrappy code, I\u2019ll readily admit. The first 2 lines hold the app\u2019s ServicePrincipal id and key, respectively. I could have retrieved it from the config, but if I do everything how are you going to have fun? \ud83d\ude09<br \/>\n  <br \/>The next 2 lines retrieve the UPN of the incoming user (<a href=\"mailto:&ldquo;username@domain\">\u201cusername@domain<\/a>\u201d) and the ID of the directory tenant from where he\/she is coming from, both very important values for crafting our query.<\/p>\n<table cellspacing=\"0\" cellpadding=\"2\" width=\"100%\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"100%\"><strong><font color=\"#ff0000\">VERY IMPORTANT<\/font><\/strong> especially for you Observers landing on this post from the future (aren\u2019t you sad that Fringe ended? Luckily the finale wasn\u2019t terrible). <\/p>\n<p>The claims used above are the claims from Windows Azure AD available TODAY. Those claims are very likely to change, hence the above will no longer be valid either because the claim types will no longer be there or more appropriate alternatives will emerge.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Next, we are going to inject the ServicePrincipal credentials in AAL and obtain a token for calling the Graph. As mentioned, this requires just few lines but the parameters are a bit arcane. Bear with me as I walk you though their function and meaning. Also, don\u2019t forget to add a reference to the AAL NuGet and associated using! You can do that by right-clicking on the GraphClaimsAuthenticaitonManager in solution explorer, choose Manage NuGet Packages, search for <strong>AAL<\/strong> and reference the result.<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"rem\">\/\/ get a token for calling the graph<\/span><\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>AuthenticationContext _authContext = <\/pre>\n<pre>          <span class=\"kwrd\">new<\/span> AuthenticationContext(<\/pre>\n<pre>              <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\"><a href=\"https:\/\/accounts.accesscontrol.windows.net\/{0}\">https:\/\/accounts.accesscontrol.windows.net\/{0}<\/a><\/span>, <\/pre>\n<pre>                            tenantID));<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>SymmetricKeyCredential credential = <\/pre>\n<pre>          <span class=\"kwrd\">new<\/span> SymmetricKeyCredential(<\/pre>\n<pre>              <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\">&quot;{0}@{1}&quot;<\/span>,appPrincipalID,tenantID),<\/pre>\n<pre>              Convert.FromBase64String(appKey));<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>AssertionCredential _assertionCredential = <\/pre>\n<pre>         _authContext.AcquireToken(<\/pre>\n<pre>         <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\"><a href=\"mailto:00000002-0000-0000-c000-000000000000\/graph.windows.net@{0\">00000002-0000-0000-c000-000000000000\/graph.windows.net@{0}<\/a><\/span>, <\/pre>\n<pre>                       tenantID), <\/pre>\n<pre>         credential);<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span><span class=\"kwrd\">string<\/span> authHeader = _assertionCredential.CreateAuthorizationHeader();<\/pre>\n<\/div>\n<p>OK. Ready?<\/p>\n<blockquote>\n<p>Line 2: we begin by initializing AuthenticationContext to the Windows Azure AD tenant we want to work with. We\u2019ll use the AuthenticationContext for accessing from our code the features that Windows Azure AD offers. In order to do that, we simply pass the path of the Windows Azure AD tenant we want to work with.<\/p>\n<p>Line 3: we create a representation of the app\u2019s ServicePrincipal credentials, as an instance of the class SymmetricCredential. We do that by combining its symmetric key the ServicePrincipal name, obtained by combining the ServicePrincipal GUID (used as ServicePrincipalAppID in the cmdlet earlier) and the ID of the current tenant. The reason for which we need both the AppPrincipalId and the Tenant ID is that we want to make sure we specify we are referring to THIS principal in THIS tenant. If our app would be a multitenant app, designed to work with multiple AAD tenants, the same AppPrinciplaId would be (possibly) used across multiple tenants. we\u2019d need to ensure we are getting a token for the right tenant, hence we qualify the name accordingly: <a href=\"mailto:appprincipalid@tenant1\">appprincipalid@tenant1<\/a>, <a href=\"mailto:appprincipalid@tenant2\">appprincipalid@tenant2<\/a> and so on. Here we are working on a single tenant hence there is no ambiguity, but we have to use that format anyway<\/p>\n<p>Line 4: we ask to the AuthenticationContext (hence to the directory tenant) to issue an access token for the Graph.<br \/>\n    <br \/>We need to prove who we are, hence we pass the credentials. Also, we need to specify for which resource we are asking a token for, hence the string.Format clause in the call. You see, the Graph is in itself a resource; and just like your app, it is represented with a ServicePrincipal. The string <span class=\"str\">00000002-0000-0000-c000-000000000000 <\/span>happens to be its AppPrincipalId, and <span class=\"str\"><a href=\"mailto:00000002-0000-0000-c000-000000000000\/graph.windows.net@%7B0\">graph.windows.net<\/a><\/span> is the hostname; qualify the two with the target tenantID and you&#8217; get the Graph ServicePrincipal name. <\/p>\n<p>Line 5: with this line we retrieve (from the results of the call to AcquireToken) the string containing the access token we need to call the Graph . The CreateAuthorizationHeader will simply put it in the form \u201cBearer &lt;token&gt;\u201d for us, less work when we\u2019ll put it in the HTTP header for the call.<\/p>\n<\/blockquote>\n<p>&#160;<\/p>\n<h1>Getting the Memberships and Enriching the Claims Collection of the Current Principal <\/h1>\n<p>A last effort and we\u2019ll be done with our GraphClaimsAuthenticationManager! I\u2019ll just put all the code there and intertwine the explanation of what\u2019s going on in the description of every line. Paste the code below right after the AAL code just described, still within the if block of the Authenticate method.<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span> <span class=\"rem\">\/\/ query the Graph for the current user's memberships<\/span><\/pre>\n<pre><span class=\"lnum\">   2:  <\/span><span class=\"kwrd\">string<\/span> requestUrl = <\/pre>\n<pre>         <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\"><a href=\"https:\/\/graph.windows.net\/{0}\/Users('{1}')\/MemberOf\">https:\/\/graph.windows.net\/{0}\/Users('{1}')\/MemberOf<\/a><\/span>, <\/pre>\n<pre>                       tenantID, upn);<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>HttpWebRequest webRequest = <\/pre>\n<pre>         WebRequest.Create(requestUrl) <span class=\"kwrd\">as<\/span> HttpWebRequest;<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>webRequest.Method = <span class=\"str\">&quot;GET&quot;<\/span>;<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>webRequest.Headers[<span class=\"str\">&quot;Authorization&quot;<\/span>] = authHeader;<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>webRequest.Headers[<span class=\"str\">&quot;x-ms-dirapi-data-contract-version&quot;<\/span>] = <span class=\"str\">&quot;0.8&quot;<\/span>;<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span><span class=\"kwrd\">string<\/span> jsonText;<\/pre>\n<pre><span class=\"lnum\">   8:  <\/span>var httpResponse = (HttpWebResponse)webRequest.GetResponse();<\/pre>\n<pre><span class=\"lnum\">   9:  <\/span><span class=\"kwrd\">using<\/span> (var streamReader = <\/pre>\n<pre>              <span class=\"kwrd\">new<\/span> StreamReader(httpResponse.GetResponseStream()))<\/pre>\n<pre><span class=\"lnum\">  10:  <\/span>{<\/pre>\n<pre><span class=\"lnum\">  11:  <\/span>     jsonText = streamReader.ReadToEnd();<\/pre>\n<pre><span class=\"lnum\">  12:  <\/span>}<\/pre>\n<pre><span class=\"lnum\">  13:  <\/span>JObject jsonResponse = JObject.Parse(jsonText);<\/pre>\n<pre><span class=\"lnum\">  14:  <\/span>var roles =<\/pre>\n<pre><span class=\"lnum\">  15:  <\/span>    from r <span class=\"kwrd\">in<\/span> jsonResponse[<span class=\"str\">&quot;d&quot;<\/span>][<span class=\"str\">&quot;results&quot;<\/span>].Children()<\/pre>\n<pre><span class=\"lnum\">  16:  <\/span>    select (<span class=\"kwrd\">string<\/span>)r[<span class=\"str\">&quot;DisplayName&quot;<\/span>];<\/pre>\n<pre><span class=\"lnum\">  17:  <\/span>&#160;<\/pre>\n<pre><span class=\"lnum\">  18:  <\/span><span class=\"rem\">\/\/ add a role claim for every membership found<\/span><\/pre>\n<pre><span class=\"lnum\">  19:  <\/span><span class=\"kwrd\">foreach<\/span>(<span class=\"kwrd\">string<\/span> s <span class=\"kwrd\">in<\/span> roles)<\/pre>\n<pre><span class=\"lnum\">  20:  <\/span>    ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(<\/pre>\n<pre>                <span class=\"kwrd\">new<\/span> Claim(ClaimTypes.Role, s, ClaimValueTypes.String, <span class=\"str\">&quot;GRAPH&quot;<\/span>));<\/pre>\n<\/div>\n<p>Line 1: we craft the URL representing the resource we want to obtain. We are using the OData query syntax, which happens to be very intuitive. I\u2019ll break this query down for you. Note that every element builds on its predecessors,<\/p>\n<table cellspacing=\"0\" cellpadding=\"2\" width=\"100%\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"30%\"><span class=\"str\"><a href=\"https:\/\/graph.windows.net\/%7B0%7D\/Users('%7B1%7D')\/MemberOf\">https:\/\/graph.windows.net\/<\/a><\/span><\/td>\n<td valign=\"top\" width=\"70%\">This indicates the Windows Azure feature we want to access. In this case, it is the Graph API: if we would have wanted to access a token issuing endpoint, or a metadata document, we would have used a different URL accordingly <\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"30%\">{tenantID}<\/td>\n<td valign=\"top\" width=\"70%\">This indicates which AAD tenant we want to query. Here I am using tenantID (a GUID) because it is pretty handy, i received it with the incoming claims; howeve I could have used the tenant domain (the cloud-managed ones are of the form \u2018tenantname.onmicrosoft.com\u2019) just as well <\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"30%\">\/Users<\/td>\n<td valign=\"top\" width=\"70%\"><strong>\/Users<\/strong> indicate the entity I want to GET. If I\u2019d stop the query here, I\u2019d get a collection of all the users in the tenant<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"30%\">(\u2018{upn}\u2019)<\/td>\n<td valign=\"top\" width=\"70%\">adding this element filters the users\u2019 list to select a specific entry, the one of the user that matches the corresponding UPN. Once again, the UPN is not the only way of identifying a user. Every entity in the directory has its (GUID) identifier, and if I would have access to it (the web sign on token did not carry it, but I could have gotten it as the result of a former query) I could use it as search key. In fact, that would even be more robust given that the UPN is non-immutable\u2026 though it is quite unlikely that a UPN would get reassigned during your session :-).<br \/>\n        <br \/>If we\u2019d stop the query here, we\u2019d get back a representation of the user matching our search key<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"30%\">\/MemberOf<\/td>\n<td valign=\"top\" width=\"70%\">assuming that the query so far produced a user: <strong>\/MemberOf<\/strong> returns all the roles and security groups the user belongs to.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p> Lines 3 and 4: standard HttpWebRequest initialization code. I guess I\u2019ll have to start using HttpClient soon, or Daniel will stop greeting me in the hallways \ud83d\ude09<\/p>\n<p>Line 5: we add the header with the access token we obtained earlier.<\/p>\n<p>Line 6: we add a well-known header, which specifies the version of the API we want to work with. This header is MANDATORY, no version no party.<\/p>\n<p>Line 7 to 12: standard request execution and deserialization of the response stream into a string. We expect this string to be filled with JSON containing the answer to our query.<br \/>\n  <br \/>We didn\u2019t finish the tutorial yet, hence at this point we should not be able to see what we are going to get a s a result, but I am going to cheat a little and give you a peek of a typical result of that query:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span>{<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>  <span class=\"str\">&quot;d&quot;<\/span>: {<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>    <span class=\"str\">&quot;results&quot;<\/span>: [<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>      {<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>        <span class=\"str\">&quot;__metadata&quot;<\/span>: {<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>          <span class=\"str\">&quot;id&quot;<\/span>: <span class=\"str\">&quot;https:\/\/graph.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/DirectoryObjects('Group_ce134d80-fa89-425a-8eb6-d64429b0ba58')&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span>          <span class=\"str\">&quot;uri&quot;<\/span>: <span class=\"str\">&quot;https:\/\/graph.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/DirectoryObjects('Group_ce134d80-fa89-425a-8eb6-d64429b0ba58')\/Microsoft.WindowsAzure.ActiveDirectory.ReferencedObject&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">   8:  <\/span>          <span class=\"str\">&quot;type&quot;<\/span>: <span class=\"str\">&quot;Microsoft.WindowsAzure.ActiveDirectory.ReferencedObject&quot;<\/span><\/pre>\n<pre><span class=\"lnum\">   9:  <\/span>        },<\/pre>\n<pre><span class=\"lnum\">  10:  <\/span>        <span class=\"str\">&quot;ObjectId&quot;<\/span>: <span class=\"str\">&quot;ce134d80-fa89-425a-8eb6-d64429b0ba58&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  11:  <\/span>        <span class=\"str\">&quot;ObjectReference&quot;<\/span>: <span class=\"str\">&quot;Group_ce134d80-fa89-425a-8eb6-d64429b0ba58&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  12:  <\/span>        <span class=\"str\">&quot;ObjectType&quot;<\/span>: <span class=\"str\">&quot;Group&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  13:  <\/span>        <span class=\"str\">&quot;DisplayName&quot;<\/span>: <span class=\"str\">&quot;Sales&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  14:  <\/span>        <span class=\"str\">&quot;Mail&quot;<\/span>: <span class=\"kwrd\">null<\/span><\/pre>\n<pre><span class=\"lnum\">  15:  <\/span>      },<\/pre>\n<pre><span class=\"lnum\">  16:  <\/span>      {<\/pre>\n<pre><span class=\"lnum\">  17:  <\/span>        <span class=\"str\">&quot;__metadata&quot;<\/span>: {<\/pre>\n<pre><span class=\"lnum\">  18:  <\/span>          <span class=\"str\">&quot;id&quot;<\/span>: <span class=\"str\">&quot;https:\/\/graph.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/DirectoryObjects('Role_fe930be7-5e62-47db-91af-98c3a49a38b1')&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  19:  <\/span>          <span class=\"str\">&quot;uri&quot;<\/span>: <span class=\"str\">&quot;https:\/\/graph.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/DirectoryObjects('Role_fe930be7-5e62-47db-91af-98c3a49a38b1')\/Microsoft.WindowsAzure.ActiveDirectory.ReferencedObject&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  20:  <\/span>          <span class=\"str\">&quot;type&quot;<\/span>: <span class=\"str\">&quot;Microsoft.WindowsAzure.ActiveDirectory.ReferencedObject&quot;<\/span><\/pre>\n<pre><span class=\"lnum\">  21:  <\/span>        },<\/pre>\n<pre><span class=\"lnum\">  22:  <\/span>        <span class=\"str\">&quot;ObjectId&quot;<\/span>: <span class=\"str\">&quot;fe930be7-5e62-47db-91af-98c3a49a38b1&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  23:  <\/span>        <span class=\"str\">&quot;ObjectReference&quot;<\/span>: <span class=\"str\">&quot;Role_fe930be7-5e62-47db-91af-98c3a49a38b1&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  24:  <\/span>        <span class=\"str\">&quot;ObjectType&quot;<\/span>: <span class=\"str\">&quot;Role&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  25:  <\/span>        <span class=\"str\">&quot;DisplayName&quot;<\/span>: <span class=\"str\">&quot;User Account Administrator&quot;<\/span>,<\/pre>\n<pre><span class=\"lnum\">  26:  <\/span>        <span class=\"str\">&quot;Mail&quot;<\/span>: <span class=\"kwrd\">null<\/span><\/pre>\n<pre><span class=\"lnum\">  27:  <\/span>      }<\/pre>\n<pre><span class=\"lnum\">  28:  <\/span>    ]<\/pre>\n<pre><span class=\"lnum\">  29:  <\/span>  }<\/pre>\n<pre><span class=\"lnum\">  30:  <\/span>}<\/pre>\n<\/div>\n<p>I didn\u2019t adjust the formatting this time to account for the msdn blog layout clipping: if you are curious to see it in its entirety feel free to select the text, copy it and paste it in notepad, but that\u2019s not required for understanding what I want to point out.<br \/>\n  <br \/>As you can see we are getting a couple of objects in our result set. One is the group \u201cSales\u201d, the other is the role \u201cUser Account Administrator\u201d: our user evidently belongs to both. The latter is one of the built-in roles, which define what the user can do in the context of AAD itself; the former is a custom security group, created by the AAD administrator. Both objects have their own IDs, which identify them unambiguously,<\/p>\n<p>Line 13 to 16: this is one of my favorite things as of late. ASP.NET includes a reference to JSON.NET, a great library from Newtonsoft which truly eats JSON for breakfast. Let\u2019s just say that, instead of going crazy to parse from C# the result string, I can just create a JObject and use LINQ to extract the values I need; namely, the DIsplayName for every security group and built-in role in the results. I am using the names (and picking both roles and groups) because that\u2019s what you\u2019d get with the classic isinrole: of course you can decide to restrict to specific types or refer to less ambiguous ObjectIds, provided that they mean something for your application.<\/p>\n<p>Lines 19 and 20: finally, for each entry in the result set we create a corresponding claim of type role and we add it to the incomingPrincipal, which we will eventually return as the principal to be assigned to the current thread and passed to the application. Did you notice that string \u201cGRAPH\u201d? That is going to appear as the issuer of those new claims, to make it clear to the application that they were added a posteriori as opposed to being already present directly in the incoming token. Just using that string is pretty clumsy, using something a bit more informative (the query itself? The graph URL+tenantID URL?) might be more appropriate but for this tutorial I\u2019ll go for conciseness. <\/p>\n<p>Ottimo direi! This is all the code we need to write. Give it a Shift+Ctrl+B just to be sure; if everything builds nicely, we are ready to create a user for our test.<\/p>\n<h1>Provisioning Test Users with the Windows Azure AD Management UX<\/h1>\n<p>Given that you have an AAD tenant, you already have at least one user: the administrator. But why not taking this opportunity to play with the nice AAD management UX? Head to <a title=\"https:\/\/activedirectory.windowsazure.com\" href=\"https:\/\/activedirectory.windowsazure.com\">https:\/\/activedirectory.windowsazure.com<\/a>, sign in as the administrator and prepare for some user &amp; group galore.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2727.image_5F00_1578CE61.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2727.image_5F00_1578CE61.png\" width=\"500\" height=\"313\" \/><\/a> <\/p>\n<p>The first screen shows you a summary of your services and proposes entry points for the most common tasks. Pick <strong>Add new user<\/strong>.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/4380.image_5F00_4DB74579.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/4380.image_5F00_4DB74579.png\" width=\"500\" height=\"309\" \/><\/a> <\/p>\n<p>The first screen is pretty straightforward. I am going to fill in the data for a random user \ud83d\ude09 once you have done it, click next:<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2234.image_5F00_6646E2C9.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2234.image_5F00_6646E2C9.png\" width=\"550\" height=\"360\" \/><\/a> <\/p>\n<p>In this screen you are given the chance to assing to the new user one of the built-in administrative roles. I added User Management administrator, just to see how that will look like. Also, I picked Antarctica: not very useful for the tutorial, but pretty cool \ud83d\ude42 hit next again. You\u2019ll be offered to assign O365 licenses, that is also inconsequential for the tutorial. Hit next again.<br \/>\n  <br \/>You\u2019ll be offered to receive the results of the wizard in a mail. Do whatever you want here as well \ud83d\ude42 then click Create.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0412.image_5F00_2CC3D2D2.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0412.image_5F00_2CC3D2D2.png\" width=\"500\" height=\"339\" \/><\/a> <\/p>\n<p>As a result, you are given the temporary password. Put it in a Notepad instance, you\u2019ll need it momentarily; then click Finish.<\/p>\n<p>&#160;<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0160.image_5F00_2C579FDD.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0160.image_5F00_2C579FDD.png\" width=\"500\" height=\"366\" \/><\/a> <\/p>\n<p>You\u2019ll end up in the user management section of the portal. Let\u2019s go to the security groups section and see if we can make our new user more interesting.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1157.image_5F00_7D25B445.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1157.image_5F00_7D25B445.png\" width=\"500\" height=\"325\" \/><\/a> <\/p>\n<p>We already have a security group, Sales. Booring! Let\u2019s create a new group, just to see how it\u2019s done. Hit New.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1663.image_5F00_43A2A44E.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1663.image_5F00_43A2A44E.png\" width=\"500\" height=\"363\" \/><\/a> <\/p>\n<p>Add a name, a description, then hit save.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0488.image_5F00_43367159.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/0488.image_5F00_43367159.png\" width=\"500\" height=\"312\" \/><\/a> <\/p>\n<p>You\u2019ll be transported to the group membership management page. Select the user you want to work with by checking the associated box, then hit add: you will see that the user gets added on the right hand side of the screen. Hit close.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/7433.image_5F00_70B7911C.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/7433.image_5F00_70B7911C.png\" width=\"500\" height=\"278\" \/><\/a> <\/p>\n<p>Your group is now listed along all others. We have one last task before we can give our app a spin: you have to change the temporary password of the newly created user. SIgn out of the portal by clicking on your administrator\u2019s user name on the top right corner of the page and choosing Sign Out.<\/p>\n<p>Sign back in right away, but this time using the new user name and temporary password.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/7848.image_5F00_425E0B6F.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/7848.image_5F00_425E0B6F.png\" width=\"500\" height=\"345\" \/><\/a> <\/p>\n<p>Do what you have to do, then hit submit. You\u2019ll be asked to sing in with your new password, and once you do so you\u2019ll be back in the portal. We are done here, close everything and head back to Visual Studio.<\/p>\n<p>&#160;<\/p>\n<h1>Testing the Solution<\/h1>\n<p>Excellent! Almost there. Now that we prepared the stage to get roles information, it\u2019s time to take advantage of that in our application.<\/p>\n<p>Open HomeController.cs and modify the About action as follows:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span>[Authorize(Roles=<span class=\"str\">&quot;Hippies&quot;<\/span>)]<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span><span class=\"kwrd\">public<\/span> ActionResult About()<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>{   <\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>   ViewBag.Message = <span class=\"str\">&quot;Your app description page.&quot;<\/span>;<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>   ClaimsPrincipal cp = ClaimsPrincipal.Current;<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>   <span class=\"kwrd\">return<\/span> View();<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span>}<\/pre>\n<\/div>\n<p>Line 1: this attribute will ensure that only users belonging to the \u201cHippies\u201d group can access this part of the application. This is standard MVC, good ol\u2019 ASP.NET, nothing claims-specific.<\/p>\n<p>Line 5: this line retries the ClaimsPrincipal from the thread, so that we can take a peek with the debugger without going though static properties magic.<\/p>\n<p>Ready? Hit F5!<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2046.image_5F00_5AEDA8BF.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2046.image_5F00_5AEDA8BF.png\" width=\"500\" height=\"274\" \/><\/a> <\/p>\n<p>You\u2019ll be presented with the usual AAD prompt. For now, access as the AAD administrator. You\u2019ll land on the application\u2019s home page (not depicted below, it\u2019s the usual straight form the project template). Let\u2019s see what happens if you hit the About link, though:<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3618.image_5F00_086EC883.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/3618.image_5F00_086EC883.png\" width=\"500\" height=\"272\" \/><\/a> <\/p>\n<p>Surprise! Sorry, hippies only here \u2013 the admin is clearly not in that category \ud83d\ude42 the error experience could be better, of course, and that\u2019s easy to fix, but hopefully this barebone page is already enough to show you that our authorization check worked.<\/p>\n<p>Let\u2019s stop the debugger, restart the app and sign in as the new user instead. Once we get to the usual home page, let\u2019s click on About.<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1663.image_5F00_39FA3618.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/1663.image_5F00_39FA3618.png\" width=\"500\" height=\"248\" \/><\/a> <\/p>\n<p>This time, as expected, we can access it! Very nice.<\/p>\n<p>Let\u2019s take a peek inside the incoming ClaimsPrincipal to see the results of our claims enrichment logic. Add a breakpoint inside the About() method, then head to the Locals and expand cp:<\/p>\n<p><a href=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2543.image_5F00_4E7F8596.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border: 0px currentcolor\" border=\"0\" alt=\"image\" src=\"http:\/\/cloudidentity.com\/blog\/wp-content\/uploads\/2013\/01\/2543.image_5F00_4E7F8596.png\" width=\"550\" height=\"375\" \/><\/a> <\/p>\n<p>The claims from 0 to 7 are the ones we got directly in the original token from AAD. I expanded the Givenname claim to show (light blue box) that the issuer is, in fact, your AAD tenant (did I mention that this is a preview and claim types\/formats\/etc etc can still change?).<br \/>\n  <br \/>The claims at index 7 and 8 are the ones that were added from our GraphClaimsAuthenticationManager: I expanded the first one, to highlight our goofy but expressive Issuer value. Given that both claims are of the <a href=\"http:\/\/schemas.microsoft.com\/ws\/2008\/06\/identity\/claims\/role\">http:\/\/schemas.microsoft.com\/ws\/2008\/06\/identity\/claims\/role<\/a>, and given that they are added before the control is handed over to the app, both can count when used in IsInRole, [Authorize], &lt;authorization&gt; and similar. Ta dah! <\/p>\n<h1>Summary<\/h1>\n<p>Yes, this took a couple of extra nights; and yes, this is definitely not production-ready code (for one, the GraphClaimsAuthenticationManager should cache the token instead of getting a new one at every sign in). However I hope this was useful for getting a more in-depth look to some interesting features such as the Graph API, the management UX, WIF extensibility and the structure of Windows Azure Active Directory itself. Remember, we are still in developer preview: if you have feedback do not hesitate to drop us a line!<\/p>\n<div style=\"clear:both\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Welcome to a new installment of the \u201caddressing the most common questions about Windows Azure AD development\u201d series! This time I am going to tackle one question that I know is very pressing for many of you guys: How do I get role and group membership claims for users signing in via Windows&#8230;<\/p>\n","protected":false},"author":1,"featured_media":1302,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[5,6,12,4],"tags":[],"class_list":["post-249","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-wif","category-windows-azure","category-windows-azure-active-directory","category-windows-identity-foundation"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=249"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions"}],"predecessor-version":[{"id":1661,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions\/1661"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/1302"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}