I want to use the ASP.NET MVC 5 for my web app. I need use the windows authentication
.
If I use the windows authentication
where is the best place for reading user information (userid and roles) and store its to the Session
?
I have the method for getting the user information by username from the database like this:
public class CurrentUser
{
public int UserId { get; set; }
public string UserName { get; set; }
public Roles Roles { get; set; }
}
public enum Roles
{
Administrator,
Editor,
Reader
}
public class AuthService
{
public CurrentUser GetUserInfo(string userName)
{
var currentUser = new CurrentUser();
//load from DB
return currentUser;
}
}
First and foremost: never, never, never store user details in the session. Seriously. Just don't do it.
If you're using Windows Auth, the user is in AD. You have use AD to get the user information. Microsoft has an MSDN article describing how this should be done.
The long and short is that you create a subclass of
UserIdentity
and extend it with the additional properties you want to return on the user:In the example code above, a property is added to bind to the AD's user's
mobile
field. This is done by implementing the property as shown utilizingExtensionSet
, and then annotating the property with theDirectoryProperty
attribute to tell it what field it binds to.The
DirectoryRdnPrefix
andDirectoryObjectClass
attributes on the class need to line up with how your AD is set up.Once this is implemented, then you will be able to get at the values simply by referencing them off
User.Identity
. For example,User.Identity.MobilePhone
would return themobile
field from AD for the user.You've asked two questions (1) the best place to obtain user information and (2) how to store it in the Session. I'll answer (1) and in so doing perhaps show that you need not put any additional information in the session.
You've stated that your application is using Windows Authentication, so that means the hard work of authenticating the user has already been done by IIS/HttpListener before your app receives the request. When you receive the request there will be a
WindowsPrincipal
inHttpContext.User
. This will have the windows username and AD roles already established, but you wish to use additional roles stored in the database...You could access your
AuthService
from anywhere in your application, but probably the best approach is to register anIAuthorizationFilter
and do the work there. By following this approach, the additional roles and other information you fetch from the database will be available in your controller methods and, perhaps more importantly, from any additional library code that needs to check user credentials.Prior to .Net 4.5, if you wanted to add additional information to the
WindowsPrincipal
I think your only choice was to replace the system-provided User with another object that implemented theIPrincipal
interface. This approach is still available (and what I recommend), but since the introduction of Windows Identity Foundation (WIF) in .Net 4.5,WindowsPrincipal
is derived fromSystem.Security.Claims.ClaimsIdentityClaimsIdentity
, which supports adding additional roles (and other useful information) to the system-provided principal. However, as several people have found, there is a bug/feature in Windows which can cause an exceptionThe trust relationship between the primary domain and the trusted domain failed
to be thrown when checking roles that have been added programmatically. We have found that a simple and reliable way to avoid this is to replace the User with aGenericPrincipal
.Steps required:
(1) create an
IAuthorizationFilter
.(2) Register your filter. This can be registered at the controller level or globally. Typically you will do this in
App_Start\FilterConfig.cs
:(3) Use the provided
GenericPrincipal
in your application code to answer questions about the user identification and other credentials. e.g. in your controller method you can access the username or any other "claims" (e.g. email address) stored in theGenericPrincipal
by your filter.Because you've used the built-in mechanism to record Principal roles, you can access user details from anywhere using
HttpContext.User
orSystem.Threading.Thread.CurrentPrincipal
. Also you can use theAuthorizeAttribute
in you controller methods to declare which actions are available to certain roles or users. e.g.See MSDN for further details about ClaimsIdentity
I hope this helps
-Rob