Most of the businesses running on the Microsoft Server technologies are happy with the native implementation of Windows-based authentication mechanism. Claims-based identity is often an afterthought. The idea of claims-based identity takes center stage when there is a need for the applications within the ecosystem to talk to the third-party vendors that are in different security realms running on the non-Microsoft platforms. The WIF runtime allows extending your current Windows-based security implementation to support claims-based identity. External vendors can be authenticated, and the claims can be assigned in the form of Active Directory Group, allowing them to request resources from the RP.
In the previous chapter, we have seen how the identity information can be abstracted using claims. In this recipe, you will learn how Windows identity can be used to generate a ClaimSet(System.IdentityModel.Claims)
object and assign it to SecurityToken
during a WS-Federation Passive Requestor Profile sign-in request processing operation. We will see how the STS can process incoming identity and assign Active Directory Group level permissions to the requestor as illustrated in the following diagram:
Make sure that you are connected to the identity provider (Active Directory) in order to be able to run the solution associated with this recipe.
To extend the Windows integrated authentication to support claims-based identity, perform the following steps:
Web.config
file. Notice that the authentication mode is commented out by the utility and the authorization element is added:<!--Commented out by FedUtil--> <!--<authentication mode="Windows" />--> <authorization> <deny users="?" /> </authorization>
CustomSecurityTokenService.cs
file under the App_Code
folder in the ASP.NET STS website, and create an instance of the WindowsClaimSet(System.IdentityModel.Claims)
class from the incoming Principal.Identity
property in the GetOutputClaimsIdentity
method:protected override IClaimsIdentity GetOutputClaimsIdentity( IClaimsPrincipal principal, RequestSecurityToken request, Scope scope ) { if ( null == principal ) { throw new ArgumentNullException( "principal" ); } ClaimsIdentity outputIdentity = new ClaimsIdentity(); outputIdentity.Claims.Add(new Microsoft.IdentityModel.Claims.Claim (System.IdentityModel.Claims.ClaimTypes.Name, principal.Identity.Name)); //Fetch the groups associated with the AD user and create roles WindowsClaimSet claimSet = new WindowsClaimSet(new WindowsIdentity(principal.Identity.Name), true); var accessControlClaims = claimSet.FindClaims(System.IdentityModel.Claims.ClaimTypes.Sid, Rights.PossessProperty); foreach (var claim in accessControlClaims) { outputIdentity.Claims.Add(new Microsoft.IdentityModel.Claims.Claim( Microsoft.IdentityModel.Claims.ClaimTypes.Role, GetResourceFromSid(claim.Resource as SecurityIdentifier))); } return outputIdentity; //The code block above is for illustration purpose only to display the named identifiers. In a real time scenario the following method can be used: //return WindowsClaimsIdentity.CreateFromUpn(principal.Identity.Name, AuthenticationTypes.Windows, false); }
The claim values are translated into their equivalent named representations for the illustration purpose in the solution.
Index
method in the HomeController
class to retrieve the list of claims from the current context identity and assign it as a model for the view:public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; var principal = Thread.CurrentPrincipal; var identity = principal.Identity as IClaimsIdentity; var claims = identity.Claims; return View(claims); }
Index
view (Index.cshtml
) under the Views
folder, create an instance of the WebGrid
and pass the model to display the assigned claims (types and values):<h2>@ViewBag.Message</h2> <p> @{ var grid = new WebGrid(Model); @grid.GetHtml(columns: grid.Columns(grid.Column("ClaimType"), grid.Column("Value"))); } </p>
The GetOutputClaimsIdentity
method in the CustomSecurityTokenService
(inherited from Microsoft.IdentityModel.SecurityTokenService)
class provides an implementation to assign claims to the requestor. In our solution, a WindowsIdentity
(System.Security.Principal
) instance is created using the incoming identity (System.SecurityModel.Principal.IPrincipal.Identity
) name. The WindowsClaimSet
(System.IdentityModel.Claims
) instance is created using the WindowsIdentity
object. The WIF runtime then assigns the claims to the requestor that are retrieved back in the HomeController
class of the RP web application using the Thread.CurrentPrincipal
property.
In our solution, we have used the ClaimSet
class to demonstrate the process of creating claims from Windows identity for the illustration purposes only (translating the identifiers into the named references). In a real scenario, you must use the WindowsClaimsIdentity (Microsoft.IdentityModel.Claims)
class to achieve similar results:
return WindowsClaimsIdentity.CreateFromUpn(principal.Identity.Name, AuthenticationTypes.Windows, false);