.Net Claims Security
Identity Providers (IdPs) manage user identity (login and properties of the user). The properties (name, and others such as role, email etc) can be passed to the application (Relying Party, RP)
Claims may be passed via different IdPs (federation), which may involve transformation (changing the claims- either to expose a subset, or a completely different set of claims).
Protocols based on claims: WS-Federation, OAuth, SOAP WS-Trust/WS-Security
ClaimsIdentity/ClaimsPrincipal
.net 1.0+ uses IPrincipal and IIdentity in Thread.CurrentPrincipal.
var cp = Thread.CurrentPrincipal;
//within Windows-AD
var wc = WindowsPrincipal.Current;
var wi = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
//or generic
var gi = new GenericIdentity("Martin");
var gp = new GenericPrincipal(gi, new[] { "Admin", "Dev" });
Thread.CurrentPrincipal = gp;
NB: WCF is different- it has ServiceSecurityContext
In .net 4.5, WindowsIdentity, GenericIdentity and FormsIdentity all derive from ClaimsIdentity.
var wp = WindowsPrincipal.Current;
var claimsIdentities = wp.Identities; //not just one wc.Identity
var claims = wp.Claims; //all the raw claims
//Windows AD properties are mapped to OASIS standard names
var nameClaim = wp.FindFirst(ClaimTypes.Name);
var roleClaims = wp.FindAll(ClaimTypes.GroupSid);
You can also get the claims principal/identity via:
var principal = ClaimsPrincipal.Current;
//is the same as
var p = Thread.CurrentPrincipal as ClaimsPrincipal ?? new ClaimsPrincipal(Thread.CurrentPrincipal);
Claims
//System.Security.Claims
var claimsList = new List<Claim>
{
//custom claim
new Claim("Name", "I"),
//SAML standard names (URIs)
new Claim(ClaimTypes.Name, "me"),
new Claim(ClaimTypes.Role, "Admin"),
};
var cId = new ClaimsIdentity(claimsList);
Console.WriteLine(cId.IsAuthenticated); //is false! Needs an authentication type.
cId = new ClaimsIdentity(claimsList, "AuthenticationType"); //NB: Windows is "Negotiate"
Console.WriteLine(cId.IsAuthenticated); //is true.
//specify the default name and roles
cId = new ClaimsIdentity(claimsList, "AuthenticationType", "Name", ClaimTypes.Role);
Console.WriteLine(cId.Name); //returns "I", not "me".
//set it on the thread as normal
Thread.CurrentPrincipal = new ClaimsPrincipal(cId);
ClaimsIdentity (+WindowsIdentity etc) flatten the claims and find the first for Name and IsInRole for first claims it finds (.FindFirst()).
Authorization
You can use ClaimsPrincipalPermission just like the old CAS Permission Demands.
//declarative
[ClaimsPrincipalPermission(SecurityAction.Demand,
Resource = "Resource", Operation = "Edit")]
public void EditResource()
{
//programmatic - System.IdentityModel.Services
ClaimsPrincipalPermission.CheckAccess("Resource", "Edit");
Derive from ClaimsAuthorizationManager and override bool CheckAccess(AuthorizationContext).
The context has the ClaimsPrincipal, a list of Action claims and a list of Resource claims.