- Identity and Principal Objects
- Authentication
- Authorization
- Conclusion
So far, I have covered how to implement different authentication mechanisms. All of them end up putting the proper Principal object into the Thread.CurrentPrincipal property. Now it's time to see how to trigger authorization checks against the active Principal or Identity to protect sensitive operations.
Authorization checks in .NET can be applied in two ways: using Security Demands or calling explicitly the Principal object IsInRole method.
Security Demands
Permission Security Demands are similar to CAS Security Demands. They can be done programmatically using the PrincipalPermission object or declaratively using the PrincipalPermissionAttribute class. Declarative authorization checks can be placed both at method level and at class level. In the latter case, the authorization check is executed at object creation and also at each method call.
You can use Security Demands to restrict access to a specific user list and/or a specific role list. The latter approach is more flexible and is the only one you will likely ever meet in production code.
In the code sample below, declarative Security Demands at class and method level are shown:
//you must be in the Administrators or Users group to access any //method of this class [PrincipalPermission (SecurityAction.Demand, Role=@"BUILTIN\Administrators")] [PrincipalPermission (SecurityAction.Demand, Role=@"BUILTIN\Users")] public class protect { //additionally, you must be an the local computer Administrator to access //the protectedMethod method [PrincipalPermission (SecurityAction.Demand, Name=@"mycomputer\Administrator")] public void protectedMethod() { Debug.WriteLine ("accessed"); } ... other methods }
Here is a code sample using programmatic Security Demands instead:
public void anotherProtectedMethod() { PrincipalPermission pp1 = new PrincipalPermission(@"PCSABBA\Administrator", null); PrincipalPermission pp2 = new PrincipalPermission(null, @"BUILTIN\Power Users"); pp1.Union (pp2); // next statement will raises exception if not in required roles pp1.Demand (); ... application code follows }
IsInRole
The second way to apply security checks is to use the IsInRole method, asking for the membership to a specific role:
IPrincipal MyPrincipal = Thread.CurrentPrincipal; if ( MyPrincipal.IsInRole("BUILTIN"+@"\Administrators") ) MessageBox.Show ("operation performed"); else if ( int.Parse (textBox1.Text) < 1000 ) MessageBox.Show ("operation performed"); Else MessageBox.Show ("Your role allows max $1000");
IsInRole is a little more verbose, but provides more fine-grained access control. One pitfall of using Security Demands is that they don't care what kind of Principal or Identity objects they deal with. This is a pity because it's useful to check for a specific Principal or Identity object to tighten.NET identity-based security.
In the code sample below, the same security check is applied using these two different approaches. The one using IsInRole is stricter because it requires the presence of a WindowsPrincipal.
[PrincipalPermission (SecurityAction.Demand , Role=@"BUILTIN\Administrators")] public void protectedmethod() { WindowsPrincipal wp = Thread.CurrentPrincipal as WindowsPrincipal; if (wp!=null) if(wp.IsInRole(@"BUILTIN\Administrators")==true) Debug.WriteLine ("accessed"); else throw new Exception ("Access Denied"); else throw new Exception ("Access Denied"); }