Authentication via FormsAuthentication in asp mvc 4 - c#

I have simple web App (asp mvc 4) that take username and password and authenticate user via custom user provider.
In account controller i write this code:
public ActionResult Login(LoginViewModel model, string returnUrl = "")
{
if (ModelState.IsValid)
{
ImasUser user=null;
var x = ImasUserManagment.ImasMembershipProvider.GetImasUser(model.Username, model.Password);
if(x!=null)
user =new ImasUser(x);
if (user != null)
{
var roles = user.ImasRoles.Select(m => m.RoleName).ToArray();
ImasPrincipalSerializeModel serializeModel = new ImasPrincipalSerializeModel();
serializeModel.UserId = user.UserID;
serializeModel.FirstName = user.FirstName;
serializeModel.LastName = user.LastName;
serializeModel.UserName = user.UserName;
serializeModel.roles = roles;
string userData = JsonConvert.SerializeObject(serializeModel);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
user.UserName,
DateTime.Now,
DateTime.Now.AddMinutes(15),
false,
userData, FormsAuthentication.FormsCookiePath);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = authTicket.Expiration;
Response.Cookies.Clear();
System.Web.HttpContext.Current.Response.Cookies.Add(faCookie);
System.Web.HttpContext.Current.Session.Add("UserInfo", userData);
if (roles.Contains("Admin"))
{
return RedirectToAction("Index", "Admin");
}
else if (roles.Contains("User"))
{
return RedirectToAction("Index", "User");
}
else
{
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError("", "xxx");
}
And in global asax :
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie =System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
ImasPrincipalSerializeModel serializeModel = JsonConvert.DeserializeObject<ImasPrincipalSerializeModel>(authTicket.UserData);
ImasPrincipal newUser = new ImasPrincipal(authTicket.Name);
newUser.UserId = serializeModel.UserId;
newUser.FirstName = serializeModel.FirstName;
newUser.LastName = serializeModel.LastName;
newUser.roles = serializeModel.roles;
HttpContext.Current.User = newUser;
}
}
But "authCookie" is null in global.asax.

1) Better Use Session
2) Try:
FormsAuthentication.SetAuthCookie
and:
FormsAuthentication.GetAuthCookie

Related

Can't check user role. User.IsInRole returning false

I'm trying to check a user role in View:
#if (User.IsInRole("User"))
but getting all time false, although
User.Identity.IsAuthenticated
User.Identity.Name
returns true and name.
My forms authentication service:
public static void SignIn(string userName, string role, bool createPersistentCookie)
{
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(30),
createPersistentCookie,
role);
string encTicket = FormsAuthentication.Encrypt(authTicket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
{
Expires = authTicket.Expiration,
Path = FormsAuthentication.FormsCookiePath
};
if (HttpContext.Current != null)
{
HttpContext.Current.Response.Cookies.Add(cookie);
}
}
and calling
FormsAuthenticationService.SignIn(model.UserName, "User", true);
Fixed by adding to Global.asax :
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
string[] roles = authTicket.UserData.Split(';');
if (Context.User != null)
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}

Dispose method is called in case of ReturnRedirectToAction in MVC Controller

I am using MVC but I have a problem of dispose method is being called. When I am going to login, all the validation and login is working properly but when I am redirecting after a successful login, then in the case of return redirect to action, dispose method is being called.
What should I do?
Here is my controller:
public UserManager<ApplicationUser> UserManager { get; private set; }
public AdminController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AdminController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (Session["RoleID"] != null)
{
if (Convert.ToInt32(Session["RoleID"]) == Ansits2018.UTILITIES.Constants.Admin)
{
return RedirectToAction("Index", "Admin");
}
}
if (ModelState.IsValid)
{
var accRepo = new AccountRepository();
int UserID = 0;
UserID = accRepo.IsUserValid(model.UserName, model.Password);
if (UserID > 0)
{
var user = accRepo.GetUserByUsername(model.UserName);
Session["CompanyID"] = 1;
Session["UserID"] = UserID;
Session["Username"] = model.UserName;
Session["RoleID"] = user.RoleID;
Session["Name"] = user.Name;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // ticket version
user.Username, // authenticated username
DateTime.Now, // issueDate
DateTime.Now.AddMinutes(60), // expiryDate
true, // true to persist across browser sessions
user.RoleID.ToString(), // can be used to store additional user data
FormsAuthentication.FormsCookiePath // the path for the cookie
);
// Encrypt the ticket using the machine key
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Add the cookie to the request to save it
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
if (!String.IsNullOrEmpty(returnUrl))
{
return RedirectToLocal(returnUrl);
}
if (user.RoleID == Ansits2018.UTILITIES.Constants.Admin)
{
return RedirectToAction("Index", "Admin");
}
}
else
{
TempData["Message"] = "Invalid username or password.";
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
protected override void Dispose(bool disposing)
{
if (disposing && UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
base.Dispose(disposing);
}
RedirectToAction (at least the form you're using) is constructed like this:
RedirectToAction(string actionName, string controllerName)
So return RedirectToAction("Index", "Home"); takes you to the Index action in the Home Controller, and return RedirectToAction("Index", "Admin"); takes you to the Index Action of the Admin Controller.
So if I'm reading your question correctly, you need to change the code to return RedirectToAction("Index", "Home");
Update (in light of comments):
If you are wanting to RedirectToAction("Index", "Admin"); then you'll need to debug your code to find out where the problem is. You can set breakpoints for the debug, or add these debug lines to your code:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (Session["RoleID"] != null)
{
if (Convert.ToInt32(Session["RoleID"]) == Ansits2018.UTILITIES.Constants.Admin)
{
return RedirectToAction("Index", "Admin");
}
}
if (ModelState.IsValid)
{
var accRepo = new AccountRepository();
int UserID = 0;
UserID = accRepo.IsUserValid(model.UserName, model.Password);
if (UserID > 0)
{
var user = accRepo.GetUserByUsername(model.UserName);
Session["CompanyID"] = 1;
Session["UserID"] = UserID;
Session["Username"] = model.UserName;
Session["RoleID"] = user.RoleID;
Session["Name"] = user.Name;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // ticket version
user.Username, // authenticated username
DateTime.Now, // issueDate
DateTime.Now.AddMinutes(60), // expiryDate
true, // true to persist across browser sessions
user.RoleID.ToString(), // can be used to store additional user data
FormsAuthentication.FormsCookiePath // the path for the cookie
);
// Encrypt the ticket using the machine key
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Add the cookie to the request to save it
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
if (!String.IsNullOrEmpty(returnUrl))
{
System.Diagnostics.Debug.WriteLine("1 #####> RedirectToLocal (valid Login): " + returnUrl);
return RedirectToLocal(returnUrl);
}
if (user.RoleID == Ansits2018.UTILITIES.Constants.Admin)
{
return RedirectToAction("Index", "Admin");
}
}
else
{
System.Diagnostics.Debug.WriteLine("2 #####> Invalid Login Attempt - UserID > 0: " + model.UserName + " => " + model.Password));
TempData["Message"] = "Invalid username or password.";
return View(model);
}
}
System.Diagnostics.Debug.WriteLine("3 #####> ModelState Invalid: " + model.UserName + " => " + model.Password);
return View(model);
}
then click the cursor on the Login View Action (not the [HttpPost]), hit Debug in the menu and then Start Debugging. Wait for it to all settle down and then login and watch the Debug messages to see which one appears. That should give a good clue as to what's going wrong, and what you need to do.

User authentication Failed

I have created a Website in ASP.Net MVC5 and used a login function in it, it works fine on localhost but when I uploaded the site server,
Server redirects me to the login page on each click.
Below is login Function
public ActionResult DoLogin(string username, string password)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
{
var user = new UserRepository().GetAll()
.Where(u => u.UserName.ToUpper() == username.Trim().ToUpper()
&& u.Password == password).SingleOrDefault();
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.UserName,true);
var authTicket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, user.Roles);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
Session["Name"] = user.Name;
return RedirectToAction("Index", "Student");
}
}
ViewBag.ErrorMessage = "User Name or Password is incorrect";
return View("Login");
}
then I added the below function in Global.asax.cs File.
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
}
After that I have added [Authorize(Roles = "Admin")] before each Controller (Not before methods in Controller) I want to Restrict access to.
Now, whenever I login, It redirects me to Index Method of Student controller, after that I click on some other link it again takes me to the Login page. Sometimes it takes me to clicked link without taking me to Login Page. Whats the Problem with my code? it works fine on localhost.
You are assigning the auth ticket twice;
if (user != null)
{
//FormsAuthentication.SetAuthCookie(user.UserName,true); Remove it
var authTicket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, user.Roles);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
Session["Name"] = user.Name;
return RedirectToAction("Index", "Student");
}
Also, I suggest you to don't store the roles in cookie because if the user role has been removed or added new one, you can't update them. So,
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');//fill it from database and it could be better to use cache mechanism for performance concern
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
}

ASP.net MVC 5: Redirecting to login page

I have a the session expire attribute
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var context = filterContext.HttpContext;
if (context.Session != null)
{
if (context.Session.IsNewSession)
{
string sessionCookie = context.Request.Headers["Cookie"];
if ((sessionCookie == null) && (sessionCookie.IndexOf("ASP.NET_SessionId") < 0))
{
FormsAuthentication.SignOut();
filterContext.Result = new RedirectResult("~/Login/Index");
}
}
}
base.OnActionExecuting(filterContext);
}
and in my controller
public ActionResult Index(Login login)
{
//WebSecurity.Login
User user = new User();
string encodePassword = Crytography.EncodePasswordToBase64(login.Password);
var consumer = user.Get(u => u.f_username == login.Username && u.f_password == encodePassword).SingleOrDefault();
if (consumer != null)
{
FormsAuthentication.SetAuthCookie(login.Username, false);
var expiration = 3;
var authTicket = new FormsAuthenticationTicket(1, login.Username, DateTime.Now, DateTime.Now.AddSeconds(expiration), false, "Admin");
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
return RedirectToAction("Index", "Main");
}
return View();
and my problem is when redirecting the navigation of the main page remained.
enter image description here

How to get the cookie value in asp.net website

I am creating a cookie and storing the value of username after succesfull login. How can I access the cookie when the website is opened. If the cookie exist I want to fill the username text box from the cookie value. And how to decrypt the value to get the username. I am doing server side validation by getting the userdetails from the database. I am using vs 2010 with c#
FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;
tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
DateTime.Now.AddYears(1), chk_Rememberme.Checked, "User Email");
cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
if (chk_Rememberme.Checked)
{
ck.Expires = tkt.Expiration;
ck.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(ck);
}
cookie is created with name as .YAFNET_Authentication and content is encrypted
Webconfig:
<forms name=".YAFNET_Authentication" loginUrl="Home.aspx"
protection="All" timeout="15000" cookieless="UseCookies"/>
You may use Request.Cookies collection to read the cookies.
if(Request.Cookies["key"]!=null)
{
var value=Request.Cookies["key"].Value;
}
FormsAuthentication.Decrypt takes the actual value of the cookie, not the name of it. You can get the cookie value like
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value;
and decrypt that.
add this function to your global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null)
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
if (authTicket == null)
{
return;
}
string[] roles = authTicket.UserData.Split(new char[] { '|' });
FormsIdentity id = new FormsIdentity(authTicket);
GenericPrincipal principal = new GenericPrincipal(id, roles);
Context.User = principal;
}
then you can use HttpContext.Current.User.Identity.Name to get username. hope it helps
HttpCookie cook = new HttpCookie("testcook");
cook = Request.Cookies["CookName"];
if (cook != null)
{
lbl_cookie_value.Text = cook.Value;
}
else
{
lbl_cookie_value.Text = "Empty value";
}
Reference Click here

Categories