The following is an attempt to give a very brief overview of ASP.NET's authentication/authorization machinery. ASP.NET uses the
Provider Model to handle authentication, authorization (roles), user info, and profile info (think user settings). ASP.NET provides built in providers (
source code), or custom providers can be implemented.
HttpContext.Current
- .User (IPrincipal)
- .IsInRole(string)
- .Identity (IIdentity)
- .IsAuthenticated (bool)
- .Name (string)
- .AuthenticationType (string)
MembershipProvder
- .ValidateUser(string username, string password)
- .GetUser(string username, bool updateLastActivityDate) (returns MembershipUser)
- .Comment
- .Email
- .LastActivityDate
- .UserName
- .ProviderUserKey
FormsAuthentication
- .Authenticate(string username, string password) uses web.config or MembershipProvider.ValidateUser
- .SetAuthCookie(string username, bool createPersistentCookie)
- .RedirectToLoginPage()
- .RedirectFromLoginPage(string username, bool createPersistentCookie)
RoleProvider
- .GetRolesForUser(string username) (returns string[])
ProfileProvider
When a
profile section is created in web.config, ASP.NET automatically creates a class derived from ProfileBase and creates strongly-typed property accessors.
- .FindProfilesByUserName(string)
- .SetPropertyValues(...) returns the different properties (boxes in which you put user-specific data) available
- .Save()
ProfileBase
- .Initialize(string username, bool isAuthenticated) not intended to be invoked directly
- .Create(string username)
- .Item(string propertyName)
- .Initialize(string username, bool isAuthenticated)
A built-in MembershipProvider can be used, or a custom one can be implemented. The same goes for RoleProvider.
One changes the IPrincipal object in the AuthenticateRequest event.
Another option is to implement custom authentication by implementing an IHttpModule:
http://www.codeproject.com/aspnet/AspNetCustomAuth.asp
See a post made on a MSDN forum (with only one response):
I've been trying to decode the provider model as it relates to authentication, authorization, and user data. I think I have it mostly figured out, but there are several gaps in my knowledge at this point.
I understand MembershipProvider to be responsible for managing anything to do with authentication — who the user is. It is my impression that MembershipProvider is not designed to be extended to support general attributes of users, such as address or telephone number; is this correct?
I understand RoleProvider to be responsible for managing all things related to authorization — is this user allowed to do X. On the one hand, the name of the provider indicates that this is restricted to roles, which does not work out when permissions are not stored at a per-role level. I do not relish the thought of creating a role for every distinct permission a user could have so that I can assign permissions on a granular level; am I correct in assuming that the ASP.NET designers did not wish to impose this? Does it make sense to extend RoleProvider to support all things relating to authentication so that authorization information is centralized?
ProfileProvider is more of an enigma to me. Is it designed to hold core information about users, such as birthdate, or is it designed to hold preferences? In particular, I see core information as having a 1:1 relationship with users, whereas other information might have a 1:n relationship (like having multiple credit cards). On the one hand, ProfileProvider appears to support choosing from multiple profiles, but it doesn't seem to support anything 1:n. Now, this could be accomplished by creating a profile with collections for the 1:n data, but then I wonder about the support for having multiple profiles for a given user. Then we have the issue of default ProfileProviders storing data in a denormalized fashion: is it considered good practice to implement a ProfileProvider that grabs user data from multiple tables, sort of like a mini O/RM? Another option for storing user is to simply store an object containing the relevant in the session; how does this compare to use of ProfileProvider?
Note that I'm looking for elegant design that does not sacrifice much in the way of performance; it seems the ProfileProvider might be been designed to do what I'm trying to do, but I'm not sure. Essentially, I'd like to establish boundary conditions for the different providers ("this provider was designed to do X by storing data Y, extending it much past Z is going to get ugly").
What is the preferred way for implementing caching of the data used by different providers? One downside of using ProfileProvider instead of the session is that the session stores data for the "correct" period of time, but I have to assume that intelligently caching user data could be as effective, if not more (items could expire/be kicked out before a session ends but after the user performs his/her last action). Are there some nice examples of elegantly caching data for the providers so that the database is not pounded?
How does IPrincipal fit into the above? It seems to include both authorization (IPrincipal members) and authentication (IIdentity members). Do I override the assignment to HttpContext.Current.User (in AuthenticateRequest) with a custom class implementing IPrincipal, pass HttpContext.Current.User to my data layer, have it cast the object to the custom class, and call authentication methods on it which delegate to RoleProvider?