The purpose of this blog post is to give you a complete overview on how to configure Windows Azure Active Directory (WAAD) together with Windows Azure Access Control Service (ACS). We will create 2 applications (an MVC 4 Web application and a Windows Store Application).
In our MVC application we will support Forms Based Authentication and Claims Based Authentication at the same time.
In our Windows Store Application we will use the JWT token generated by ACS to authenticate on our previously created MVC Web Api controllers.
On both applications we will be able to authorize users based on their roles (CIA users and U.S. Marine users).
This blog post will consist of 2 parts:
1. Setting up ACS, WAAD and an MVC Application by using Jason Web Tokens (this part)
2. Add support for Windows Store Applications by passing the Jason Web Token
1. Configuration on Windows Azure
Prerequisites
- .Net Framework 4.5 (Visual Studio 2012)
- Azure subscription
1.1 Configuring WAAD
1. Create / or use an existing WAAD account (our sample WAAD domain is "natsec"). Sign-up: (https://activedirectory.windowsazure.com/Signup/QuickSignup.aspx?ru=https://activedirectory.windowsazure.com&ali=1)

2. Login on https://activedirectory.windowsazure.com/
3. From here it is pretty straightforward. You can sync an existing AD with your WAAD or create users / groups manually.
For our sample, I've created the following
2 groups:
- Central Intelligence Agency
- US Marine
3 users:
- David Estes (member of Central Intelligence Agency group)
- Saul Goodman (member of Central Intelligence Agency group)
- Mike Faber (member of US Marine group)
1.2. Configuring ACS
1. Login to your current Windows Azure Subscription (https://manage.windowsazure.com)
2. Navigate to Active Directory. Create a new Access Control Namespace and after creation, click on the management link (https://[your_namespace].accesscontrol.windows.net/v2/mgmt/web).
1.2.1. Create a new Identity Provider
1. Select WS-Federation Identity provider, click next.
2. Enter a display name, select the Url radio button for WS-Federation metadata and enter
https://accounts.accesscontrol.windows.net/[your_namespace].onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml
In the above url replace [your_namespace] and browse to it to make sure it works.

1.2.2. Create a new Relying Party Application
1. As Realm you type your application realm (free to choose, but must be unique in your ACS). ex. urn:NatSec
2. As Return Url, you enter the Url that your MVC front-end will run on. You can change this later to match with your local IIS Express port. The subpath of this URL will be discussed later in this post (needed to set our cookies and/or JWT token).
3. As Token Format we will choose JWT (Jason Web Token: at time of writing it is still in beta, but currently the most compact token available).
4. Under Authentication Settings we select our Identity Provider we just created and check "Create new rule group".
5. For Token Signing Settings we opt for a new generated Symmetric Key. We work with a symmetric key as a certificate would require the MVC website to have it installed in the Certificate Store. As we will host the website on Windows Azure Websites, we currently can't add the certificate.

1.2.3. Changing Default Rule Group
In ACS you can map WAAD Claims to your custom claims. To distinguish user access in our application we could map WAAD User Roles to custom User Roles we can use in our application (Another relying party could map role claims to our same custom format). The only problem we face is that the roles are not included in the claims (claims could become very large). When we need to request the current user roles, we need to query the GraphApi from WAAD. The mapping of user roles will happen on our MVC backend later.
1. Edit the Rule Group and Generate default rules. (this way we will receive standard claims like 'firstname', 'lastname', ... )
In order to please ASP.Net Security we will need to modify an existing claim. ASP.Net AntiForgery expects the following claims to be present:
2. Edit the name claim and change the output claim to "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" (in the predefined selectable types)

1.3. Creating a Trust relation ship between ACS and WAAD
Prerequisites
WAAD should be configured to trust our ACS to issue a token. The only way we currently can configure this is with PowerShell.
Enter the following statements
connect-msolservice
import-module msonlineextended –force
$replyUrl = New-MsolServicePrincipalAddresses -Address "https://[yournamespace].accesscontrol.windows.net/"
New-MsolServicePrincipal -ServicePrincipalNames @("https://[yournamespace].accesscontrol.windows.net/") -DisplayName "[justAName]" -Addresses $replyUrl
You will be prompted for your WAAD credentials after line 1 (ex. david.estes@natsec.onmicrosoft.com).
On line 3 you'll need to replace [yournamespace] with the namespace you choose for ACS (ex. coditblog)
On line 4 you'll need to replace [yournamespace] with the namespace you choose for ACS (ex. coditblog) and [justAName] with a descriptive name).

Be sure to note the symmetric key credential that is created for you as output of the cmdlet if you do not supply a value. Once the service principal has been created, you cannot retrieve the symmetric key credential. You will need to use it in your code when authenticating to Windows Azure AD Access Control.
2. Building our MVC Application
2.1. Creating the MVC Application
The MVC Application will act as an API to issue a token for our Windows Store Application. It will contain all configuration in order to authenticate with ACS.
Create a new MVC Application using an Internet Application as Project Template.
Most existing applications will already have some security mechanism, so we'll jump into a real-world scenario and use Forms Authentication as our current authentication. We will extend our authentication mechanism by configuring ACS in our application.
Using the Internet Application Template, Forms Authentication is already configured. Forms Authentication in MVC 4 is no longer using the ASP.Net MembershipProvider but instead it's using SimpleMembership.
First of all, start the application and Create a new users (default password in the sample is: "mypassword")

Stop the application and click "Show All Files" in Solution Explorer. You will notice the mdf ASP.net Membership database file under "App_Data". Include the file into the project and double click on it.
For the sake of simplicity, we'll create our roles using T-SQL. Right click the database (in Server Explorer) and select "New Query".
Execute the following statement:
insert into [aspnet-Codit.Blog.Waad.Mvc-20130301113648].[dbo].[webpages_Roles] (RoleName) values ('CIA')
insert into [aspnet-Codit.Blog.Waad.Mvc-20130301113648].[dbo].[webpages_Roles] (RoleName) values ('U.S. Marine')
insert into [aspnet-Codit.Blog.Waad.Mvc-20130301113648].[dbo].[webpages_UsersInRoles] (UserId, RoleId) values (1, 2)

As you may have noticed already, the roles are different from the roles we previously configured in WAAD. This is on purpose.
2.2. Configuring ACS in our MVC Application
Add the following NuGet Package to your solution: "JSON Web Token Handler For the Microsoft.Net Framework 4.5" (Id: Microsoft.IdentityModel.Token.JWT (https://nuget.org/packages/Microsoft.IdentityModel.Tokens.JWT/0.1.0))
Also add a reference to System.IdentityModel (v4.0.0.0) and System.IdentityModel.Services (v4.0.0.0)
Create a new class "CustomJwtSecurityTokenHandler"
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens.JWT;
namespace Codit.Blog.Waad.Mvc.Infrastructure.Auth.Handlers
{
public class CustomJwtSecurityTokenHandler : JWTSecurityTokenHandler
{
public override ClaimsPrincipal ValidateToken(JWTSecurityToken jwt, TokenValidationParameters validationParameters)
{
if ((validationParameters.ValidIssuer == null) &&
(validationParameters.ValidIssuers == null || !validationParameters.ValidIssuers.Any()))
{
validationParameters.ValidIssuers = new List<string> { ((ConfigurationBasedIssuerNameRegistry)Configuration.IssuerNameRegistry).ConfiguredTrustedIssuers.First().Value };
}
if (validationParameters.SigningToken == null)
{
var resolver = (NamedKeyIssuerTokenResolver)this.Configuration.IssuerTokenResolver;
if (resolver.SecurityKeys != null)
{
var keyName = Configuration.AudienceRestriction.AllowedAudienceUris[0].ToString();
List<SecurityKey> skeys;
if (resolver.SecurityKeys.TryGetValue(keyName, out skeys))
{
var tok = new NamedKeySecurityToken(keyName, skeys);
validationParameters.SigningToken = tok;
}
}
}
return base.ValidateToken(jwt, validationParameters);
}
protected override string NameIdentifierClaimType(JWTSecurityToken jwt)
{
return ClaimTypes.GivenName;
}
}
}
JWT Token Validation isn't supported out of the box so we override the ValidateToken method. The main issue is that the parameters defined in the config aren't recognized so we need to read them from the config ourselves.
We do an override of the NameIdentifierClaimType method in order to pass our name claim to be set in the RolePrincipal object. By default it will use the "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" claim. This claim contains our user's complete e-mail adress. Instead we want to greet the user with his first name. We return the default nameclaim ClaimTypes.GivenName (="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"). The result of this override is demonstrated in the following screenshot

Next add the following configuration to your Web.Config
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<audienceUris>
<add value="[yourRealm]" />
</audienceUris>
<securityTokenHandlers>
<add type="[yourClassAndAssemblyCustomJWTTokenHandler]" />
<securityTokenHandlerConfiguration>
<certificateValidation certificateValidationMode="PeerTrust" />
<issuerTokenResolver type="[yourClassAndAssemblyCustomJWTTokenHandler]">
<securityKey symmetricKey="[jwtSymmetricKey]" name="[yourRealm]" />
</issuerTokenResolver>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
<issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<trustedIssuers>
<add thumbprint="[thumbPrint]" name="https://[yournamespace].accesscontrol.windows.net/" />
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
</system.identityModel>
<system.identityModel.services>
<federationConfiguration>
<cookieHandler requireSsl="false" />
<wsFederation passiveRedirectEnabled="true" issuer="https://[yournamespace].accesscontrol.windows.net/v2/wsfederation" realm="[yourRealm]" requireHttps="false" />
</federationConfiguration>
</system.identityModel.services>
On line 2:
We've added saveBootstrapContext="true" in order to retrieve our JWT token easily in our controller.
On line 4:
Replace [yourRealm] with the realm you entered when creating a relying party (ex. urn:NatSec)
On line 7:
Replace [yourClassAndAssemblyCustomJWTTokenHandler] with the your "custom jwt class, assemblyname".
On line 10:
Replace [yourClassAndAssemblyCustomJWTTokenHandler] with the your "custom jwt class, assemblyname".
On line 11:
Replace [yourRealm] with the realm you entered when creating a relying party (ex. urn:NatSec)
On line 11:
Replace [jwtSymmetricKey] with the symmetric key of your JWT (ACS Management page => Certificates and keys => Token Signing => [your RP] (WAAD - NatSec) => Copy the full 256-bit symmetric key
On line 17:
Replace [thumbPrint] with your Service Certificate Thumbprint (ACS Management page => Service Settings => Certificates and keys => Token Signing => Service Namespace (X.509 Certificate) => Copy your thumbprint).
Replace [yournamespace] with your ACS namespace (ex. coditblog)
On line 25:
Replace [yournamespace] with your ACS namespace (ex. coditblog)
Replace [yourRealm] with the realm you entered when creating a relying party (ex. urn:NatSec)
Add requestValidationMode="4.5" to the httpRuntime element.
<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
Add <allow users="*" /> as a child of the <authorization> element and above the <deny users="?" /> element.
<authorization>
<allow users="*"/>
<deny users="?" />
</authorization>
Make sure any wif packages do not disable forms authentication module (comment the remove element if you have it)
<system.webServer>
<modules>
<!--<remove name="FormsAuthentication" />-->
</modules>
</system.webServer>
When you run the application you will be automatically promted with the following screen:

2.3. Support ACS and Forms Authentication
In order to allow Forms Based login, we need to disable the auto redirect to the Windows Azure Active Directory login page. We can do this by setting "passiveRedirectEnabled" to false in our web.config (wsFederation element).
When we now run the application we can use the standard Forms Authentication but the WAAD seems to be disabled. We need to manually add a link in order for the user to login using WAAD.
We will and cannot use the build in Authentication Providers class for this demo. Instead locate the following line in Login.cshtml
@Html.Action("ExternalLoginsList", new { ReturnUrl = ViewBag.ReturnUrl })
and replace it with
<a href="https://[yournamespace].accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=[yourRealm]" title="Log in using your Windows Azure Active Directory account">Windows Azure Active Directory</button>
Make sure you replace the following in the above URL
- [yourRealm] with the realm you entered when creating a relying party (ex. urn:NatSec)
- Replace [yournamespace] with your ACS namespace (ex. coditblog)

In order to authenticate successfully with our ACS we need to make sure we support the configured Return Url (in ACS).
We will create a new WebApi controller to act as our return Url. You could also use a normal controller but our WebApi controller will become in handy when we also support Windows Store Applications. We use WebAPI for returning tokens and JSON data, we will use normal Controllers for returning Views. Create a new folder named "api" under "Controllers". Add a new Empty Web API Controller named "AuthController".

Add the following
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Codit.Blog.Waad.Mvc.Controllers.api
{
public class AuthController : ApiController
{
[AllowAnonymous]
[HttpPost]
public HttpResponseMessage GetToken()
{
var response = Request.CreateResponse(HttpStatusCode.Redirect);
response.Headers.Add("Location", "/");
return response;
}
}
}
When the return url is configured correctly in ACS, then this controller action will be called after the login procedure of WAAD.
It will receive a HttpPost with security tokens, these tokens will result in FedAuth cookies.
Fiddler Return Url request from WAAD:

Fiddler Cookies on Redirect to home page:

And we're in:

2.4. Enabling WAAD Graph Api and Role Authentorization
We've already discussed authentication before, now it is time for authorization. Based on the roles of a user we will allow or deny page requests.
2.4.1. References and Packages
Add the following NuGet Package Windows Azure Authentication Library (Beta) to your solution
Id: Microsoft.WindowsAzure.ActiveDirectory.Authentication (https://nuget.org/packages/Microsoft.WindowsAzure.ActiveDirectory.Authentication/0.6.1)
Add a service reference to your WAAD using the following URL: https://graph.windows.net/[yourWaadDomain]
Replace [yourWaadDomain] by your Waad Domain (obviously...) ex. NatSec
Reference following assemblies:
System.Windows.Forms (v4.0.0.0)
In order to access the GraphApi, we need to give read-permissions. Fire up a PowerShell instance and enter following commands.
First of all we need to retrieve the RoleMemberObjectId (so it can be replaced in the next command), type the following command:
Get-MsolServicePrincipal | select DisplayName,ObjectId
After executing the command below we will have read-only access to the WAAD Directory.
Add-MsolRoleMember -RoleName "Service Support Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId [yourRoleMemberObjectId]
2.4.2. Interaction with the GraphApi
Add a new class named "GraphClient" (see inline for detailed explanations)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Codit.Blog.Waad.Mvc.NatSec.Microsoft.WindowsAzure.ActiveDirectory;
using Microsoft.WindowsAzure.ActiveDirectory.Authentication;
namespace Codit.Blog.Waad.Mvc.Infrastructure.Auth.GraphApi
{
/// <summary>
/// This class uses the Windows Azure Graph API to retrieve a given user's direct group memberships.
/// Except for the <see cref="GetUserGroups"/> method, the code in this class is heavily based on public
/// Graph API examples from Microsoft.
/// </summary>
public class GraphClient
{
private readonly DirectoryDataService _dataService;
private readonly string _tenantDomainName;
private readonly string _servicePrincipalSymmetricKey;
private readonly string _tenantId;
private readonly string _appPrincipalId;
// ReSharper disable InconsistentNaming
/// <summary>
/// Name of the HTTP header that contains the unique ID of a client request.
/// Used when making Graph API requests
/// </summary>
private const string HeaderName_ClientRequestId = "client-request-id";
/// <summary>
/// Authorization header used when making Graph API requests
/// </summary>
private const string HeaderName_Authorization = "Authorization";
/// <summary>
/// Version of the data contract, used when making Graph API requests
/// </summary>
private const string HeaderName_DataContractVersion = "x-ms-dirapi-data-contract-version";
// ReSharper restore InconsistentNaming
private const string DataContractVersion = "0.8";
public GraphClient(string tenantDomainName, string tenantId, string appPrincipalId, string servicePrincipalSymmetricKey)
{
_tenantDomainName = tenantDomainName;
_tenantId = tenantId;
_servicePrincipalSymmetricKey = servicePrincipalSymmetricKey;
_appPrincipalId = appPrincipalId;
_dataService = new DirectoryDataService(GetConnectionUri());
_dataService.SendingRequest += (sender, args) =>
{
var webRequest = ((HttpWebRequest)args.Request);
webRequest.Headers.Add(HeaderName_Authorization, GetAuthorizationHeader());
webRequest.Headers.Add(HeaderName_DataContractVersion, DataContractVersion);
webRequest.Headers.Add(HeaderName_ClientRequestId, Guid.NewGuid().ToString());
};
}
/// <summary>
/// Identifier of the issuing resource for the symmetric key.
/// Used for getting an access token for requests.
/// Looks something like this:
/// A4423C7C-35F7-4679-99F8-5921A0482B63@tenantdomain.onmicrosoft.com
/// (the GUID here is an example, not the actual value)
/// </summary>
private string GetSymmetricKeyIssuingResource()
{
return _appPrincipalId + "@" + _tenantDomainName;
}
/// <summary>
/// Realm identifier for the service we want to access. Which is the tenant domain
/// hosted at Windows Azure AD.
/// 00000002-0000-0000-c000-000000000000/graph.windows.net@yourtenantdomain.onmicrosoft.com
/// (the GUID here is the actual identifier)
/// </summary>
private string GetServiceRealm()
{
return AzureAdPrincipalId + "/" + GraphApiServiceHost + "@" + _tenantDomainName;
}
/// <summary>
/// URI of the Graph API we're accessing.
/// Looks something like this:
/// https://graph.windows.net/EA314D90-8751-4534-A96E-77A5DF0E72AB
/// (the GUID here is an example, not the actual value)
/// </summary>
private Uri GetConnectionUri()
{
return new Uri(string.Format(@"https://{0}/{1}", GraphApiServiceHost, _tenantId));
}
/// <summary>
/// URI of the WAAD tenant domain.
/// Looks something like this:
/// https://accounts.accesscontrol.windows.net/yourtenantdomain.onmicrosoft.com
/// </summary>
private string GetFullTenantUri()
{
return "https://accounts.accesscontrol.windows.net/" + _tenantDomainName;
}
/// <summary>
/// This is the known identifier of the WAAD service principal
/// </summary>
private const string AzureAdPrincipalId = "00000002-0000-0000-c000-000000000000";
/// <summary>
/// This is the domain name of the WAAD Graph API service
/// </summary>
private const string GraphApiServiceHost = "graph.windows.net";
/// <summary>
/// Method to get the Oauth2 Authorization header from WAAD. This basically authenticates
/// the calling application to WAAD and gets a token with which further requests can be made.
/// </summary>
private string GetAuthorizationHeader()
{
var authContext = new AuthenticationContext(GetFullTenantUri());
var credential = new SymmetricKeyCredential(GetSymmetricKeyIssuingResource(), Convert.FromBase64String(_servicePrincipalSymmetricKey));
AssertionCredential assertionCredential = authContext.AcquireToken(GetServiceRealm(), credential);
return assertionCredential.CreateAuthorizationHeader();
}
/// <summary>
/// Queries the Graph API for security groups in which an active user with the given
/// <paramref name="userPrincipalName"/> is a direct member.
/// </summary>
public IList<Group> GetUserGroups(string userPrincipalName)
{
var user = _dataService.Users
.Where(u => u.AccountEnabled == true && u.UserPrincipalName == userPrincipalName)
.AsEnumerable()
.SingleOrDefault();
var groupReferences = _dataService.LoadProperty(user, "MemberOf")
.OfType<ReferencedObject>()
.Where(r => r.ObjectType == "Group")
.Select(g => g.ObjectId);
return _dataService.Groups
.AsEnumerable()
.Where(g => groupReferences.Contains(g.ObjectId))
.ToList();
}
}
}
Add a new class named GraphApiClaimAuthenticationManager (will use the GraphApi class)
Please replace [yourSymmetricKey] and [appPrincipalId] with the values you received when creating your WAAD using powershell.
Please see inline for detailed explanation.
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Web.Http;
using Codit.Blog.Waad.Mvc.Infrastructure.Auth.GraphApi;
namespace Codit.Blog.Waad.Mvc.Infrastructure.Auth.GraphApi
{
/// <summary>
/// This class uses <see cref="GraphClient"/> to read the AD security groups in which a given
/// <see cref="ClaimsPrincipal"/> is a direct member and then converts the memberships to group
/// claims. The group claims are then used to authorize user actions with <see cref="AuthorizeAttribute"/>.
/// </summary>
public class GraphApiClaimAuthenticationManager : ClaimsAuthenticationManager
{
/// <summary>
/// This is an arbitrary string identifying the claims issued by this class.
/// It exists to make it possible to distinguish those claims from other claims.
/// </summary>
private const string ClaimIssuerName = "waad-demo-usergroup-roleclaim";
/// <summary>
/// Augument <paramref name="incomingPrincipal"/> with claims obtained by converting
/// the user's direct security group memberships to role claims.
/// </summary>
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal == null || !incomingPrincipal.Identity.IsAuthenticated)
return incomingPrincipal;
// TODO: Load user roles from cache to avoid roundtrips to GraphApi
// TODO: Load these keys from persistence store based on the tenantDomain
const string appPrincipalId = "[yourAppPrincipalId]";
const string symmKey = "[yourSymmetricKey]";
var upn = incomingPrincipal.FindFirst(ClaimTypes.Upn).Value;
var tenantId = incomingPrincipal.FindFirst("http://schemas.microsoft.com/ws/2012/10/identity/claims/tenantid").Value;
var tenantDomain = upn.Split('@')[1];
var graphClient = new GraphClient(tenantDomain, tenantId, appPrincipalId, symmKey);
var userGroups = graphClient.GetUserGroups(upn);
var localRoles = new List<string>();
// Our local roles are CIA and U.S. Marine
// The roles on WAAD are Central Intelligence Agency and US Marine
// TODO: load these from persistence store
foreach (var userGroup in userGroups)
{
switch (userGroup.DisplayName)
{
case "Central Intelligence Agency":
localRoles.Add("CIA");
break;
case "US Marine":
localRoles.Add("U.S. Marine");
break;
}
}
var roleClaims = localRoles.Select(x => new Claim(ClaimTypes.Role, x, null, ClaimIssuerName));
((ClaimsIdentity)incomingPrincipal.Identity).AddClaims(roleClaims);
return incomingPrincipal;
}
}
}
There are a couple of things that can do here in order to extend functionality. If we support multiple WAAD tenants, we could load the securitykeys based on the waad domain from a persistence store.
We could also store mapping roles in our persistence store in order to configure them later. As noted before, roles of WAAD aren't the roles you will use locally.
In order to use the GraphApiClaimAuthenticationManager we need to add an extra line in our config that is responsible for kicking in our Authentication Manager
<claimsAuthenticationManager type="[NamespaceAndClassOfAuthManager], [assemblyName]" />
We would like to restrict access to our Contact page for US Marines. So only our CIA personnel will be authorized to access the contact page.
Protect our controller by replacing our Controller Action in HomeController.cs. The MultipleAuthorize class decoration is discussed later.
[MultipleAuthorize(Roles = "CIA")]
public ActionResult Contact()
{
ViewBag.Message = "CIA Only!";
return View();
}
Normally we could make use of the IsInRole method exposed by ClaimsPrincipal. However, I never succeeded on using this when we have Claims Based and Forms Based Authentication enabled. It will always falls back to Forms Based Authentication by default.
Therefore, I've implemented a custom authorization attribute that will check for claims and roles manually.
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading;
using System.Web.Mvc;
namespace Codit.Blog.Waad.Mvc.Infrastructure.Auth
{
public class MultipleAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
IPrincipal client = Thread.CurrentPrincipal;
// Customer ClaimsIdentity authorization
if ((client.Identity.GetType() == typeof (ClaimsIdentity)))
{
if (client.Identity.IsAuthenticated)
{
var roleClaims = ((ClaimsIdentity) client.Identity).Claims.Where(x => x.Type == ClaimTypes.Role).ToList();
if (Roles.Split(',').Any(role => roleClaims.FirstOrDefault(x => x.Value == role) == null))
{
return false;
}
return true;
}
return false;
}
// Use normal forms authorization
return base.AuthorizeCore(httpContext);
}
}
}
When you login either using WAAD or Forms authentication, you should be able to access the Contact page when you are part of the CIA and get an Access Denied Exception when you aren't part of the CIA.
You can download the complete sample of this first part here
In the next part, we'll add support for Windows Store Applications. Stay tuned!
24105c9c-5d00-4d4b-bd53-7e3f7daa025f|6|4.7