User re-authentication in MVC application for Action

How to force a user to re-authenticate before performing an action in MVC?

We use Windows authentication. There are some actions that we want to make sure are performed by the user (and do not allow other users to perform these actions if the user forgot to lock his workstation).

Ideally, I can simply write an attribute extending Authorize :

 namespace AuthTest.Controllers { [Authorize(Roles="MyApp")] public class HomeController : Controller { public ActionResult Index() { // A regular action return View(); } [ReAuthenticate] public ActionResult CriticalAction() { // Do something important return View(); } } } 

It looks like I can get the user to re-enter their credentials by indicating that the ReAuthenticate user attribute ReAuthenticate HTTP 401 response in the AuthorizeCore method. However, this required some deception, as Html.ActionLink sent two requests:

 protected override bool AuthorizeCore(HttpContextBase httpContext) { bool ok = base.AuthorizeCore(httpContext); if (!ok) return false; if (httpContext.Session["ReAuthCnt"] == null) { httpContext.Session["ReAuthCnt"] = 1; return false; } else if ((int) httpContext.Session["ReAuthCnt"] < 2) { httpContext.Session["ReAuthCnt"] = (int)httpContext.Session["ReAuthCnt"] + 1; return false; } else { httpContext.Session["ReAuthCnt"] = 0; return true; } } 

Is there a better way to reauthorize?

+6
source share
4 answers

If the user is performing POST, can you add a username and password field to this form, and then check the credentials in Active Directory either in the controller or with ActionFilter?

0
source

If you are allowed the business to actually use the form for re-authentication (in other words, there is a page on which they enter the username and password), you can do the following.

ReauthorizeAttribute

 // custom page where user does type user/pass private string revalidateLoginUrl = "/account/reauth"; private bool? hasReauthenticated = false; protected override bool AuthorizeCore(HttpContextBase httpContext) { var authUrl = HttpContext.Request.Url; hasReauthenticated = httpContext.Session[authUrl] as bool? // could be just (hasReauthenticated) // this look a bit more readable return (hasReauthenticated == true); } public override void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } var isAuthorized = AuthorizeCore(filterContext.HttpContext); var authUrl = filterContext.HttpContext.Request.Url; filterContext.HttpContext.Session[authUrl] = false; if (!isAuthorized) { HandleUnauthorizedRequest(filterContext); } } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // something like this var fullUrl = validateLoginurl + "?returnUrl=" + HttpUtility.UrlEncode(revalidaetLoginUrl); filterContext.HttpContext.Response.Redirect(validateLoginUrl); } 

Reauthmodel

 public class ReauthModel { public string Username { get; set; } public string Password { get; set; } public string ReturnUrl { get; set; } } 

AccoountController.cs ( Confirm username and password in Active Directory? )

 using System.DirectoryServices.AccountManagement; public ActionResult Reauth(string returnUrl) { var model = new ReauthModel(); model.ReturnUrl = returnUrl; return View(model); } [ValidateAntiForgeryToken] public ActionResult Reauth(ReauthModel model) { using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN")) { // validate the credentials bool isValid = pc.ValidateCredentials("myuser", "mypassword"); if (isValid) { Session[model.ReturnUrl] = true; return RedirectTolocal(model.ReturnUrl); } } // not authenticated return RedirectToAction("?"); //or model.Username = string.Empty; model.Passsword = string.Empty; return View(model); } 

I think you can imagine, based on ReauthModel, what the view will look like.

Note. should be used in addition to any other authorization attribute that you use, and not instead. Since the user enters the username and password on the website, you must use SSL (even if it is internal).

0
source

I would approach it differently. It looks like what you REALLY want is a temporary credential boost, similar to UAC or Sudo, but on your site. You probably want that if a certain amount of time has passed, the user must again enter their credentials to access these functions.

The approach I would like to make is to create a custom IPrincipal that will allow you to temporarily add a specific role to the user and expire this role after a certain period of time. This will not be tied to the roles assigned to users that are stored in the database, except, perhaps, only for users who have a specific role, they can be increased.

This way, you can simply perform a password check, temporarily add the role to the list of user roles, and then enable the standard authorization attribute.

0
source

you can get the idea from here, I'm doing a role base. Login here

 [Authorize(Roles = "admin,superadmin")]//Controler Authorization public class ControlController : Controller { [Authorize(Roles = "superadmin")]//action Authorization public ActionResult youraction() { return View(); } } 
-2
source

Source: https://habr.com/ru/post/954540/


All Articles