How to know if the user is Already SignedIn and thus prevent displaying the Login page in asp dot net core 2.0 Cookie based authentication? - authentication

This is the basic code snippet !!
Show me the Login page if none of the user is signedIn. If any user is active it should redirect to Index Page of Home Controller and should not show Login page !!
public class AccountController : CommonController
{
public AccountController(IOptions<ConnectionSetting> connString) : base(connString)
{
}
public IActionResult Index()
{
return RedirectToAction("Index", "Home");
}
[HttpGet]
[AllowAnonymous]
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(User user)
{
if (ValidateUser(user.UserName , user.Password))
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name , user.UserName)
};
//Now Create an ClaimIdentity
var claimsIdentity = new ClaimsIdentity(claims, "BloggingCookie");
//Create Claim Principal using that Identity
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
await HttpContext.SignInAsync("BloggingCookie", principal );
return RedirectToAction("Index", "Home");
}
else
{
ViewData["Status"] = "Invalid Username or Password";
return View();
}
}
}

All you need is to add something like the following to the top of your login action:
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Manage");
}
You can of course redirect to wherever you like.

Related

ASP.Net Core - Authorize Method doesn't work, it logs out the user

I have been trying to use the authorization method to limit access to specific actions and pages to users that are not logged in. In this case, I am trying to prevent users who are not logged in from purchasing books on my website. Here is how I used the authorize method.
// GET: Books/Purchase/5
[Authorize]
public async Task<IActionResult> Purchase(Guid id)
{
if (id == null)
{
return NotFound();
}
var book = await _context.Book.FindAsync(id);
if (book == null)
{
return NotFound();
}
OrderViewModel model = new OrderViewModel();
model.BookOrder = book;
model.Quantity = 1;
return View(model);
}
When I try to purchase a book the browser takes me back to the login page even though I am already logged in as an admin. What could be the reason for this? Here is my login action:
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var result = await signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);
if (result.Succeeded)
{
if (!string.IsNullOrEmpty(returnUrl))
{
return LocalRedirect(returnUrl);
}
return RedirectToAction("index", "home");
}
}
ModelState.AddModelError("", "Invalid Login Attempt");
return View(model);
}
Any help/guidance with this?
One reason is that the order of app.UseAuthentication(); and app.UseAuthorization(); is reversed.
You need to make sure app.UseAuthorization(); is after app.UseAuthentication();.
More details you can refer to Asp.Net Core identity.

Force 2 Factor Authentication for new users when they login for the first time .NET Core

I am trying to configure the 2FA when users log in for the first time in .net core. So I added an if condition for checking if 2FA is not enabled then redirecting to creating MFA, however, a major flaw here is that the users can change the URL link on the browser to skip 2FA creation, how can I avoid this? Below are my Account Controller Codes:
Login Controller Methods
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
return View();
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
returnurl ??= Url.Content("~/");
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.UserName);
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
if (user.TwoFactorEnabled==false)
{
return RedirectToAction(nameof(EnableAuthenticator), new { returnurl, model.RememberMe });
}
return LocalRedirect(returnurl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(VerifyAuthenticatorCode), new { returnurl, model.RememberMe });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
Enable 2FA Controller Methods
[HttpGet]
public async Task<IActionResult> EnableAuthenticator()
{
string AuthenticatorUriFormat = "MY-OTP-SECRET-HERE";
var user = await _userManager.GetUserAsync(User);
await _userManager.ResetAuthenticatorKeyAsync(user);
var token = await _userManager.GetAuthenticatorKeyAsync(user);
string AuthenticatorUri = string.Format(AuthenticatorUriFormat, _urlEncoder.Encode("My-App-Name-Here"),
_urlEncoder.Encode(user.Email), token);
var model = new MFAViewModel() { Token = token, QRCodeUrl = AuthenticatorUri };
return View(model);
}
[HttpPost]
public async Task<IActionResult> EnableAuthenticator(MFAViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.GetUserAsync(User);
var succeeded = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code);
if (succeeded)
{
await _userManager.SetTwoFactorEnabledAsync(user, true);
}
else
{
ModelState.AddModelError("Verify", "Your two factor auth code could not be validated.");
return View(model);
}
}
return RedirectToAction(nameof(AuthenticatorConfirmation));
}
As mentioned in my comment, you could consider configuring the application use Claims-based authorization, after user login with 2FA successfully, you could add a claim store the 2FA login result and add it to the login user. After that, in your application, create a policy which requires the claim, and add the Authorize attribute on each controller.
Besides, you could also add the user's claims after 2FA , then create a custom middleware/Authorize attribute to validate each request and check whether the current user contains the claims or not. You can refer to the following links: Custom Authorization attributes and How To Override Attribute Class To Do Custom Authorization In .NET Core.

Not redirect to Authorize Action Result after successful login in Identity MVC

I am trying create a login page that should redirect to an action result on successful login. I have user roles that should check. For now I can validate user but it does not redirect to Authorize Action result. Besides it provide return url to login page. Here is my Code for Account Controller
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(string UserName, string Password)
{
if (new UserManager().IsValid(UserName, Password))
{
string userName = "Test Name"; //Hard coded for test purpose
string[] userRoles = {"Admin"};//Hard coded for test purpose
ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userName));
userRoles.ToList().ForEach((role) => identity.AddClaim(new Claim(ClaimTypes.Role, role)));
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
AuthenticationManager.SignIn(identity);
return RedirectToAction("Index","Home"); // auth succeed
// auth succeed
}
// invalid username or password
ModelState.AddModelError("", "invalid username or password");
return View();
}
private IAuthenticationManager AuthenticationManager
{
get { return HttpContext.GetOwinContext().Authentication; }
}
And Home controller
[Authorize]
public ActionResult Index()
{
return View(); //Which contain Dashboard for admin panel
}
But problem is when it appear to return RedirectToAction("Index","Home");it not redirect but URL change to ../Account/Login?ReturnUrl=%2fHome.
This is very new to me (Past I restrict user from database), Is there anything wrong with this code? Thanks in advance....

How to use MVC Authorize attribute?

I just start to try using MVC, and notice about the authorize attribute to limit access to authenticated user. Unfortunately it doesn't seems to work for now.
Below is my code :
Web.config :
<authentication mode="Forms">
<forms loginUrl="/Login/Index" timeout="30"/>
</authentication>
Login Controller :
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
[HttpPost]
[AllowAnonymous]
public ActionResult ValidateLogin(UserLogin userLog)
{
if (userLog.UserName != "admin" || userLog.Password != "admin")
{
ModelState.AddModelError("Error Message", "Wrong Login Credentials.");
return View("Index", userLog);
}
return RedirectToAction("Index", "Home");
}
Home Controller :
[Authorize]
public ActionResult Index()
{
return View();
}
It will still block access after enter a correct login.
Thank you.
Try to expand your login method with the actual login by the authenticationmanager:
[HttpPost]
[AllowAnonymous]
public ActionResult ValidateLogin(UserLogin userLog)
{
if (userLog.UserName != "admin" || userLog.Password != "admin")
{
ModelState.AddModelError("Error Message", "Wrong Login Credentials.");
return View("Index", userLog);
}
// Signing in the user will make the Authorize attribute work!
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
return RedirectToAction("Index", "Home");
}
ALTERNATIVE?:
I've heart about FormsAuthentication, but not used it so far, maybe that's an option for you, but the AuthenticationManager is so easy to use!
Login:
FormsAuthentication.SetAuthCookie(username, false);
Logout:
FormsAuthentication.SignOut();

MVC5 Authentication cannot save UseCookieAuthentication

I have a problem with MVC 5 Authentication
After success login, i think i cannot save UseCookieAuthentication.
My Startup code:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/MyAccount/Login")
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
My login controler:
public ActionResult Login(Login l, string ReturnUrl="")
{
using (CBDB2012Entities dc = new CBDB2012Entities())
{
var user = dc.Users.Where(a => a.UserName.Equals(l.Username) && a.Password.Equals(l.Password)).FirstOrDefault();
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.UserName, l.RememberMe);
if (Url.IsLocalUrl(ReturnUrl))
{
return Redirect(ReturnUrl);
}
else
{
return RedirectToAction("MyProfile", "MyAccount");
}
}
}
ModelState.Remove("Password");
return View();
}
after login, it RedirectToAction("MyProfile", "MyAccount");
But in MyProfile view, i cannot see anything about user and i cann't access to contac page with [Authorize]:
-Contact controler
[Authorize]
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
I has test via session in login control, and it work fine:
var user = dc.Users.Where(a => a.UserName.Equals(l.Username) && a.Password.Equals(l.Password)).FirstOrDefault();
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.UserName, l.RememberMe);
Session["loginname"] = user.Employee.FirstName;
if (Url.IsLocalUrl(ReturnUrl))
{
return Redirect(ReturnUrl);
}
else
{
return RedirectToAction("MyProfile", "MyAccount");
}
}
i can get Session["loginname"] in view from database.