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) {
(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")) {
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