This article has been excerpted from book "The Complete Visual C# Programmer's Guide" from the Authors of C# Corner.

The System.Security.Principal namespace defines a principal object that represents the security context under which code is running.

IIdentity Interface

IPrincipal Interface

WindowsIdentity Class

The WindowsIndentity class implements the IIdentity interface. It represents the identity of the user based on a method of authentication supported by the Windows operating system. A Windows identity provides the ability to impersonate another user so resources can be accessed on that user's behalf.

WindowsPrincipal Class

The WindowsPrincipal class implements the IPrincipal interface. It represents Windows users and their roles, which are simply the Windows groups to which the users belong.

GenericIdentity Class

The GenericIdentity class implements the IIdentity interface. It represents the identity of the user based on a custom authentication method defined by the application.

GenericPrincipal Class

The GenericPrincipal class implements the IPrincipal interface. It represents users and roles that exist independent of Windows users and their roles. Essentially, the generic principal is a simple solution for application authentication and authorization.

PrincipalPermission Class

PrincipalPermission objects allow code to perform actions (Demand, Union, Intersect, etc.) against the current user identity in a manner consistent with the way those actions are performed for code access permissions and identity permissions. PrincipalPermission can be issued as an imperative demand, as shown at the top of Listing 22.27, or as a declarative demand, as the bottom of the listing shows.

Listing 22.27: IsInRole Example

PrincipalPermission p = new PrincipalPermission(null, "BUILTIN\Administrator");
p.Demand();

// or it can be issued as a declarative demand as shown in the line below
[PrincipalPermission(SecurityAction.Demand, Role=@"BUILTIN\Administrators")]

CurrentPrincipal Property

The CurrentPrincipal property of the Thread class is a static proprety that allows you to get or set the current security context of the user. You can use the CurrentPrincipal property of the System.Threading.Thread class in order to get the current WindowsPrincipal object as in the line of code below:

WindowsPrincipal myWindowsPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;

IsInRole Method

You can check role membership by calling the IsInRole method on the principal object. You can use IsInRole with WindowsPrincipal and CurrentPrincipal. Listing 22.28 shows a simple use of the IsInRole method.

Listing 22.28: IsInRole Example

// IsInRole
WindowsPrincipal winpr = (WindowsPrincipal)Thread.CurrentPrincipal;

// WindowsBuiltInRole is an enumeration!
// Is winpr object in role of Administrator?
winpr.IsInRole(WindowsBuiltInRole.Administrator);

// Is the current thread principal in role of Administrator?
System.Threading.Thread.CurrentPrincipal.IsInRole(@"BUILTIN\Administrator");

Impersonate and ImpersonateContext

If your application must impersonate a Windows account that has not been attached to the current thread, you must retrieve that account's token and use it to activate the account:

Listing 22.29 illustrates how you can accomplish impersonation.

Listing 22.29: Impersonation Example

// impersonation
public class ImpersonationExample
{
[DllImport("ADVAPI32")]
private unsafe static extern int LogonUser(
String lpszUsername,
String lpszDomain,
String lpszPasswords,
int dwLogonType,
int dwLogonProvider,
out InPtr phToken
);

public void anyfunction()
{
InPtr lToken;
int lRetVal = 0;
lRetval = LogonUser(strUserName, strDomain,
strPassword, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, out lToken);

if (lRetval == 0)
{
Console.WriteLine("Login error occurred!");
return;
}

WindowsIdentity ImpId = new WindowsIdentity(lToken);
WindowsImpersonationContext ImpContext = ImpId.Impersonate();

// you are impersonating another user now in this
// thread!
// execute some managed and unmanaged code now
ImpContext.Undo();
}
}

Listing 22.30 creates two PrincipalPermission objects representing two different users. The union demand succeeds only if user mcb is in the role of director or user mindcracker is in the role of officer.

Listing 22.30: PrincipalPermission Union Example

// Union Demand
String id1 = "mcb";
String role1 = "Director";
PrincipalPermission PrincipalPerm1 = new PrincipalPermission(id1, role1);
String id2 = "mindcracker";
String role2 = "Officer";
PrincipalPermission PrincipalPerm2 = new PrincipalPermission(id2, role2);
(PrincipalPerm1.Union(PrincipalPerm2)).Demand();

In Listing 22.31, the current WindowsIdentity class is transformed into a WindowsPrincipal class. Then all of the identity and principal properties are written to the system console.

Listing 22.31: WindowsIdentity to WindowsPrincipal Example

// WindowsIdentity illustrated
WindowsIdentity MyIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal MyPrincipal = new WindowsPrincipal(MyIdentity);

//Principal values.
Console.WriteLine(MyPrincipal.Identity.Name);
Console.WriteLine(MyPrincipal.Identity.AuthenticationType);
Console.WriteLine(MyPrincipal.Identity.IsAuthenticated.ToString());

//Identity values.
Console.WriteLine(MyIdentity.Name);
Console.WriteLine(MyIdentity.AuthenticationType);
Console.WriteLine(MyIdentity.IsAuthenticated.ToString());
Console.WriteLine(MyIdentity.IsAnonymous.ToString());
Console.WriteLine(MyIdentity.IsGuest.ToString());
Console.WriteLine(MyIdentity.IsSystem.ToString());
Console.WriteLine(MyIdentity.Token.ToString());

Listing 22.32 illustrates GenericIdentity class usage.

Listing 22.32: GenericIdentity Example

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal myUser = WindowsPrincipal)System.Threading.Thread.CurrentPrincipal;
GenericIdentity MyIdentity = new GenericIdentity(myUser.Identity.Name.ToString());

String[] MyStringArray = {"Role1", "Teller"};
GenericPrincipal MyPrincipal = new GenericPrincipal(MyIdentity, MyStringArray);
System.Threading.Thread.CurrentPrincipal = MyPrincipal;

//Return user values
String Name = MyPrincipal.Identity.Name;
bool Auth = MyPrincipal.Identity.IsAuthenticated;
bool IsInRole = MyPrincipal.IsInRole("Role2");

if(IsInRole)
{
Console.WriteLine("The test was successful as a user in the user-defined role of Role1");
}
else
{
Console.WriteLine("The test was not successful!");
}

In Listing 22.33, declarative demands for PrincipalPermission and PrincipalPermissionAttribute are illustrated. The attribute adjustment says that only a principal in the role of Role1 may execute these functions.

Listing 22.33: Declarative Identity Example

[PrincipalPermission(SecurityAction.Demand, Role=@"Role1")]

private string MyFunction()
{
return "Declarative control for the role of Role1 is truly successfully. his function can be executed by you!";
}

[PrincipalPermissionAttribute(SecurityAction.Demand, Name = "MyUser", Role = "Role1")]

public static void PrivateInfo()
{
//Output of private data
Console.WriteLine("You have access to the private data!");
}

Conclusion

Hope this article would have helped you in understanding System.Security.Principal in .NET. See other articles on the website on .NET and C#.

visual C-sharp.jpg
The Complete Visual C# Programmer's Guide covers most of the major components that make up C# and the .net environment. The book is geared toward the intermediate programmer, but contains enough material to satisfy the advanced developer.