MVC Login with repository? - asp.net-mvc

I am trying to validates users with login view,controller and repository
Actions result in controller
[HttpPost]
public ActionResult Login(Models.UserModel user)
{
CartLibrary.Repository.UserRepository objuserrepository = new CartLibrary.Repository.UserRepository();
objuserrepository.Login(user.Username, user.Password);
return RedirectToAction("Index", "Orders");
}
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
Method in repository
public string Login(string Username, string Password )
{
if (!DB.Users.Any(x => x.Username == Username && x.Password == Password))
{
return Username;
}
throw new UnauthorizedAccessException();
return Username;
}

In your Login method you just return string (username).....but you don't set any cookies so......????
So you can after your login method write code:
if(String.IsNullOrEmpty(objuserrepository.Login(user.Username,user.Password))
{
FormsAuthentication.SetAuthCookie(
this.TextBox_username.Text.Trim(), flase);
FormsAuthenticationTicket ticket1 =
new FormsAuthenticationTicket(
1, // version
this.TextBox_username.Text.Trim(), // get username from the form
DateTime.Now, // issue time is now
DateTime.Now.AddMinutes(10), // expires in 10 minutes
false, // cookie is not persistent
"HR" // role assignment is stored
// in userData
);
HttpCookie cookie1 = new HttpCookie(
FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket1) );
Response.Cookies.Add(cookie1);
}

Related

How to properly use RedirectToAction()

namespace AspWebAppTest.Controllers
{
public class AccountController : Controller
{
public IActionResult Login()
{
return View();
}
[HttpGet]
public IActionResult Login(string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password))
{
return RedirectToAction("Login");
}
ClaimsIdentity identity = null;
bool isAuthenticated = false;
if (userName == "Admin" && password == "pass")
{
identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.Role, "Admin")
}, CookieAuthenticationDefaults.AuthenticationScheme);
isAuthenticated = true;
}
if (isAuthenticated)
{
var principal = new ClaimsPrincipal(identity);
var login = HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return RedirectToAction("Mapping","Setting", "Home");
}
return View();
}
public IActionResult Logout()
{
var login = HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Login");
}
}
}
I have this Cookie Authentication Controller for my tabs(Mapping, and Config). I'am using RedirectToAction() method to redirect my return view to access mapping and config tab once the user entered the correct password and username. My problem is, after I put the password and username nothing is happening. Am I using the wrong method?
Here is my startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
The SignInAsync method returns a Task which will complete when the sign-in operation has succeeded.
Your code does not await this Task, so you're sending the redirection response before the user has been authenticated.
Make your actions async, and await the results of the Sign[In|Out]Async methods:
[HttpGet]
public async Task<IActionResult> Login(string userName, string password)
{
...
if (isAuthenticated)
{
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return RedirectToAction("Mapping", "Setting", "Home");
}
return View();
}
public async Task<IActionResult) Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Login");
}

Authorize as Roles = "Admin" during login

First of all i am new to MVC user authentication system. Code bellow is working fine for authenticate normal users but i wanted to log all user as per under MVC role based system. So admin user can only see admin controller and normal user cant see admin controller. I already made it on my admin controller i have added "[Authorize(Roles = "Admin")]" and i am also redirecting correctly to specific controller during login filter inside login controller. Now my issue is: How can i tell MVC "[Authorize(Roles = "Admin")]" is only accessed who has admin role? I mean how can i assign a user as admin from my login controller bellow? Ask any question if may have
Administrator Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Blexz.Controllers
{
[Authorize(Roles = "Admin")]
public class AdministratorController : Controller
{
// GET: Administrator
public ActionResult Index()
{
return View();
}
}
}
Login Controller:
//Login post
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(UserLogin login, string ReturnUrl="")
{
string Message = "";
using (BlexzWebDbEntities db = new BlexzWebDbEntities())
{
var v = db.Users.Where(x => x.Email == login.Email && x.IsEmailVerified == true).FirstOrDefault();
int RoleId = db.Users.Where(x => x.Email == login.Email).Select(x => x.RoleId).FirstOrDefault();
string RoleTypeName = db.Roles.Where(x => x.RoleId == RoleId).Select(x => x.RoleType).FirstOrDefault();
if (v != null)
{
if (string.Compare(Crypto.Hash(login.Password), v.PasswordHash) == 0)
{
int timeOut = login.RememberMe ? 43800 : 100; // 43800 == 1 month
var ticket = new FormsAuthenticationTicket(login.Email, login.RememberMe, timeOut);
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new System.Web.HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = DateTime.Now.AddMinutes(timeOut);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
if (Url.IsLocalUrl(ReturnUrl))
{
return Redirect(ReturnUrl);
}
else if (RoleTypeName == "Admin")
{
return RedirectToAction("Index", "Administrator");
}
else
{
return RedirectToAction("User", "Home");
}
}
else
{
Message = "Invalid Credential Provided";
}
}
else
{
Message = "Invalid Credential Provided";
}
}
ViewBag.Message = Message;
return View();
}
Remove FirstOrDefault from RoleTypeName selection and change it as
string[] RoleTypeName = db.Roles.Where(x => x.RoleId == RoleId).Select(x => x.RoleType);
and change the checking as
if (Url.IsLocalUrl(ReturnUrl))
{
return Redirect(ReturnUrl);
}
else if (RoleTypeName.Contains("Admin"))
{
return RedirectToAction("Index", "Administrator");
}
else
{
return RedirectToAction("User", "Home");
}
Change your ticket as shown below
var ticket = new FormsAuthenticationTicket(
version: 1,
name: UserName,
issueDate: DateTime.Now,
expiration: DateTime.Now.AddSeconds(httpContext.Session.Timeout),
isPersistent: false,
userData: String.Join(",", RoleTypeName));
and After that in global.asax you would do something like this:
public override void Init()
{
base.AuthenticateRequest += OnAuthenticateRequest;
}
private void OnAuthenticateRequest(object sender, EventArgs eventArgs)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
var decodedTicket = FormsAuthentication.Decrypt(cookie.Value);
var roles = decodedTicket.UserData.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries);
var principal = new GenericPrincipal(HttpContext.Current.User.Identity, roles);
HttpContext.Current.User = principal;
}
}

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
}

Will Unity Framework Remove cookies from Context in MVC 5

I'm creating an application that have unity framework for dependency injection so my Account Controller is following and that contain Login Action
public class AccountController : Controller
{
private readonly IUserService userService;
public AccountController(IUserService userService)
{
this.userService = userService;
}
public ActionResult Login()
{
return View();
}
[HttpPost]
[AllowAnonymous]
//[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
string message = "";
var user = userService.UserExists(model, out message);
if (user != null)
{
CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
serializeModel.UserId = Convert.ToInt32(user.Id);
serializeModel.EmailId = user.EmailId;
serializeModel.FirstName = user.FirstName;
serializeModel.LastName = user.LastName;
serializeModel.role = user.Role;
string userData = JsonConvert.SerializeObject(serializeModel,Formatting.Indented,
new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects
});
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
user.EmailId,
DateTime.Now,
model.RememberMe ? DateTime.Now.AddDays(3) : DateTime.Now.AddHours(3),
model.RememberMe ? true : false,
userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = model.RememberMe ? DateTime.Now.AddDays(3) : DateTime.Now.AddHours(3);
Response.Cookies.Add(faCookie);
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Incorrect username and/or password");
}
return View(model);
}
}
.In login action I'm doing following
1) Checking User Is Existed Or Not if existed then adding FormsAuthentication Cookie .
but when I using IUserService (Interface for DI ) then cookie is deleted when redirect to another action .
2) But if I remove DI from controller then Cookie is persisted .
whats wrong I'm finding answer from couple of days .
please give me solution I want DI and Cookie Both .
Thanks in advanced .

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