I have to get roles of a user from DB as per my application nature. I am authenticating user in context.AcquireRequestState += context_AcquireRequestState; event handler in HttpModule. Can I do db calls from HttpModule to assign roles in Identity? Is it good practice? if not, where I have to do it before controller’s action method called.?
I dont know what you doing with Aquaire request state, Ideally you have to do as below:
[Authorize(Roles="Admin")]
[Route("user/{id:guid}/roles")]
[HttpPut]
public async Task<IHttpActionResult> AssignRolesToUser([FromUri] string id, [FromBody] string[] rolesToAssign)
{
var appUser = await this.AppUserManager.FindByIdAsync(id);
if (appUser == null)
{
return NotFound();
}
var currentRoles = await this.AppUserManager.GetRolesAsync(appUser.Id);
var rolesNotExists = rolesToAssign.Except(this.AppRoleManager.Roles.Select(x => x.Name)).ToArray();
if (rolesNotExists.Count() > 0) {
ModelState.AddModelError("", string.Format("Roles '{0}' does not exixts in the system", string.Join(",", rolesNotExists)));
return BadRequest(ModelState);
}
IdentityResult removeResult = await this.AppUserManager.RemoveFromRolesAsync(appUser.Id, currentRoles.ToArray());
if (!removeResult.Succeeded)
{
ModelState.AddModelError("", "Failed to remove user roles");
return BadRequest(ModelState);
}
IdentityResult addResult = await this.AppUserManager.AddToRolesAsync(appUser.Id, rolesToAssign);
if (!addResult.Succeeded)
{
ModelState.AddModelError("", "Failed to add user roles");
return BadRequest(ModelState);
}
return Ok();
}
Source read here
Related
When a User logins into a Web application. The Website has to authenticate who the User against the Database. Once the User is authenticated then a system can authorise the person so that they can make request to other pages without logging in again. I am having a implementing security into my asp.net core 2.0 web application, because I am not using Entity Framework. I am using MariaDB as the database Back-End. When a request is made to the Server
public ViewResult testMethod(LoginModel model){
User user = dataManager.GetUser(model.Email);
if (user == null)
{
// return user to view
return View(model);
}
if (user.Activated != true)
{
// return user to view
return View(model);
}
// Use userManager
I want to use the UserManager but since I am using a MariaDB as the backend is this still possible?
if you are using, entity framework
let say you have table User with password
try using claim principal
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
try
{
var user = _authService.Login(model.UserName, model.Password);
if (user != null)
{
var userClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.NameIdentifier, user.UserId),
new Claim(ClaimTypes.Email, user.Mail),
new Claim(ClaimTypes.Role, user.PositionId)
};
var identity = new ClaimsIdentity(userClaims, "Ix");
//userClaims.Add(new Claim(ClaimTypes.Role, "0"));
var principal = new ClaimsPrincipal(identity);
await HttpContext.Authentication.SignInAsync("app", principal, new AuthenticationProperties { IsPersistent = false });
return RedirectToLocal(returnUrl);
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View(model);
}
I've been banging my head against a wall for some time now about this:
I have an ASP.NET MVC 5.2.3 web application with ASP.NET Identity 2.2.1. I want to force users to
validate their email-address and
validate their mobile phone number.
So when a user registers for the application an emailVerification token is generated and sent to the user.
After that the user is redirected to the VerifyPhoneNumber endpoint in the Manage controller. SMS-code is generated and gets send to the user. User is promted to enter the SMS-code. Code is verified.
BUT if then the user receives the email with the email-verification-code and click the link the token cannot no longer be verified (Invalid Token).
As far as I understand, this happens because calling UserManager.ChangePhoneNumberAsync changes the user's SecurityStamp. Email-verification works well if phone verification is not active. To be more specific, when ChangePhoneNumberAsync is not called.
Any ideas on how to prevent the SecurityStamp from changing or allow both verifications on inital registration are greatly appreciated.
Ben
VerifyPhoneNumber
public async Task<ActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var userId = User.Identity.GetUserId();
var result = await UserManager.ChangePhoneNumberAsync(userId, model.PhoneNumber, model.Code);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(userId);
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
return RedirectToAction("Index", "Home");
}
else
{
return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess });
}
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "Could not verify phone number.");
return View(model);
}
ConfirmEmail
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
code = HttpUtility.UrlDecode(code);
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
Im developing an MVC 5.0 .ASP NET app. Im using Identity to authorize users. I've added another method to AccountController where user can log in with Token. After 'signing in' in my method instead of rendering chosen view application redirects to default login method. When you type mysite/home/ it shows that user is logged in.
I can't find when the redirect to Login is made.
Any ideas how to fix this?
To authenticate user in my action I use this method:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
My custom login action
[AllowAnonymous]
public async Task<ActionResult> LoginWithToken(string token, string returnUrl)
{
AccountService accountService = new AccountService(db);
string userId;
try
{
userId = await accountService.GetUserIdFromToken(token);
}
catch (Exception exception)
{
ModelState.AddModelError(exception.Message, exception);
return RedirectToAction("Login");
}
var user = await UserManager.FindByIdAsync(userId);
try
{
await SignInAsync(user, false);
}
catch (Exception)
{
ModelState.AddModelError("Logowanie nieudane. Konto mogło zostać zablokowane lub usunięte. Skontaktuj się z administratorem serwisu.", new AccessViolationException());
return RedirectToAction("Login");
}
LogUserLogin(user.UserName, Request.UserHostAddress);
string decodedUrl = "";
if (!string.IsNullOrEmpty(returnUrl))
decodedUrl = Server.UrlDecode(returnUrl);
if (Url.IsLocalUrl(decodedUrl))
{
return View((object)decodedUrl);
}
else
{
return RedirectToAction("Home", "Index", new { });
}
}
EDIT:
I've found out that when my method is hitting return View((object)decodedUrl); request doesn't contains ".AspNet.ApplicationCookie". I've set breakpoint on Application_BeginRequest and right after renturn View((object)decodedUrl) there is request to Login action. At this point there is ".AspNet.ApplicationCookie" in request.
Finally I've found that the authentication cookie wasn't set to the current request but to next request.
Now my LoginWithToken Method redirects to another [AllowAnonymous] Action so the cookie is set. Then that action redirects to authorisation restricted areas.
I am using Webapi with Identity2.0 AccessFailedCount, LockoutEndDateUtc is not incermenting on Invalid UserName and Password. I have implement Token Based Authentication provided by WebAPI. Please help .
here is code Snippet
using (UserManager<ApplicationUser> userManager = userManagerFactory)
{
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
if (await userManager.IsLockedOutAsync(user.Id))
{
context.SetError("lock_out", "The account is locked.");
return;
}
if (!userManager.IsEmailConfirmed(user.Id))
{
context.SetError("inactive_user", "The user is not active. Please check your Register Email to verify.");
return;
}
ClaimsIdentity oAuthIdentity = await userManager.CreateIdentityAsync(user,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = await userManager.CreateIdentityAsync(user,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
Finally I have resolved with this code
// To lock the user with userName ---- setting of maximum access 5 in IdentityConfig.cs File
ApplicationUser userToLock = await userManager.FindByNameAsync(context.UserName);
if (userToLock != null)
{
await userManager.AccessFailedAsync(userToLock.Id);
}
Now Access AccessFailedCount, LockoutEndDateUtc getting value
Thanks for the help guys. Special Thanks for #trailmax ... To divert my thinking to webapi
To increment AccessFailedCount on a user, every time the login is invalid you need to call for
await userManager.AccessFailedAsync(user.Id);
Otherwise this is not done for you in any way.
ApplicationSignInManager does this this for you but (as far as I know) this class only works with MVC, not WebAPI
Hi It may be too late but I got some code from ASP.Net Identity 2.0 AccessFailedCount not incrementing
and customized to Web API.
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindByNameAsync(context.UserName);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
bool EmailConfirmed = await userManager.IsEmailConfirmedAsync(user.Id);
if ( !EmailConfirmed)
{
context.SetError("inactive_user", "The user is not active. Please check your Register Email to verify.");
return;
}
bool LockedOut = await userManager.IsLockedOutAsync(user.Id);
if (userManager.SupportsUserLockout && LockedOut)
{
context.SetError("invalid_grant", "This account has been locked out, please try again later.");
return;
}
int FailedCount = await userManager.GetAccessFailedCountAsync(user.Id);
bool LockoutEnabled = await userManager.GetLockoutEnabledAsync(user.Id);
if (userManager.CheckPassword(user, context.Password))
{
if (userManager.SupportsUserLockout && LockoutEnabled && FailedCount > 0)
{
await userManager.ResetAccessFailedCountAsync(user.Id);
}
// Authenticate user
}
else
{
if (userManager.SupportsUserLockout && LockoutEnabled)
{
await userManager.AccessFailedAsync(user.Id);
}
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
I am Implementing Social login in my application but I am getting an error "No parameterless constructor defined for this object".I am not able to find out the reason behind this.can any one tell me exactly what haapening.My Controller is as follows:
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return RedirectToLocal(returnUrl);
}
if (User.Identity.IsAuthenticated)
{
// If the current user is logged in add the new account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
return RedirectToLocal(returnUrl);
}
else
{
// User is new, ask for their desired membership name
string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
}
}
and I am getting an error in this line:
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
Please Let me know..