Where can I upload user information to a session in ASP.NET MVC 5 using Windows Authentication?

I want to use ASP.NET MVC 5 for my web application. I need to use windows authentication .

If I use windows authentication , where is the best way to read user information (userid and roles) and store it in Session ?

I have a way to get user information by username from a database as follows:

 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; } } 
+5
source share
2 answers

You asked two questions (1): the best place to get information about the user and (2) how to save him in the session. I will answer (1) and perhaps show that you do not need to add additional information to the session.

You stated that your application uses Windows authentication, which means that the hard work of user authentication has already been done by IIS / HttpListener before your application receives the request. When you receive the request, there will be a WindowsPrincipal in HttpContext.User . This will already have a Windows username and AD roles, but you want to use additional roles stored in the database ...

You can access your AuthService from anywhere in the application, but probably the best approach is to register the IAuthorizationFilter and do the work there. Following this approach, additional roles and other information that you extract from the database will be available in your controller methods and, more importantly, from any additional library code that should verify user credentials.

Prior to .Net 4.5, if you want to add additional information to WindowsPrincipal , I think that your only choice was to replace the user provided by the system with another object that implemented the IPrincipal interface. This approach is still available (and I recommend), but since the introduction of Windows Identity Foundation (WIF) in .Net 4.5, WindowsPrincipal comes from System.Security.Claims.ClaimsIdentityClaimsIdentity , which supports adding additional roles (and other useful information) to system principle. However, as it turned out by several people, there is an error / function on Windows that can throw an exception The trust relationship between the primary domain and the trusted domain failed when checking roles that were added programmatically. We found that a simple and reliable way to avoid this is to replace the user with a GenericPrincipal .

Required Steps:

(1) create an IAuthorizationFilter .

 class MyAuthorizationFilter : IAuthorizationFilter { AuthService _authService; public MyAuthorizationFilter(AuthService authService) { _authService = authService; } public void OnAuthorization(AuthorizationContext filterContext) { var principal = filterContext.HttpContext.User; if (principal.Identity != null && principal.Identity.IsAuthenticated) { // Add username (and other details) to session if you have a need filterContext.HttpContext.Session["User"] = principal.Identity.Name; // get user info from DB and embue the identity with additional attributes var user = _authService.GetUserInfo(principal.Identity.Name); // Create a new Principal and add the roles belonging to the user GenericPrincipal gp = new GenericPrincipal(principal.Identity, user.RoleNames.ToArray()); filterContext.HttpContext.User = gp; } } } 

(2) Register your filter. This can be registered at the controller level or globally. Typically, you will do this in App_Start\FilterConfig.cs :

 public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new MyAuthorizationFilter(new AuthService())); } } 

(3) Use the application code provided by the GenericPrincipal to answer questions about user ID and other credentials. for example, in your controller method, you can access the username or other β€œclaims” (for example, email address) stored in the GenericPrincipal your filter.

  public ActionResult Index() { ViewBag.Name = HttpContext.User.Identity.Name; if(HttpContext.User.IsInRole("Administrator")) { // some role-specific action } return View(); } 

Since you used the built-in mechanism to record the main roles, you can access user data from anywhere using HttpContext.User or System.Threading.Thread.CurrentPrincipal . You can also use AuthorizeAttribute in your controller methods to declare what actions are available for specific roles or users. eg

  public class HomeController : Controller { [Authorize(Roles = "Administrator")] public ActionResult Admin() { return View(); } 

See MSDN for more information on ClaimsIdentity.

I hope this helps

-Rob

+2
source

First of all: never, never, never store user data in a session. Jokes aside. Just don't do it.

If you are using Windows Auth, the user is in AD. You are using AD to get user information. Microsoft has an MSDN article describing how this should be done.

Long and short is to create a subclass of UserIdentity and extend it with additional properties that you want to return to the user:

 [DirectoryRdnPrefix("CN")] [DirectoryObjectClass("inetOrgPerson")] public class InetOrgPerson : UserPrincipal { // Inplement the constructor using the base class constructor. public InetOrgPerson(PrincipalContext context) : base(context) { } // Implement the constructor with initialization parameters. public InetOrgPerson(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { } InetOrgPersonSearchFilter searchFilter; new public InetOrgPersonSearchFilter AdvancedSearchFilter { get { if ( null == searchFilter ) searchFilter = new InetOrgPersonSearchFilter(this); return searchFilter; } } // Create the mobile phone property. [DirectoryProperty("mobile")] public string MobilePhone { get { if (ExtensionGet("mobile").Length != 1) return null; return (string)ExtensionGet("mobile")[0]; } set { ExtensionSet( "mobile", value ); } } ... } 

In the above code example, a property is added to bind to the mobile user field of the AD user. This is accomplished by implementing the property, as shown, using ExtensionSet , and then annotating the property with the DirectoryProperty attribute to tell it which field it is bound to.

The DirectoryRdnPrefix and DirectoryObjectClass attributes in the class must be consistent with your AD settings.

Once this is implemented, you can get the values ​​simply by specifying their User.Identity . For example, User.Identity.MobilePhone will return the mobile field from AD for the user.

+1
source

All Articles