User is still signed in after AuthenticationManager.SignOut() - asp.net

When I sign out a user in a controller, User.Identity.Authenticated is still true on the returned view.
If I refresh the page again, then User.Identity.Authenticated is false
// GET: /Account/SessionExpired
[AllowAnonymous]
public ActionResult SessionExpired()
{
AuthenticationManager.SignOut();
//Clear the session
SessionHelper.Clear();
return View();
}
Is it normal?
Thank you

Yes that is normal as the authorization is checked before the action executes. If you want to log out before that you have to do it before that, for example with a custom attribute

The standard MVC template in Visual Studio uses a RedirectToAction to instead of returning a View. That way the browser is automatically redirected to for example the home/index action from a new request.

// GET: /Account/SessionExpired
[AllowAnonymous]
public ActionResult SessionExpired()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
//Clear the session
SessionHelper.Clear();
return View();
}

Related

How can I force the user login before go to any where in my application?

I'm working on the asp.net mvc5 project, my problem is forcing the user login then they can go anything on my site. I'm using Session to check user login or not (I'm not using Identity or Authorization).
Here is my Login code:
[HttpPost]
public ActionResult Login(User user)
{
if (IsValid(user.username, user.password))
{
Session["username"] = user.username;
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Login details are wrong.");
}
return View(user);
}
I can check the user login or not with Session but I cannot deny the user access to the link, if I have to do this manually, I will need to add the block code below to any action in every controller I have.
public ActionResult Index()
{
if (Session["username"] != null)
{
//then user can go anywhere with any link
}
else
{
//user cannot go to here without login
}
}
There is any way I can force the user to redirect to the login page (if they are not login) when they click on any link or type the link in the browser? I was searching about config the route or using filter config but it seems not to solve my problem. I hope there has the general way to do this without adding the check-code manually to each controller/action.
Thanks for reading my problem, I will be very appropriated any comment to help me solve this.
One possible way to tackle on this globally is to override the OnActionExecuting method on the controller, that does the check and redirects to the homepage if no user is logged or allows the action if there is a user.
This can be done on a base controller so that it applies to all the website (by making all controllers inherit from this one).
public abstract class LoginRequiredController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Session["username"] != null)
{
base.OnActionExecuting(filterContext);
}
else
{
//Redirect to the main page, or login, or somewhere else, without running the requested action
filterContext.Result = Redirect("/");
return;
}
}
}
Controllers inheriting from this one will check on each request that there is a user, and redirected to the main page in case there isn't one, without needing to copy/paste this check for each method.
Of course, the login controller should not inherit from it or it would be impossible to login at all.

Include JavaScript based on ActiveDirectory Membership

I've got a single page application and in the start page I've linked to the ActionResult "_ADMIN()"
#Html.Action("_ADMIN")
Depending on the user's group membership, this ActionResult returns either an EmptyResult or its view:
public ActionResult _ADMIN()
{
if (User.IsInRole("admin"))
{
return View();
}
else
{
return new EmptyResult();
}
}
Its view consists of this one line:
#Scripts.Render("~/bundles/admin")
This works but feels suboptimal. I could copy the start page and create seperate ones for non-admins and admins, but that would be even more suboptimal. I'm using MVC 4.
What's a better way to include a bundle of JavaScript only if the current user is in a certain Active Directory group?
You can add scripts depending on roles. Like that :
if (User.IsInRole("admin"))
{
#Scripts.Render("~/bundles/admin")
}
And on your Action method you add attribute then the user will be automatically redirected to the login page if it does not have rights. You can add this attribute also on whole class.
[Authorize(Roles = "admin")]
I would only show the link to admin users:
if (User.IsInRole("admin"))
{
#Html.Action("_ADMIN")
}
Then, in the event a non-admin tried to access the action method, I would block the request at the action method:
[Authorize(Roles = "admin")]
public ActionResult _ADMIN()
{
return View();
}

How do I call an Index action and conditionally pass it a value in an ASP.NET MVC app

I have an index action on a controller as follows...
public ActionResult Index(string errorMsg = "")
{
//do stuff
ViewBag.ErrorMsg=erorMsg;
return View();
}
I have another action that is an http post for Index.
When there is something wrong I want to reload the Index page and show the error...
I have my view already conditionally showing errorMsg. But I cannot figure out how to call Index and pass in the error string?
Typically, you'd just share the view between the two actions. I'm guessing you have actions that look something like this (the more info you provide about what index does, the better my example will be):
public ActionResult Index()
{
return View();
}
[HttpPost, ActionName("Index")]
public ActionResult IndexPost()
{
if (!ModelState.IsValid)
{
ViewBag.ErrorMsg = "Your error message"; // i don't know what your error condition is, so I'm just using a typical example, where the model, which you didn't specify in your question, is valid.
}
return View("Index");
}
And Index.cshtml
#if(!string.IsNullOrEmpty(ViewBag.ErrorMsg))
{
#ViewBag.ErrorMsg
}
#using(Html.BeginForm())
{
<!-- your form here. I'll just scaffold the editor since I don't know what your view model is -->
#Html.EditorForModel()
<button type="Submit">Submit</button>
}
If I understand you correctly you just need to hit the url with the errorMsg in the query string:
/*controllername*/index?errorMsg=*errormessage*
However, when there is something wrong you don't necessarily need to reload the page. Seems like you might be approaching this in the wrong way..?
You can use RedirectToAction to redirect to the page, with a querystring for errorMsg value.
[HttpPost]
public ActionResult Index(YourViewModel model)
{
try
{
//try to save and then redirect (PRG pattern)
}
catch(Exception ex)
{
//Make sure you log the error message for future analysis
return RedirectToAction("Index",new { errorMs="something"}
}
}
RedirectToAction issues a GET request. So your form values will be gone, because HTTP is stateless. If you want to keep the form values as it is in the form, return the posted viewmodel object again. I would get rid of ViewBag and add a new property called ErrorMsg to my ViewModel and set the value of that.
[HttpPost]
public ActionResult Index(YourViewModel model)
{
try
{
//try to save and then redirect (PRG pattern)
}
catch(Exception ex)
{
//Make sure you log the error message for future analysis
model.ErrorMsg="some error";
return View(model);
}
}
and in the view you can check this model property and show the message to user.

Why is using a URL containing a questionmark when redirecting gets a “potentially dangerous request”?

I'm using MVC3 and in my view I have the following code block;
Response.Redirect(#Url.Action("index","home", new {error = "test"}));
so the url i would expect is http://marketurk.co.uk/?error=test but I get is this http://marketurk.co.uk/%3Ferror=test so that I get potentially dangerous request.
does anyone have the same issue, and could tell me what I'm doing wrong?
UPDATE:
I moved my logic into a controller method as follows;
public ActionResult Index()
{
if (!User.Identity.IsAuthenticated)
return RedirectToAction("index", "home", new { error = "test" });
return View();
}
It still redirects to http://marketurk.co.uk/%3Ferror=test
This is typically logic which would go into the controller I'd say. There's the ever present unwritten rule that your view should contain as little logic as possible, unless it's intended for presentation purposes.
In your controller action you could verify your view model, and if it's invalid you should use the built-in RedirectToAction:
public ActionResult SomeAction()
{
// build your viewmodel here //
if(/* viewmodel is invalid */)
return RedirectToAction("index", "Home", new { error = "test" });
else
return View( /* your viewmodel */);
}
Answer should be something:
as ? encoded to %3F,
by using Html.Raw you can keep ?
Response.Redirect(Html.Raw(Url.Action("index","home", new {error = "test"})));
are you using an OnActionExecuting function for that Controller? Maybe problem caused by another line of code after your request?

MVC3 logged in User can see only own stuff apart from Admin

A novice to asp.net and mvc3. I am learning by setting myself challenges/developing an application. I tag all record tables where users interact with ProviderUserKey. Now I want to be able to restrict users logged in to be able to edit or delete their own records only but administrators can edit or delete any. I have been using scaffolding to generate controllers and views etc. for eg code for editing`// POST: /Post/Edit/5
[HttpPost]
public ActionResult Edit(PJpost pjpost)
{
if (ModelState.IsValid)
{
db.Entry(pjpost).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(pjpost);
}`
Any help will be highly appreciated.
If you have a generic Edit method/action and you would like to keep it that way, I would add a method in your controller somethink like ValidateOwnership(record). This method would need to verify if CurrentUser's ID is matching the one on the record and if user is a member of particular role - that can be done with RoleManager class. Method would return true/false.
When you got it ready just put the call to the method in your code after ModelState validation. It would look like this
[HttpPost]
public ActionResult Edit(PJpost pjpost)
{
if (ModelState.IsValid)
{
if(IsOwnershipValid(pjpost){
db.Entry(pjpost).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
else {
ModelState.AddModelError("ERROR","You're not allowed to do that");
return View(pjpost);
}
}
return View(pjpost);
}
EDIT :
So the OwnershipValidation could look like this :
public bool ValidateOwnership(Pjpost pjpost) {
if (pjpost.MemUID == Membership.GetUser().ProviderUserKey.ToString())
{
return true;
}
else
{
return false;
}
}
I hope this is what you meant.
You need to look in to user roles and the process of authorization usually, MVC provides a registration and log in in it template including the account controller. To restrict user access you have to assign roles to users.
the code behind it would look something like this.
[Authorize(Roles="admin")]
public ActionResult admin()
{
//Action gives an admin rights since the user is in the admin role
return View();
}
[Authorize(Roles="manager")]
public ActionResult manager()
{ //give a managers rights since user is im managers roles.
return View();
}

Resources