Pages

Wednesday, October 28, 2009

Using GenericIdentity for Cross Platform Authentication in the .NET framework

Let me say from the beginning that this should be a lot easier.

Basic Authentication

When designing a WinForms application, the most straightforward way to authenticate a user is using NTLM or Active Directory... It's built right into the OS and you don't need to deal with password dialogs and lost password questions at all - just ask Windows who the user is, like this...

using System.Security.Principal;
...
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();

That was easy... now how about using a web application?  That gets a little more complicated.  If the user is coming in over the intranet, then IIS knows who it is, but if they are accessing your site over the internet, it uses the whole aspnet security setup to create users and roles and permissions.  This is very easy to use as well, and for the most part requires no coding at all - but if you need to retrieve the name of the authenticated user, you would use something like this...

using System.Web.Security;
...
MembershipUser User = Membership.GetUser();
roles = System.Web.Security.Roles.GetRolesForUser();

Rolling Your Own

What if you need a robust set of libraries that can access identity information regardless of the data source?  Thats where the GenericIdentity and GenericPrincipal objects come into play.
For deployment into a mixed web/winforms environment, these components are very useful as they can migrate without regard to the source of the user and role data.

Creating a Generic Identity

...empty

string userName = "somebody";
GenericIdentity authenticatedGenericIdentity = new GenericIdentity(userName, "Database");

This creates a generic identity named somebody who was validated using an authenticacationType of "Database".

...from Windows

WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
string authenticationType = windowsIdentity.AuthenticationType;
string userName = windowsIdentity.Name;
GenericIdentity authenticatedGenericIdentity = new GenericIdentity(userName, authenticationType);

...from a database

string connectionstring = @"Data Source=.\SQLExpress;Initial Catalog=PermsLib;Integrated Security=True";
SqlConnection MyConn = new SqlConnection(connectionstring);
MyConn.Open();

SqlCommand Query1 = new SqlCommand(@"Select * from logins where username=@user and password=@pwd and account_locked=0;", MyConn);
Query1.Parameters.AddWithValue("@user", username);
Query1.Parameters.AddWithValue("@pwd", password);

SqlDataReader myReader = Query1.ExecuteReader();

if (myReader.HasRows)
{
string userName = username;
GenericIdentity authenticatedGenericIdentity = new GenericIdentity(userName, "Database");
return authenticatedGenericIdentity;
} else {
throw new System.Security.SecurityException("invalid user");
}

The great thing is that you can toss these objects around in a mixed application, and they will travel nicely from place to place.

What is a GenericPrincipal?

That explains the identity object, but what is a GenericPrincipal?
As far as I can tell the Generic principal's only use is to contain both a GenericIdentity object, and a list of roles assigned to that identity.  So think of it as a baggie with an ID card and a ring of keys (roles/permissions).
Loading a GenericPrincipal  object is easy, all you need is a GenericIdentity, and a string array of roles.
string[] userRoles = { "Administrator", "Manager" }; GenericPrincipal MyPrincipal = new GenericPrincipal(userIdentity, userRoles);
The source of the roles data is unimportant, it can be hard coded, from a database, XML, or even read directly from ActiveDirectory sources.

Share This!

Contact Us

Name

Email *

Message *