Passwor re-init

This commit is contained in:
Paul Schneider
2025-09-07 17:43:13 +01:00
parent 111ada56f7
commit 9c5ea692b0
14 changed files with 67 additions and 55 deletions

View File

@ -16,7 +16,7 @@
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework" Version="8.0.5-preview-net9" /> <PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.Security" Version="8.0.5-preview-net9" /> <PackageVersion Include="HigginsSoft.IdentityServer8.Security" Version="8.0.5-preview-net9" />
<PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" /> <PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" />
<PackageVersion Include="MailKit" Version="4.13.0" /> <PackageVersion Include="MailKit" Version="4.8.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.0" /> <PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" /> <PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
@ -42,7 +42,7 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.53.0" /> <PackageVersion Include="Microsoft.Playwright" Version="1.53.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" /> <PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="MimeKit" Version="4.13.0" /> <PackageVersion Include="MimeKit" Version="4.8.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" /> <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" /> <PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" />

View File

@ -0,0 +1,18 @@
namespace Yavsc.Services
{
[Serializable]
internal class YavscInfrastructureException : Exception
{
public YavscInfrastructureException()
{
}
public YavscInfrastructureException(string? message) : base(message)
{
}
public YavscInfrastructureException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
}

View File

@ -453,7 +453,6 @@
<data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data> <data name="PasswordConfirm"><value>Confirmation du mot de passe</value></data>
<data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data> <data name="ErrorSendingEmailForConfirm"><value>L'envoi de de courrier pour confirmation de l'adresse e-mail a échoué.</value></data>
<data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data> <data name="EmailSentForConfirm"><value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value></data>
<data name="ConfirmYourAccountTitle"><value>S'il vous plait, confirmez votre addresse e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0}, <data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer. mais votre adresse e-mail reste à confirmer.
Pour ce faire, suivez le lien suivant : &lt;{1}&gt;. Pour ce faire, suivez le lien suivant : &lt;{1}&gt;.

View File

@ -775,7 +775,6 @@ Valid caracters are: underscore '_', '-', 'a' - 'z', 'A' - 'Z', '0' - '9', th
<data name="EmailSentForConfirm"> <data name="EmailSentForConfirm">
<value>An email has been sent to confirm your addresse.</value> <value>An email has been sent to confirm your addresse.</value>
</data> </data>
<data name="ConfirmYourAccountTitle"><value>Please, confirm your e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>You successfully created your {0} account, <data name="ConfirmYourAccountBody"><value>You successfully created your {0} account,
but your e-mail address is not yet confirmed. but your e-mail address is not yet confirmed.
Please, in order to validate it, follow this link &lt;{1}&gt;. Please, in order to validate it, follow this link &lt;{1}&gt;.

View File

@ -437,7 +437,6 @@
<data name="ConfirmPassword"><value>Confirme sua senha</value></data> <data name="ConfirmPassword"><value>Confirme sua senha</value></data>
<data name="ErrorSendingEmailForConfirm"><value>O envio de e-mail para confirmação do endereço de e-mail falhou.</value></data> <data name="ErrorSendingEmailForConfirm"><value>O envio de e-mail para confirmação do endereço de e-mail falhou.</value></data>
<data name="EmailSentForConfirm"><value>Um e-mail foi enviado para confirmação do endereço de e-mail.</value></data> <data name="EmailSentForConfirm"><value>Um e-mail foi enviado para confirmação do endereço de e-mail.</value></data>
<data name="ConfirmYourAccountTitle"><value>Por favor, confirme seu endereço de e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Você criou sua conta {0} com sucesso, <data name="ConfirmYourAccountBody"><value>Você criou sua conta {0} com sucesso,
mas o seu endereço de e-mail tem que ser confirmado. mas o seu endereço de e-mail tem que ser confirmado.
Para fazer isso, siga o seguinte link : &lt;{1}&gt;. Para fazer isso, siga o seguinte link : &lt;{1}&gt;.

View File

@ -230,7 +230,6 @@ Votre code dáctivation est : {4}
Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur. Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur.
{0} - {2} &lt;{3}&gt;</value></data> {0} - {2} &lt;{3}&gt;</value></data>
<data name="ConfirmYourAccountTitle"><value>S'il vous plait, confirmez votre addresse e-mail</value></data>
<data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0}, <data name="ConfirmYourAccountBody"><value>Vous avez créé avec succès votre compte {0},
mais votre adresse e-mail reste à confirmer. mais votre adresse e-mail reste à confirmer.

View File

@ -47,8 +47,6 @@ namespace Yavsc.Services
/// <returns>a MessageWithPayloadResponse, /// <returns>a MessageWithPayloadResponse,
/// <c>bool somethingsent = (response.failure == 0 &amp;&amp; response.success > 0)</c> /// <c>bool somethingsent = (response.failure == 0 &amp;&amp; response.success > 0)</c>
/// </returns> /// </returns>
public async Task SendEmailAsync(string email, string subject, string htmlMessage) public async Task SendEmailAsync(string email, string subject, string htmlMessage)
{ {
await SendEmailAsync("", email, subject, htmlMessage); await SendEmailAsync("", email, subject, htmlMessage);
@ -57,7 +55,7 @@ namespace Yavsc.Services
public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage) public async Task<string> SendEmailAsync(string name, string email, string subject, string htmlMessage)
{ {
logger.LogInformation($"SendEmail for {email} : {subject}"); logger.LogInformation($"SendEmail for {email} : {subject}");
MimeMessage msg = new (); MimeMessage msg = new();
msg.From.Add(new MailboxAddress(siteSettings.Owner.Name, msg.From.Add(new MailboxAddress(siteSettings.Owner.Name,
siteSettings.Owner.EMail)); siteSettings.Owner.EMail));
msg.To.Add(new MailboxAddress(name, email)); msg.To.Add(new MailboxAddress(name, email));
@ -69,20 +67,22 @@ namespace Yavsc.Services
msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId( msg.MessageId = MimeKit.Utils.MimeUtils.GenerateMessageId(
siteSettings.Authority siteSettings.Authority
); );
using (SmtpClient sc = new ()) using (SmtpClient sc = new())
{ {
sc.Connect( sc.Connect(
smtpSettings.Server, smtpSettings.Server,
smtpSettings.Port, smtpSettings.Port,
SecureSocketOptions.Auto); SecureSocketOptions.Auto
);
if (smtpSettings.UserName!=null) { if (smtpSettings.UserName != null)
NetworkCredential creds = new ( {
smtpSettings.UserName, smtpSettings.Password); sc.Authenticate(smtpSettings.UserName, smtpSettings.Password);
await sc.AuthenticateAsync(System.Text.Encoding.UTF8, creds, System.Threading.CancellationToken.None);
} }
await sc.SendAsync(msg); await sc.SendAsync(msg);
logger.LogInformation($"Sent : {msg.MessageId}"); logger.LogInformation($"Sent : {msg.MessageId}");
sc.Disconnect(true);
} }
return msg.MessageId; return msg.MessageId;
} }

View File

@ -14,14 +14,17 @@ namespace Yavsc
public string FavIcon { get; set; } = "favicon.ico"; public string FavIcon { get; set; } = "favicon.ico";
public string Logo { get; set; } = "logo.png"; public string Logo { get; set; } = "logo.png";
/// <summary> /// <summary>
/// Conceptually,
/// This authorisation server only has this present site as unique audience.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public string Audience { get; set; } = "lua.pschneider.fr"; public string Audience { get; set; } = "lua.pschneider.fr";
/// <summary> /// <summary>
/// it's a very small company, with one domaine name only, /// External Url
/// so let it be the same as in the Audience field. /// </summary>
/// <value></value>
public string ExternalUrl { get; set; } = "http://lua.pschneider.fr";
/// <summary>
/// Must be a fqdn.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public string Authority { get; set; } = "lua.pschneider.fr"; public string Authority { get; set; } = "lua.pschneider.fr";

View File

@ -84,9 +84,7 @@ namespace Yavsc.Controllers
_logger = loggerFactory.CreateLogger<AccountController>(); _logger = loggerFactory.CreateLogger<AccountController>();
_dbContext = dbContext; _dbContext = dbContext;
var type = typeof(AccountController); _localizer = localizerFactory.Create(typeof(AccountController));
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = localizerFactory.Create(type);
} }
@ -865,11 +863,13 @@ namespace Yavsc.Controllers
{ {
ApplicationUser user; ApplicationUser user;
// Username should not contain any '@' // Username should not contain any '@'
if (model.LoginOrEmail.Contains('@')) { if (model.LoginOrEmail.Contains('@'))
{
user = await _userManager.FindByEmailAsync(model.LoginOrEmail); user = await _userManager.FindByEmailAsync(model.LoginOrEmail);
} }
else { else
user = await _dbContext.Users.FirstOrDefaultAsync( u => u.UserName == model.LoginOrEmail); {
user = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserName == model.LoginOrEmail);
} }
// Don't reveal that the user does not exist or is not confirmed // Don't reveal that the user does not exist or is not confirmed
@ -892,7 +892,8 @@ namespace Yavsc.Controllers
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713 // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link // Send an email with this link
var code = await _userManager.GeneratePasswordResetTokenAsync(user); var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = _siteSettings.Audience + "/Account/ResetPassword/" + var f = this.HttpContext.Features;
var callbackUrl = _siteSettings.ExternalUrl + "/Account/ResetPassword/" +
HttpUtility.UrlEncode(user.Id) + "/" + HttpUtility.UrlEncode(code); HttpUtility.UrlEncode(user.Id) + "/" + HttpUtility.UrlEncode(code);
@ -900,6 +901,8 @@ namespace Yavsc.Controllers
_localizer["Please reset your password by "] + " <a href=\"" + _localizer["Please reset your password by "] + " <a href=\"" +
callbackUrl + "\" >following this link</a>"); callbackUrl + "\" >following this link</a>");
return View("ForgotPasswordConfirmation", sent); return View("ForgotPasswordConfirmation", sent);
} }
// If we got this far, something failed, redisplay form // If we got this far, something failed, redisplay form
@ -1133,10 +1136,6 @@ namespace Yavsc.Controllers
return await _userManager.DeleteAsync(user); return await _userManager.DeleteAsync(user);
} }
#region Helpers
private void AddErrors(IdentityResult result) private void AddErrors(IdentityResult result)
{ {
foreach (var error in result.Errors) foreach (var error in result.Errors)
@ -1145,15 +1144,5 @@ namespace Yavsc.Controllers
} }
} }
private async Task<ApplicationUser> GetCurrentUserAsync()
{
return await GetCurrentUserAsync(HttpContext.User.GetUserId());
}
private async Task<ApplicationUser> GetCurrentUserAsync(string id)
{
return await _userManager.FindByIdAsync(id);
}
#endregion
} }
} }

View File

@ -87,4 +87,6 @@ Please, follow this link to confirm your account : &lt;{1}&gt;.
-- --
{0} - {2} &lt;{3}&gt;</value> {0} - {2} &lt;{3}&gt;</value>
</data> </data>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root> </root>

View File

@ -61,4 +61,6 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root> </root>

View File

@ -89,4 +89,6 @@ Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette
<value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value> <value>Un courrier a été envoyé pour confirmation de l'adresse e-mail .</value>
</data> </data>
<data name="Reset Password"><value>Ré-initialiser votre mot de passe</value></data>
<data name="Reset password confirmation"><value>Confirmation de ré-initialisation du mot de passe</value></data>
</root> </root>

View File

@ -471,7 +471,6 @@ Votre code dáctivation est : {4}
Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur. Vour pourrez cochez la case "Se souvenir de ce navigateur" pour conserver cette authorisation pour ce navigateur.
{0} - {2} &lt;{3}&gt;</value></data> {0} - {2} &lt;{3}&gt;</value></data>
<data name="ConfirmYourAccountTitle"><value>S'il vous plait, confirmez votre addresse e-mail</value></data>
<data name="BadStringLength"><value>Taille maximale: {0} caractère.</value></data> <data name="BadStringLength"><value>Taille maximale: {0} caractère.</value></data>
<data name="DetailledMinMaxStringLength"><value>Ce champ est <data name="DetailledMinMaxStringLength"><value>Ce champ est

1
src/Yavsc/tempkey.jwk Normal file
View File

@ -0,0 +1 @@
{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"HQxDb0hC8hkvwiC9eL7Xgi3oxVuD2KhYRf2LgdVbTNNp7hof2ZxHQaRJBUjXXWu5dgjEFTbYHugydnsUb-y9fO-Q_k2mHYrCwwRGRR8_B1bqX6Or98PDKMLj8JOCoRWUe238hUjqdfm3X-wjLco9iEe86UUWnhPhsTKQ8hGuI7vo5c5BEF9Y3T9duITK0c3hgJQGujLUQLbCCP2MX0BR-tmvnBPV1mPe5fMkW79CymmlBdc8RjPNA_YLtLD4znZGoh7Fr_G1WpO6HdDyqnjqIof9QFSY9zjGissOhs6k5xZrTdego6giHk_hhxLsHvf9lekfL1XcOt97j28mooXGUQ","DP":"5gUJNJI-z3swRqAX0YSZxKjD1bbOl-HgEU9Bkrz_U6myVGziVnjrrLT92ymu7XiERwhRm4Hv-UNgCSipUA5wkTNw_qANbibcMAqjLqtXtC9OOraE9zw0fw72BzFp3BF2AvaUZlByyr45IJGyVVOg-AxCgaLinoWa15hjpVVLBck","DQ":"MVwIv2v0k93-nqLkTfU7UXe5lifNfqwK_h6wFrlPv2eRiPFs016-9epfAYz4w0KqHaFzZtK-_XDet_f6-Vommn4DjahTzBbyUWKPxo2jmu06hne8naoeLYP0VqRtbVVlq_rP5VKwb3SMnxj02FjpuDdSvbaEgJiCLjfv-mP3x8c","E":"AQAB","K":null,"KeyId":"31CBEC0AA49B244C218F53DA8D15FAF8","KeyOps":[],"Kid":"31CBEC0AA49B244C218F53DA8D15FAF8","Kty":"RSA","N":"vrBmdOxP7dksWCfJieoorbBgxiPlgcY1QpBbESso_7XpcGbtwK7Nmfbe_sy_jtdEi586MQBb6g7W663hnQyZ5j9etC6uNo5XkqJ4oAPvjWjjdx7HPyjhkSOgj6dS-mGNCzn36ZLkZacAxvDhxh409QGWEe7MpFB6ZRK9bj7hn77FMFvTnI71YU3sL3w35W3wjw30jyw4oaAA6cDA0dLLSc5wutu76KPxcyQGOhXtcOnUd0c1XYuOIAffg6EcmGSe5nF5iCZYk9Y7MuYKH07w6cVlPgKuOATSOuMSo7bp7Kgd-tuqvelJbGryNoAd4V_Fo6pgLbJoY8IeZDr9CDxZgw","Oth":[],"P":"8WfFywgbOmCiJwupMdgNF0VsdZ5VcgsAwlkrLSWAvIzihD99Fz3J9VPYnLtXW5b144CfJLz8nEnMDYPTqYw_dZ2rT9rsiUUvbVzeKvDVTjDLYNvdhZeseyoXIVfoHStoAdKXQqdhcVtDcuv3E0zszfuAP-jMMh0cwlTfscjauz0","Q":"yjexMUjUY5RvhN127pC4NKqkD5PABxDgt3w8ENuJZbAo-dJ72Ay2MFGAhNMVp-DZIijS_OntyqTNLADhFmf8nh6ZNRyvRYNPpvkvb0qf4QgSn2TiXm3wJrKG8mTJuuFWnUDTf3D2GLFAHk2MtAemh3-C34SezLHORjkaEvqLs78","QI":"KQRvX-At5Rb16A0R7hE0JOB2oNJKcbAoQHKttFBU9KeQo17TIBzt4R_ABswbWjmLRN_mzfaag8nrN-mOeeOzzgqt3xMjibRB4HJ0MBndt5wi4SEyHt3Me_-7fUN85SZR6DsNt2w05QTojsUBq4ah4RXAXIT5SqwcUE4ztBbM5Vw","Use":null,"X":null,"X5c":[],"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true,"SignatureProviderObjectPoolCacheSize":16}}