NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Performing Principal and Identity Demands

Directly Referencing the Principal Object

There are cases where direct access to the Principal object is required. We provide a mechanism to do this easily. This allows one, for example, to access the method for performing impersonation given a WindowsIdentity or to access to behaviors specific in an application defined Principal.

It is also possible to use this mechanism to perform identity/role checks. For example:

If (Thread.CurrentPrincipal.IsInRole(“Administrator”)) {}

This test will succeed if “Administrator” is a valid role within the Principal object.

Similarly, an identity may be checked by

If (Thread.CurrentPrincipal.Identity.Name == “Bob”) {}

The test will succeed if “Bob” matches the name held in the Identity object.

Using the PrincipalPermission Object

A mechanism for checking the identity and/or roles consistent with those for resource and code identity permissions is also supported. This allows one to leverage the defined language constructs for both declarative and imperative security actions.

This functionality builds on the Code Access Security permission objects and the IPermission abstract Interface specification defining a “PrincipalPermission” object to enable this functionality. The PrincipalPermission exposes a constructor that accepts an identity string and a role string. For example:

   String id = “Bob”;
   String role = “Administrator”;
   PrincipalPermission principalPerm = new PrincipalPermission(id, role);

To match the active Principal object, and associated Identity object, both the specified identity and role must match. A NULL identity string is interpreted as a request to match any identity. A NULL role string will match any role. By implication, PrincipalPermission(NULL, NULL) will match the identity and roles in any Principal object.

It is also possible to construct a PrincipalPermission that only checks for whether the Identity represents and authenticated or unauthenticated entity. In this case, the name and roles are ignored.

To determine if the active Principal object matches the identity and/or role for a given PrincipalPermission, one does a “Demand” on the permission object. This is simply a check against the active Principal, there is no dependence on code in the call chain and no stack walk is required. Hence, the Demand() and DemandImmediate() methods on the PrincipalPermission always return the same result.

As with other permissions, one may intersect and/or union the PrincipalPermission objects. An intersection is somewhat non-sensical since we expect individual PrincipalPermission objects to be orthogonal. But, we define it for completeness. The result if intersecting PrincipalPermission objects is the identity and/or role that are common to the set , where intersecting non-comparable entities returns the empty string. For example:

   String id1 = “Bob”;
   String role1 = “Administrator”;
   PrincipalPermission PrincipalPerm1 = new PrincipalPermission(id1, role1);
   String id2 = “Louise”;
   String role2 = “Administrator”;
   PrincipalPermission PrincipalPerm2 = new PrincipalPermission(id2, role2);

PrincipalPerm1.Intersect(PrincipalPerm2) will return an object equivalent to that created by

   String id3 = “”; // i.e., no identity can simultaneously represent both Bob and Louise
   String role3 = “Administrator”;
   PrincipalPermission PrincipalPerm3 = new PrincipalPermission(id3, role3);

In effect, PrincipalPerm3.Demand() would only succeed if we had an unauthenticated principal (with name = “”) allowed to act in the Administrator role.

A union will create a permission object representing the criteria of a given set of individual PrincipalPermission objects and is useful for compactly representing a set of conditions to test. Given the above example,

(PrincipalPerm1.Union(PrincipalPerm2)).Demand()

will succeed if the Principal object represents:

Subset operations will determine if a PrincipalPermission instance is a strict subset of another. Effectively this means the identities and roles must exactly match or one must be NULL

Declarative Demands

Consistent with Code Access Security, it is possible to place Declarative demands for identity and/or role compliance on any Class, Method, or Event (see NGWS Runtime Security Permissions). These are interpreted as requirements that must be satisfied for the associated method(s) to be called. If they are not met, then a call attempt will result in a SecurityException.

The Declarative syntax is language specific, but will indicate the type of check required. It is only valid to request a runtime ‘Demand’ of this permission, i.e., the SecurityAction enum value is SecurityAction.Demand.

Use of LinkDemand or InheritanceDemand is not valid since these checks are only done once, on the first reference between a caller and callee. This is useful for code evidence related permissions, since these don’t change after loading. But, there is nothing to prevent the same code path from being executed multiple times on a behalf of a different entity as reflected in the Principal and Identity objects. Also Assert, Deny, and PermitOnly actions aren’t valid, as these aren’t defined for an object implementing the IPermission interface.

Declarations may affect multiple Methods within an Assembly:

Imperative Demands

Imperative demands for a given identity or role can be easily incorporated into managed code. Doing this requires the code create a new PrincipalPermission object specifying the identity and role of interest. For example, checking for an identity of “Bob” and a role of “Administrator” can be done by:

   String id = “Bob”;
   String role = “Administrator”;
   PrincipalPermission PrincipalPerm = new PrincipalPermission(id, role);
   try {
      PrincipalPerm.Demand();
      // code here executes when identity and role match
  }
 catch (SecurityException) {
      // error handling code 
 }