ResetPasswordAsync возвращает недопустимый токен, когда токен генерируется внутри WebJob

У меня есть запланированный WebJob, который запускается ежедневно и проверяет дату истечения срока действия пароля для всех пользователей в моей базе данных. Если срок действия пароля истекает сегодня, он сгенерирует токен сброса пароля и отправит его пользователю по электронной почте. Затем пользователь нажимает ссылку в письме и попадает на веб-сайт, где вводит новый пароль.

Мне удалось создать токен в моей WebJob и отправить его по электронной почте. Однако при сбросе пароля через мой сайт Asp.NET я получаю неверный токен. Я не могу понять, почему. Я предполагаю, что это как-то связано с провайдером токенов из моего WebJob.

1) Мой сайт Asp.NET. Пользовательский UserManager:

public class CustomUserManager : UserManager<ApplicationUser> {
    public CustomUserManager(IUserStore<ApplicationUser> store) : base(store) { }          

    public static CustomUserManager Create(IdentityFactoryOptions<CustomUserManager> options, IOwinContext context) {
        var db = context.Get<DataContext>();
        var manager = new CustomUserManager(new UserStore<ApplicationUser>(db));
        // [...]          
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null) {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        // [...]   
        return manager;
    }
}

Который используется так:

userManager = HttpContext.GetOwinContext().Get<CustomUserManager>();
// [...]
await userManager.ResetPasswordAsync(model.Id, model.Token, model.ConfirmPassword); // token here is invalid (although the string looks like a proper token)

2) Моя функция WebJob:

public static async void CheckPasswords([QueueTrigger("checkpasswords")] string message) {
    using (var db = new DataContext())
    using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db))) {
        var provider = new DpapiDataProtectionProvider("MyApp");
        userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"));

        var users = await queryHandler.Run(new UserPasswordExpiryQuery());
        foreach (var user in users) {
            var days = new DateCalculations().DaysFromNow(user.PasswordExpiryDate);
            // if password expired today
            if (days == 0) {
                var token = await userManager.GeneratePasswordResetTokenAsync(user.Id);
                var url = string.Format("{0}/resetpass?user={1}&token={2}", settings.BaseUrl, user.Id, HttpUtility.UrlEncode(token));
                // [...] send email logic here
            }
        }
    }
}

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ

Я думаю, что я мог бы понять это. Я заменил провайдер токенов в своем приложении Asp.NET:

Старый код:

var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null) {
manager.UserTokenProvider =
    new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}

Новый код:

 var provider = new DpapiDataProtectionProvider("MyApp");
 manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("ASP.NET Identity"));

Сделаем некоторые дальнейшие испытания позже.

1 ответ

Возможно, что логика, которую вы используете, работает с некоторыми ограничениями в песочнице.

Если вы укажете имя вашего веб-приложения, прямо или косвенно, и время UTC для одного из таких сбоев, я потенциально могу это подтвердить.

Другие вопросы по тегам