ASP.NET Core - Registering new Users - authentication

I'm adding the functionality of adding new users to my project following this project:
http://www.c-sharpcorner.com/article/asp-net-core-mvc-authentication-and-role-based-authorization-with-asp-net-core/
However, I encounter a problem when I try to Add a new user:
On the Post Method of the UserController:
[HttpPost]
public async Task<IActionResult> AddUser(UserViewModel model)
{
if (ModelState.IsValid)
{
ApplicationUser user = new ApplicationUser
{
Name = model.Name,
UserName = model.UserName,
Email = model.Email
};
IdentityResult result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
ApplicationRole applicationRole = await roleManager.FindByIdAsync(model.ApplicationRoleId);
if (applicationRole != null)
{
IdentityResult roleResult = await userManager.AddToRoleAsync(user, applicationRole.Name);
if (roleResult.Succeeded)
{
return RedirectToAction("Index");
}
}
}
}
return View(model);
I'm getting an error on this line:
IdentityResult result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
When I put a break here, I see that result is null.
I'm trying to solve it on my own but no luck so far.
Any ideas? Thanks in advance for any help.
Regards,

Related

Redirect To Action Not Working after login ASP.NET Core Identity (.Net 5)

Even after a successful sign-in it does not redirect to action but stays on the login page.
I have put breakpoints but have not been able to know what exactly is wrong with my code.
Even if the condition is true the code is not executed.
Here is my code:
[HttpPost]
public async Task<ActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = await _context.Users.SingleOrDefaultAsync(u => u.UserName == model.UserName);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, model.Password, true, false);
if (result.Succeeded)
{
var role = await _userManager.GetRolesAsync(user);
if (role.Contains("Client"))
{
return RedirectToAction("Index", "MyDashboard");
}
if (role.Contains("Admin"))
{
return RedirectToAction("Index", "Admin");
}
}
}
else
{
ModelState.AddModelError("", "Invalid login attempt");
return View(model);
}
}
return View();
}
I got the solution myself. Actually, I was missing Authentication middleware in the startup class. After adding app.UseAuthentication() ,it works fine. Thanks.

The Challange method does not redirect to the specified url

I'm making a site with external authorization through VK, I've looked through a lot of examples, but I ran into one problem, in all examples redirection to ExternalLoginCallback happens through Challange method with provider parameters and url, but redirection happens not to specified url, but to signin-vkontakte-token, which is specified in ConfigureServices. What can this be related to?(It doesn't matter if you give me an answer with the specified provider or another one, such as Facebook)
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl)
{
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Home", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction("Index");
}
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, false);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}

The name "'_emailSender'" does not exist in the current context

I'm trying to learn authentication on razor pages
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-5.0&tabs=visual-studio
And when I changed the Login page as they wrote in the example-
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation",
new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
I get the error-
The name "'_emailSender'" does not exist in the current context
And I searched later if there is a reference to the _emailSender class and did not see. Does anyone know how to fix this error?
Best regards
I should have added -
private readonly IEmailSender _emailSender;
Too bad they did not write it, it would have saved me a lot of time

User roles are zero after login in MVC6?

I am using the default site template that comes in visual studio 2015. I have added some roles and assigned roles to the user. When a used signs in, the roles are zero. What do I need to do to get the roles working?
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
var signInStatus = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (signInStatus)
{
case SignInStatus.Success:
var user = await GetCurrentUserAsync();
return RedirectToLocal(returnUrl);
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid username or password.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Looking at your code, it looks like you're missing any check for a role.
I was having this similar problem and after digging into the code I noticed that GetCurrentUserAsync() was not returning a valid user object and was intact returning a null object. Context.User.GetUserId() is the problem and isn't returning a user id to pass on to the UserManager.
Until this is resolved I'm using the following:
if (result.Succeeded)
{
var user = await UserManager.FindByEmailAsync(model.Email);
if (await UserManager.IsInRoleAsync(user, Roles.Admin))
{
return RedirectToAction("Index", "Admin");
}
return RedirectToLocal(returnUrl);
}
While this isn't ideal it does work
This works for me...does not redirect correct for Invalid username or password 4 me yet...will check...
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewBag.ReturnUrl = returnUrl;
if (ModelState.IsValid)
{
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
if (result.Succeeded)
{
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
this is for MVC 6, (VS 2015 RC)...u can find it all here : https://github.com/aspnet/Identity/tree/dev/samples/IdentitySample.Mvc

Claims Authentication ASP.NET vNext

When adding a claim to the user, the claims information does not get recorded as a cookie on the page and the information gets lost for all other requests. Why does this happen?
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
try
{
var authReq = new AuthenticationViewModel() { password = model.Password, username = model.UserName };
var userInfo = await _dataService.AuthenticateAsync(authReq);
var claims = new List<Claim>();
claims.Add(new Claim("username", userInfo.user.userName));
claims.Add(new Claim("AddtionalData", userInfo.AddtionalData));
var user = ClaimsPrincipal.Current;
var identity = user.Identities.Where(x => x.AuthenticationType == "Custom").FirstOrDefault();
if (identity == null)
identity = new ClaimsIdentity(claims.ToArray(), "Custom");
user.AddIdentity(identity);
return RedirectToAction("Users", "Index");
}
catch (Exception)
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
I found the issue, I needed to add the following code:
context.Response.SignIn(new ClaimsIdentity(new[] { new Claim("name", "bob") }, CookieAuthenticationDefaults.AuthenticationType));
also, I changed the AuthenticationType to be CookieAuthenticationDefaults.AuthenticationType.
Please see link with Sample