简体   繁体   中英

Asp net Core Identity token authentication expiration

I use asp net core Identity. This is what I am trying to do and I have no Idea how to do this so need some expert help on this. When a new user registers in my application , a password reset link is sent to the person's email, Now when the link token in the link has expired and the user clicks on the link I need to show a message as token expired. How do I find out If the token has expired or not when the user clicks on the link which is in the email. Can any one suggest ways to achieve this scenario?

The ASP.NET Core has a built-in Claims system to store information about the user .

To do that ,

  1. add a helper method to store the expiration datetime in Register.cshtml.cs :

     private async Task AddTokenExpirationInfo(IdentityUser user, int span=1*24*60) { var expiresAt = DateTime.Now.Add(TimeSpan.FromMinutes(span)); var tokenExpiredAtClaim = new Claim("ActivtationTokenExpiredAt", expiresAt.ToUniversalTime().Ticks.ToString()); await _userManager.AddClaimAsync(user, tokenExpiredAtClaim); }
  2. add a helper method to check whether the token has expired in the ConfirmEmail.cshtml.cs :

     private async Task<bool> TokenExpiredValidate(IdentityUser user) { var claims = (await _userManager.GetClaimsAsync(user)) .Where(c => c.Type == "ActivtationTokenExpiredAt"); var expiredAt = claims.FirstOrDefault()?.Value; bool expired = true; // default value if (expiredAt != null) { var expires = Convert.ToInt64(expiredAt); var now = DateTime.Now.Ticks; expired= now <= expires? false : true; } else { expired = false; } // clear claims await _userManager.RemoveClaimsAsync(user, claims); return expired; }
  3. invoke AddTokenExpirationInfo when there's a registeration request :

     public async Task<IActionResult> OnPostAsync(string returnUrl = null) { returnUrl = returnUrl ?? Url.Content("~/"); 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); var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new { 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>."); ///////////////// invoke here //////////////////// AddTokenExpirationInfo(user); 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(); }
  4. invoke TokenExpiredValidate in your ConfirmEmail.cshtml.cs :

     public async Task<IActionResult> OnGetAsync(string userId, string code) { if (userId == null || code == null) { return RedirectToPage("/Index"); } var user = await _userManager.FindByIdAsync(userId); if (user == null) { return NotFound($"Unable to load user with ID '{userId}'."); } var result = await _userManager.ConfirmEmailAsync(user, code); if (!result.Succeeded) { throw new InvalidOperationException($"Error confirming email for user with ID '{userId}':"); } if (await TokenExpiredValidate(user)) throw new InvalidOperationException($"Token has alread expired '{userId}':"); return Page(); }

When a user registers , there' will be a record in the AspNetUserClaims table :

演示

When a user confirmed successfully , the record will be removed . Just as a reminder , a more robust method is to use a background service to clear the expired record .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM