How to: Implement Claims Authorization in a Claims-Aware ASP.NET Application Using WIF and ACS
Updated: June 19, 2015
Applies To: Azure
Applies To
Microsoft® Azure™ Access Control Service (ACS)
Windows® Identity Foundation (WIF)
ASP.NET
Summary
This topic describes how to implement Claims Based Access Control (CBAC) authorization in claims-aware ASP.NET web applications using WIF and ACS.
Contents
Objectives
Overview
Summary of Steps
Step 1 – Implement a Claims Authorization Library
Step 2 – Configure an ASP.NET Application to Use the Claims Authorization Library
Step 3 – Configure an Authorization Policy
Related Items
Objectives
Externalize the authorization logic from the application.
Implement the authorization checks beyond roles, resulting in a more detailed control over authorization.
Provide for policy driven, declarative, authorization management.
Overview
Claims authorization is based on using the information that is carried within a token—the claims. Claims authorization is useful, when it is insufficient to make the authorization decision based solely on roles. For example, in financial applications, the same role can be given to different limits for transferring money between accounts based on tenure and other attributes. Such attributes may come in the form of a claim along with the role and therefore allow for a more finely tuned authorization decision.
Summary of Steps
Step 1 – Implement a Claims Authorization Library
Step 2 – Configure an ASP.NET Application to Use the Claims Authorization Library
Step 3 – Configure an Authorization Policy
Step 1 – Implement a Claims Authorization Library
This step shows you how to create an external class library that will read an access policy from a configuration file and enforce the access checks. The following sample shows how to implement a claims authorization library that makes an authorization decision based on a ZIP code claim.
To implement claims authorization library
Make sure you are running Visual Studio® in Administrator mode.
Right-click the desired solution in Solution Explorer, add a new Class Library project, and then give it a name, for example, MyClaimsAuthorizationManager.
Delete the default class, Class1.cs.
Add a new class and give it a name, for example, ZipClaimsAuthorizationManager. This will implement an authorization based on postal codes.
Add a reference to the Microsoft.IdentityModel and to the System.Web assemblies.
Add the following declarations.
using System.IO; using System.Xml; using Microsoft.IdentityModel.Claims; using Microsoft.IdentityModel.Configuration;
Extend the ClaimsAuthorizationManager class, overriding its AccessCheck method, and then implementing a constructor to your ZipClaimsAuthorizationManager class. Your code should look similar to the following.
namespace MyClaimsAuthorizationManager { class ZipClaimsAuthorizationManager : ClaimsAuthorizationManager { private static Dictionary<string, int> m_policies = new Dictionary<string, int>(); public ZipClaimsAuthorizationManager(object config) { XmlNodeList nodes = config as XmlNodeList; foreach (XmlNode node in nodes) { { //FIND ZIP CLAIM IN THE POLICY IN WEB.CONFIG AND GET ITS VALUE //ADD THE VALUE TO MODULE SCOPE m_policies XmlTextReader reader = new XmlTextReader(new StringReader(node.OuterXml)); reader.MoveToContent(); string resource = reader.GetAttribute("resource"); reader.Read(); string claimType = reader.GetAttribute("claimType"); if (claimType.CompareTo(ClaimTypes.PostalCode) == 0) { throw new ArgumentNullException("Zip Authorization is not specified in policy in web.config"); } int zip = -1; bool success = int.TryParse(reader.GetAttribute("Zip"),out zip); if (!success) { throw new ArgumentException("Specified Zip code is invalid - check your web.config"); } m_policies[resource] = zip; } } } public override bool CheckAccess(AuthorizationContext context) { //GET THE IDENTITY //FIND THE POSTALCODE CLAIM'S VALUE IN IT //COMPARE WITH THE POLICY int allowedZip = -1; int requestedZip = -1; Uri webPage = new Uri(context.Resource.First().Value); IClaimsPrincipal principal = (IClaimsPrincipal)HttpContext.Current.User; if (principal == null) { throw new InvalidOperationException("Principal is not populate in the context - check configuration"); } IClaimsIdentity identity = (IClaimsIdentity)principal.Identity; if (m_policies.ContainsKey(webPage.PathAndQuery)) { allowedZip = m_policies[webPage.PathAndQuery]; requestedZip = -1; int.TryParse((from c in identity.Claims where c.ClaimType == ClaimTypes.PostalCode select c.Value).FirstOrDefault(), out requestedZip); } if (requestedZip!=allowedZip) { return false; } return true; } } }
Compile the solution to make sure that there are no compilation errors.
Locate the compiled library, in this case MyClaimsAuthorizationManager.dll. It will need to be dropped into the bin folder of the ASP.NET web application.
Step 2 – Configure an ASP.NET Application to Use the Claims Authorization Library
The next steps are performed in your ASP.NET web application. Do not add a reference to your Claims Authorization Manager library that you created in previous step. Your ASP.NET web application should be “unaware” of it, except in web.config.
To configure an ASAP.NET application to use the Claims Authorization Library
Configure your ASP.NET web application to include WIFs ClaimsAuthorizationModule in its pipeline by adding the following entry to the HttpModules section in the web.config (valid for the development web server that ships with Visual Studio; for Internet Information Services (IIS) version 7, this configuration should be located in the modules section under the system.webServer node).
<add name="ClaimsAuthorizationModule" type="Microsoft.IdentityModel.Web.ClaimsAuthorizationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
Configure your ASP.NET web application to use the custom authorization library you implemented in the previous step by adding the following entry to the microsoft.identityModel.service node.
<claimsAuthorizationManager type="MyClaimsAuthorizationManager.ZipClaimsAuthorizationManager, MyClaimsAuthorizationManager" >
Step 3 – Configure an Authorization Policy
In this topic the configuration policy is expressed in the ASP.NET web application web.config file. The policy carries simple rules that map resources to the claim type and its value. For example, the following policy can be read and enforced by the custom authorization library you created and configured in the previous steps. Add the following entry to the claimsAuthorizationManager node you configured in the previous step.
<policy resource="/default.aspx">
<claim claimType=https://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode
Zip="11111" />
</policy>
The above policy requires that an incoming token must have a zip claim with a value of 11111 in order to access the default.aspx page.