diff --git a/src/Yavsc.Server/ViewModels/Account/VerifyCodeViewModel.cs b/src/Yavsc.Server/ViewModels/Account/VerifyCodeViewModel.cs index 223f6e8f..a113ac14 100644 --- a/src/Yavsc.Server/ViewModels/Account/VerifyCodeViewModel.cs +++ b/src/Yavsc.Server/ViewModels/Account/VerifyCodeViewModel.cs @@ -14,9 +14,6 @@ namespace Yavsc.ViewModels.Account public string ReturnUrl { get; set; } [Display(Name = "Se souvenir de ce navigateur?")] - public bool RememberBrowser { get; set; } - - [Display(Name = "Se souvenir de moi?")] public bool RememberMe { get; set; } } } diff --git a/src/Yavsc/Controllers/Accounting/AccountController.cs b/src/Yavsc/Controllers/Accounting/AccountController.cs index 332a36a8..7411f24c 100644 --- a/src/Yavsc/Controllers/Accounting/AccountController.cs +++ b/src/Yavsc/Controllers/Accounting/AccountController.cs @@ -26,10 +26,10 @@ namespace Yavsc.Controllers public class AccountController : Controller { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; const string nextPageTokenKey = "nextPageTokenKey"; const int defaultLen = 10; + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; private readonly IEmailSender _emailSender; // private readonly ISmsSender _smsSender; private readonly ILogger _logger; @@ -323,6 +323,19 @@ namespace Yavsc.Controllers _siteSettings.Audience)); return res; } + + private async Task SendEMailFactorAsync(ApplicationUser user, string provider) + { + var code = await _userManager.GenerateTwoFactorTokenAsync(user, provider); + var callbackUrl = Url.Action("VerifyCode", "Account", + new { userId = user.Id, code, provider }, protocol: "https", host: Startup.Authority); + var res = await _emailSender.SendEmailAsync(user.UserName, user.Email, + this._localizer["AccountEmailFactorTitle"], + string.Format(this._localizer["AccountEmailFactorBody"], + _siteSettings.Title, callbackUrl, _siteSettings.Slogan, + _siteSettings.Audience, code)); + return res; + } // // POST: /Account/LogOff [HttpPost(Constants.LogoutPath)] @@ -366,7 +379,7 @@ namespace Yavsc.Controllers } if (result.RequiresTwoFactor) { - return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); + return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe= true }); } if (result.IsLockedOut) { @@ -465,13 +478,41 @@ namespace Yavsc.Controllers IdentityResult result=null; try { result = await _userManager.ConfirmEmailAsync(user, code); + _dbContext.SaveChanges(userId); } catch (Exception ex) { _logger.LogError(ex.StackTrace); _logger.LogError(ex.Message); } - return View(result.Succeeded ? "ConfirmEmail" : "Error"); + return View(result.Succeeded ? "EmailConfirmed" : "Error"); + } + + // GET: /Account/ConfirmTwoFactorToken + [HttpGet] + [AllowAnonymous] + public async Task ConfirmTwoFactorToken(string userId, string code) + { + if (userId == null || code == null) + { + return View("Error"); + } + var user = await _userManager.FindByIdAsync(userId); + if (user == null) + { + return View("Error"); + } + bool result=false; + try { + result = await _userManager.VerifyTwoFactorTokenAsync(user, Constants.DefaultFactor, code); + _dbContext.SaveChanges(userId); + } + catch (Exception ex) + { + _logger.LogError(ex.StackTrace); + _logger.LogError(ex.Message); + } + return View(result ? "EmailConfirmed" : "Error"); } // @@ -607,7 +648,7 @@ namespace Yavsc.Controllers // // GET: /Account/SendCode [HttpGet, AllowAnonymous] - public async Task SendCode(string returnUrl = null, bool rememberMe = false) + public async Task SendCode(string returnUrl = null, bool rememberMe = true) { var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); if (user == null) @@ -615,11 +656,8 @@ namespace Yavsc.Controllers return View("Error", new Exception("No Two factor authentication user")); } - - var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user); - var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); } @@ -645,7 +683,7 @@ namespace Yavsc.Controllers { return View("Error", new Exception("No mobile app service was activated")); } - else // if (model.SelectedProvider == Constants.EMailFactor || model.SelectedProvider == "Default" ) + else if (model.SelectedProvider == Constants.SMSFactor) { return View("Error", new Exception("No SMS service was activated")); @@ -653,7 +691,7 @@ namespace Yavsc.Controllers } else // if (model.SelectedProvider == Constants.EMailFactor || model.SelectedProvider == "Default" ) { - var sent = await this.SendEMailForConfirmAsync(user); + var sent = await this.SendEMailFactorAsync(user, model.SelectedProvider); } return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); } @@ -662,7 +700,7 @@ namespace Yavsc.Controllers // GET: /Account/VerifyCode [HttpGet] [AllowAnonymous] - public async Task VerifyCode(string provider, bool rememberMe, string returnUrl = null) + public async Task VerifyCode(string code, string provider, bool rememberMe=true, string returnUrl = null) { // Require that the user has already logged in via username/password or external login var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); @@ -670,7 +708,8 @@ namespace Yavsc.Controllers { return View("Error", new Exception("user is null")); } - return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); + // it may be a GET response from some email url, or the web response to second fqctor requirement + return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe, Code = code }); } // @@ -690,12 +729,14 @@ namespace Yavsc.Controllers // will be locked out for a specified amount of time. _logger.LogWarning("Signin with code: {0} {1}", model.Provider, model.Code); - var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser); + var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberMe); if (result.Succeeded) { ViewData["StatusMessage"] = "Your code was verified"; _logger.LogInformation($"Signed in. returning to {model.ReturnUrl}"); + if (model.ReturnUrl!=null) return Redirect(model.ReturnUrl); + else RedirectToAction("Index","Home"); } if (result.IsLockedOut) { diff --git a/src/Yavsc/Helpers/Tags/MarkDownTagHelper.cs b/src/Yavsc/Helpers/Tags/MarkDownTagHelper.cs index e15ca4f5..cb00a72e 100644 --- a/src/Yavsc/Helpers/Tags/MarkDownTagHelper.cs +++ b/src/Yavsc/Helpers/Tags/MarkDownTagHelper.cs @@ -47,7 +47,8 @@ namespace Yavsc.TagHelpers string actual; var settings = CommonMarkSettings.Default.Clone(); settings.OutputFormat = OutputFormat.Html; - // settings.PrologueLineHandler = null; + settings.AdditionalFeatures |= CommonMarkAdditionalFeatures.StrikethroughTilde; + Block document; // Act diff --git a/src/Yavsc/Resources/Yavsc.YavscLocalisation.resx b/src/Yavsc/Resources/Yavsc.YavscLocalisation.resx index f6fd25b3..6782d8e1 100644 --- a/src/Yavsc/Resources/Yavsc.YavscLocalisation.resx +++ b/src/Yavsc/Resources/Yavsc.YavscLocalisation.resx @@ -463,10 +463,22 @@ Confirmation du mot de passe L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué. Un courrier a été envoyé pour confirmation de l'adresse e-mail . + + Le second facteur de votre identification + Votre compte est endurci d'une requisition d'un second facteur d'identification. + Une nouvelle connection depuis un navigateur web nécéssite votre authorisation. +Vous pouvez l'accorder en suivant le lien suivant : <{1}>. + +Votre code dáctivation est : {4} + +Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur. +{0} - {2} <{3}> S'il vous plait, confirmez votre addresse e-mail Vous avez créé avec succès votre compte {0}, mais votre adresse e-mail reste à confirmer. -Pour ce faire, suivez le lien suivant : <{1}>. + +Pour ce faire, veuillez, s'il vous plait, suivre le lien suivant +dans votre navigateur favori : <{1}>. -- {0} - {2} <{3}> diff --git a/src/Yavsc/Startup/Startup.OAuth.cs b/src/Yavsc/Startup/Startup.OAuth.cs index cb2380e9..1961ef3b 100644 --- a/src/Yavsc/Startup/Startup.OAuth.cs +++ b/src/Yavsc/Startup/Startup.OAuth.cs @@ -65,31 +65,30 @@ namespace Yavsc IdentityAppOptions = option; option.User.AllowedUserNameCharacters += " "; option.User.RequireUniqueEmail = true; - // option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; option.Cookies.ApplicationCookie.LoginPath = "/signin"; + // option.Cookies.TwoFactorRememberMeCookie.ExpireTimeSpan = TimeSpan.FromDays(30); + // option.Cookies.TwoFactorRememberMeCookie.DataProtectionProvider = ProtectionProvider; + // option.Cookies.ApplicationCookie.DataProtectionProvider = ProtectionProvider; + // option.Cookies.ExternalCookie.DataProtectionProvider = ProtectionProvider; // option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; /* - option.Cookies.ApplicationCookie.DataProtectionProvider = protector; option.Cookies.ApplicationCookie.LoginPath = new PathString(Constants.LoginPath.Substring(1)); option.Cookies.ApplicationCookie.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1)); option.Cookies.ApplicationCookie.AutomaticAuthenticate = true; option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme; option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme; - option.Cookies.TwoFactorRememberMeCookie.ExpireTimeSpan = TimeSpan.FromDays(30); - option.Cookies.TwoFactorRememberMeCookie.DataProtectionProvider = protector; option.Cookies.ExternalCookieAuthenticationScheme = Constants.ExternalAuthenticationSheme; option.Cookies.ExternalCookie.AutomaticAuthenticate = true; option.Cookies.ExternalCookie.AuthenticationScheme = Constants.ExternalAuthenticationSheme; - option.Cookies.ExternalCookie.DataProtectionProvider = protector; */ } ).AddEntityFrameworkStores() .AddTokenProvider>(Constants.DefaultFactor) // .AddTokenProvider(Constants.DefaultFactor) // .AddTokenProvider(Constants.SMSFactor) - // .AddTokenProvider(Constants.EMailFactor) + .AddTokenProvider(Constants.EMailFactor) // .AddTokenProvider(Constants.AppFactor) - // .AddDefaultTokenProviders() + // ; } private void ConfigureOAuthApp(IApplicationBuilder app, diff --git a/src/Yavsc/Views/Account/ConfirmEmail.cshtml b/src/Yavsc/Views/Account/EmailConfirmed.cshtml similarity index 100% rename from src/Yavsc/Views/Account/ConfirmEmail.cshtml rename to src/Yavsc/Views/Account/EmailConfirmed.cshtml diff --git a/src/Yavsc/Views/Account/VerifyCode.cshtml b/src/Yavsc/Views/Account/VerifyCode.cshtml index c1fd1560..1cce17ae 100755 --- a/src/Yavsc/Views/Account/VerifyCode.cshtml +++ b/src/Yavsc/Views/Account/VerifyCode.cshtml @@ -22,8 +22,8 @@
- - + +
diff --git a/src/Yavsc/wwwroot/favicon-yavsc.ico b/src/Yavsc/wwwroot/favicon-yavsc.ico new file mode 100644 index 00000000..0b8d8e63 Binary files /dev/null and b/src/Yavsc/wwwroot/favicon-yavsc.ico differ