Issue in logout - asp.net-mvc

In my web application, I want to set cookies, but while keeping that, i am having issues while logging out.
The Code is given below:
#region Logout
public ActionResult Logout()
{
Session.Clear();
HttpContext.Session["var1"] = null;
HttpContext.Session["var2"] = null;
HttpContext.Session["var3"] = null;
SetCookie("XXXX", XXXX, 30);
return View();
}
#endregion
#region Set Cookie
private void SetCookie(string CookieName, string CookieValue, int CookieLifeDay)
{
if (HttpContext.Request.Cookies[CookieName] == null)
{
var cookie = HttpContext.Response.Cookies[CookieName];
cookie.Expires = DateTime.Now.AddDays(CookieLifeDay);
cookie.Value = CookieValue;
HttpContext.Response.Cookies.Add(cookie);
}
else
{
var cookie = HttpContext.Request.Cookies[CookieName];
cookie.Expires = DateTime.Now.AddDays(CookieLifeDay);
cookie.Value = CookieValue;
HttpContext.Response.Cookies.Add(cookie);
}
}
#endregion
When i am logging out first time, it shows logout succeessfull, but when i click the back button, it enters to the last page accessed by user. while second time , i click the logout button. I can successfully logout. It has been a major issue in this web application. Any type of help is highly solicited.

Use there to remove Session
public ActionResult Logout()
{
Session.Clear();
Session.RemoveAll();
Session.Abandon();
return RedirectToAction("Login", "Home");
}

You can use
Authentication.Logout();

Related

Retrieve Windows Identity after HttpUnauthorizedResult for IAuthenticationFilter

I have a IAuthenticationFilter will check the user group in SharePoint:
public class BasicAuthFilter : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
string userLoginName = filterContext.RequestContext.HttpContext.User.Identity.Name;
if (SecurityManager.Auth(userLoginName))
return;
else
filterContext.Result = new RedirectResult(new UrlHelper(filterContext.RequestContext).Action("AccessDenied", "Error"));
}
...
}
}
It will run on every request but except ErrorController
[AllowAnonymous]
public class ErrorController : Controller
...
// Display view and link for "Logout"
public ActionResult AccessDenied()
{
return View();
}
// GET: Logout
[OutputCache(VaryByParam = "*", Duration = 0, NoStore = true)] // disable caching
public ActionResult Logout()
{
string currentUser = User.Identity.Name;
int AuthenticationAttempts = 0;
if (Session["AuthenticationAttempts"] == null || !int.TryParse(Convert.ToString(Session["AuthenticationAttempts"]), out AuthenticationAttempts))
AuthenticationAttempts = 0;
AuthenticationAttempts += 1;
if (AuthenticationAttempts == 1)
{
Session["PrevUser"] = User.Identity.Name;
Session["AuthenticationAttempts"] = AuthenticationAttempts;
return new HttpUnauthorizedResult();
}
else if (string.Compare(Convert.ToString(Session["PrevUser"]), currentUser, true) == 0) // Somehow it will have echo back, ignore it
{
return new HttpUnauthorizedResult();
}
else
{
Session.Abandon();
Session.Clear();
return RedirectToAction("Index", "Home");
}
}
}
When the Error Controller return HttpUnauthorizedResult, the browser will prompt a login. And I can get the new user name from User.Identity.Name in ErrorController.
However, when it redirect to HomeController, the user was reset to original one, I tried following but still the same
filterContext.RequestContext.HttpContext.User.Identity.Name
filterContext.HttpContext.User.Identity.Name
filterContext.Principal.Identity.Name
Do I miss something or I should assign the principal after user input?
For anybody encounter the same issue, please make sure you have test it with IIS.
This method work but cannot work in IISExpress.

ASP.Net MVC - Cookie Remember Me

Hi Trying to create a simple username cookie.
seems to add but when I refresh the page the cookie has gone, any ideas?
[HttpGet]
public ActionResult Login()
{
var model = new ViewModels.UserCredentials();
ViewBag.Title = "Login";
model.UserName = CheckLoginCookie();
model.RememberMe = !string.IsNullOrEmpty(model.UserName);
return View("Login",model);
}
private string CheckLoginCookie()
{
if (Response.Cookies.Get("username") != null)
{
return Response.Cookies["username"].Value;
}
return string.Empty;
}
[HttpPost]
public ActionResult Login(ViewModels.UserCredentials credentials)
{
//do lots of stuff
//Create username remember cookie
if (credentials.RememberMe)
{
HttpCookie ckUserName = new HttpCookie("username");
ckUserName.Expires = DateTime.Now.AddSeconds(500)
//yeap i know its only 500;
ckUserName.Value = credentials.UserName;
Response.Cookies.Add(ckUserName);
}
}
To check the cookies cming from the client you need to look in to Request not the Response.
private string CheckLoginCookie()
{
if (Request.Cookies.Get("username") != null)
{
return Request.Cookies["username"].Value;
}
return string.Empty;
}

UserManager.FindByNameAsync slow in ASP.NET MVC

I have a site based on ASP.NET MVC framework. Although i am using async method to login the user, i have found that it takes forever to get user logged in into the site. I have used Visual Studio's diagnostic tools and found that this line takes most of the time during the code execution.
var user = await UserManager.FindByNameAsync(model.Email);
Full Code:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user != null)
{
var getPasswordResult = UserManager.CheckPassword(user, model.Password);
if (getPasswordResult)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
var identity = await UserManager.CreateIdentityAsync(
user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = model.RememberMe }, identity);
if (model.RememberMe == true)
{
HttpCookie cookie = new HttpCookie("UsersLogin");
cookie.Values.Add("UserName", model.Email);
cookie.Expires = DateTime.Now.AddDays(15);
Response.Cookies.Add(cookie);
}
return RedirectToAction("NavigateAuthUser", "Home", new { ReturnUrl = returnUrl });
}
else
{
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
return new EmptyResult();
}
Any suggestion to improve the performance?
Thanks
Sanjeev
For workaround I use:
_db.Users.First(x => x.UserName == User.Identity.Name);
But I'm sure this is not the best way
Develop my own method FindByEmail, this way I greatly improve the perfomance
public AspNetUsers FindByEmail(string Email)
{
try
{
var _modelo = new SIGMAEntities();
return _modelo.AspNetUsers.FirstOrDefault(x => x.Email.Trim().ToLower() == Email);
}
catch (Exception)
{
throw;
}
}

Authorize Attribute with Roles

I want to implement my custom authorization, I wonder what is wrong with my code even I got the user credentials correctly it still redirects me to my Login Method, please see the code below
Edit: I have successfully implemented the Authorize Attribute with Roles, for future readers please see code below
Login Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
PasswordHasher passwordVerify = new PasswordHasher();
var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
select new { acc.username, acc.password}).FirstOrDefault();
if (query != null)
{
if (ModelState.IsValid)
{
var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
switch (result)
{
case PasswordVerificationResult.Success:
//set forms ticket to be use in global.asax
SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
return RedirectToLocal(returnURL);
case PasswordVerificationResult.Failed:
ModelState.AddModelError("", "Wrong Username or Password");
return View(viewModel);
}
}
}
return View(viewModel);
}
Forms Auth Ticket
private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
{
account user = new account();
var userId = user.id;
var userData = userId.ToString(CultureInfo.InvariantCulture);
var authTicket = new FormsAuthenticationTicket(1, //version
userName, // user name
DateTime.Now, //creation
DateTime.Now.AddMinutes(20), //Expiration
persistanceFlag, //Persistent
userData);
var encTicket = FormsAuthentication.Encrypt(authTicket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return user;
}
Global.asax
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//take out user name from cookies
string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string[] roles = null;
trainingEntities db = new trainingEntities();
//query database to get user roles
var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
roles = query;
//Let us set the Pricipal with our user specific details
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
}
catch (Exception)
{
//somehting went wrong
}
}
}
}
Now you can use [Authorize(Roles = "Admin")]
to any action method or on top of controller
I have successfully implemented the Authorize Attribute with Roles, for future readers please see code below.
Login Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
PasswordHasher passwordVerify = new PasswordHasher();
var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
select new { acc.username, acc.password}).FirstOrDefault();
if (query != null)
{
if (ModelState.IsValid)
{
var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
switch (result)
{
case PasswordVerificationResult.Success:
//set forms ticket to be use in global.asax
SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
return RedirectToLocal(returnURL);
case PasswordVerificationResult.Failed:
ModelState.AddModelError("", "Wrong Username or Password");
return View(viewModel);
}
}
}
return View(viewModel);
}
FormsAuthTicket
private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
{
account user = new account();
var userId = user.id;
var userData = userId.ToString(CultureInfo.InvariantCulture);
var authTicket = new FormsAuthenticationTicket(1, //version
userName, // user name
DateTime.Now, //creation
DateTime.Now.AddMinutes(20), //Expiration
persistanceFlag, //Persistent
userData);
var encTicket = FormsAuthentication.Encrypt(authTicket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return user;
}
Global.asax
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//take out user name from cookies
string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string[] roles = null;
trainingEntities db = new trainingEntities();
//query database to get user roles
var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
roles = query;
//Let us set the Pricipal with our user specific details
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
}
catch (Exception)
{
//somehting went wrong
}
}
}
}
Now you can use [Authorize(Roles = "Admin")]
to any action method or on top of controller
as I see in ControllerLogin attribute it is now being applied in a variable, when it should be applied to a method or a class
[CustomAuthorization(UserRole="Admin")]
// GET: Manage
private trainingEntities db = new trainingEntities();
public ActionResult Index()
{
return View();
}
Private trainingEntities dB = new TrainingEntities();
[CustomAuthorization(UserRole="Admin")]
Public ActionResult Index()
{
//yourcode
}

Simplemembership Login and RemeberMe ASP.Net MVC4

I am using ASP.net MVC4 with SimpleMemberShip.
I simply want to store the username if the remember me checkbox is ticked and reload it from the cookie.
Login works fine, RememberMe is set to true. But Request.Cookies[FormsAuthentication.FormsCookieName] is always null. I am confused on how this is supposed to work.
Login Controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Index(LoginModel model, string returnUrl)
{
bool RememberMe = model.RememberMe == "on" ? true : false;
if (WebSecurity.Login(model.UserName, model.Password, persistCookie: RememberMe))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
Login Page Controller:
[AllowAnonymous]
public ActionResult Index(string returnUrl)
{
// load user name
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
ViewBag.Username = Server.HtmlEncode(ticket.Name);
ViewBag.RememberMeSet = true;
}
else
{
ViewBag.RememberMeSet = false;
}
ViewBag.ReturnUrl = returnUrl;
return View();
}
I wanted to get the username saved by clicking the "Remember me" checkbox. I now understand the cookie is null unless logged in so it was of no use on a login page. For reference I have added my solution below.
Handle Login Request Controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Index(LoginModel model, string returnUrl)
{
// handle remembering username on login page
bool RememberMe = model.RememberMe == "on" ? true : false;
HttpCookie existingCookie = Request.Cookies["xxx_username"];
if (RememberMe)
{
// check if cookie exists and if yes update
if (existingCookie != null)
{
// force to expire it
existingCookie.Expires = DateTime.Today.AddMonths(12);
}
else
{
// create a cookie
HttpCookie newCookie = new HttpCookie("xxx_username", model.UserName);
newCookie.Expires = DateTime.Today.AddMonths(12);
Response.Cookies.Add(newCookie);
}
}
else
{
// remove cookie
if (existingCookie != null)
{
Response.Cookies["xxx_username"].Expires = DateTime.Now.AddDays(-1);
}
}
if ((!string.IsNullOrEmpty(model.UserName)) && (!string.IsNullOrEmpty(model.Password)))
{
if (WebSecurity.Login(model.UserName, model.Password, RememberMe))
{
return RedirectToLocal(returnUrl);
}
}
// If we got this far, something failed, redisplay form
TempData["ErrorMsg"] = "Login failed";
return View(model);
}
Display Login Page Controller:
[AllowAnonymous]
public ActionResult Index(string returnUrl)
{
// load user name
HttpCookie existingCookie = Request.Cookies["xxx_username"];
if (existingCookie != null)
{
ViewBag.Username = existingCookie.Value;
ViewBag.RememberMeSet = true;
}
else
{
ViewBag.RememberMeSet = false;
}
ViewBag.ReturnUrl = returnUrl;
return View();
}

Resources