3

パスワードを知っていて登録済みのメールをまだ変更していない(データベースに登録されていない)新しく作成されたユーザーを許可する古い電子メール確認トークン(ID)を取り消し/無効化/取り消す方法

問題は、電子メールを変更した場合、私は新しい電子メール確認トークンを生成しますが、古いトークンは(登録時に発行した)トークンを検証できるということです。彼らがアクセスできない他のメールに変更して、古いセキュリティホールから妥当性を確認してください。

古いトークンを削除/取り消す方法はありますか? (技術的には、私は新しいユーザーを作成し、古いものを削除することができます、古いトークンは新しいユーザーでは動作しませんでしたが、これにはもっと良い解決策があるはずです)

答えて

4

私はApplicationUserクラス

public class ApplicationUser : IdentityUser { 
    public string EmailConfirmationToken { get; set; } 
    public string ResetPasswordToken { get; set; } 
} 

これは、電子メールトークンを確認する際に確認される確認トークンを保持します。

次に、私はApplicationUserManagerに次を追加しました。UserManager<ApplicationUser>派生クラスです。

public override async System.Threading.Tasks.Task<string> GenerateEmailConfirmationTokenAsync(string userId) { 
    /* NOTE: 
    * The default UserTokenProvider generates tokens based on the users's SecurityStamp, so until that changes 
    * (like when the user's password changes), the tokens will always be the same, and remain valid. 
    * So if you want to simply invalidate old tokens, just call manager.UpdateSecurityStampAsync(). 
    */ 
    //await base.UpdateSecurityStampAsync(userId); 

    var token = await base.GenerateEmailConfirmationTokenAsync(userId); 
    if (!string.IsNullOrEmpty(token)) { 
     var user = await FindByIdAsync(userId); 
     user.EmailConfirmationToken = token; 
     user.EmailConfirmed = false; 
     await UpdateAsync(user); 
    } 
    return token; 
} 

public override async System.Threading.Tasks.Task<string> GeneratePasswordResetTokenAsync(string userId) { 
    var token = await base.GeneratePasswordResetTokenAsync(userId); 
    if (!string.IsNullOrEmpty(token)) { 
     var x = await FindByIdAsync(userId); 
     x.ResetPasswordToken = token; 
     await UpdateAsync(x); 
    } 
    return token; 
} 

public override async System.Threading.Tasks.Task<IdentityResult> ConfirmEmailAsync(string userId, string token) { 
    var result = await base.ConfirmEmailAsync(userId, token); 
    if (result.Succeeded) { 
     var x = await FindByIdAsync(userId); 
     x.EmailConfirmationToken = null; 
     await UpdateAsync(x); 
    } 
    return result; 
} 

public override async System.Threading.Tasks.Task<IdentityResult> ResetPasswordAsync(string userId, string token, string newPassword) { 
    var result = await base.ResetPasswordAsync(userId, token, newPassword); 
    if (result.Succeeded) { 
     var x = await FindByIdAsync(userId); 
     x.ResetPasswordToken = null; 
     await UpdateAsync(x); 
    } 
    return result; 
} 

保存されたトークンに基づいてユーザーを見つけるために、次の拡張機能が追加されました。

public static class ApplicationUserManagerExtension { 
    public static Task<string> FindIdByEmailConfirmationTokenAsync(this UserManager<ApplicationUser> manager, string confirmationToken) { 
     string result = null; 

     ApplicationUser user = manager.Users.SingleOrDefault(u => u.EmailConfirmationToken != null && u.EmailConfirmationToken == confirmationToken); 

     if (user != null) { 
      result = user.Id; 
     } 

     return Task.FromResult(result); 
    } 

    public static Task<string> FindIdByResetPasswordTokenAsync(this UserManager<ApplicationUser> manager, string token) { 
     string result = null; 

     ApplicationUser user = manager.Users.SingleOrDefault(u => u.ResetPasswordToken != null && u.ResetPasswordToken == token); 

     if (user != null) { 
      result = user.Id; 
     } 

     return Task.FromResult(result); 
    } 
} 
+1

あなたのコード内のコメントは、セキュリティスタンプが古いトークンを無効に更新し、私が探していたソリューションでしたし、私は単にあなたに感謝し、素晴らしかったこと、新しいトークンを発行する前にそれを使用しました! – mynameisjeff

関連する問題