Merge pull request #2109 from sbwalker/dev

dogfooding fixes
This commit is contained in:
Shaun Walker 2022-04-04 10:54:50 -04:00 committed by GitHub
commit acc4099ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 173 additions and 123 deletions

View File

@ -93,45 +93,53 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
_togglepassword = Localizer["ShowPassword"]; try
if (PageState.Site.Settings.ContainsKey("LoginOptions:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]))
{ {
_allowsitelogin = bool.Parse(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]); _togglepassword = Localizer["ShowPassword"];
}
if (PageState.Site.Settings.ContainsKey("ExternalLogin:ProviderType") && !string.IsNullOrEmpty(PageState.Site.Settings["ExternalLogin:ProviderType"])) if (PageState.Site.Settings.ContainsKey("LoginOptions:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]))
{
_allowexternallogin = true;
}
if (PageState.QueryString.ContainsKey("returnurl"))
{
_returnUrl = PageState.QueryString["returnurl"];
}
if (PageState.QueryString.ContainsKey("name"))
{
_username = PageState.QueryString["name"];
}
if (PageState.QueryString.ContainsKey("token"))
{
var user = new User();
user.SiteId = PageState.Site.SiteId;
user.Username = _username;
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
if (user != null)
{ {
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username); _allowsitelogin = bool.Parse(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]);
AddModuleMessage(Localizer["Success.Account.Verified"], MessageType.Info);
} }
else
if (PageState.Site.Settings.ContainsKey("ExternalLogin:ProviderType") && !string.IsNullOrEmpty(PageState.Site.Settings["ExternalLogin:ProviderType"]))
{ {
await logger.LogError(LogFunction.Security, "Email Verification Failed For Username {Username}", _username); _allowexternallogin = true;
AddModuleMessage(Localizer["Message.Account.NotVerfied"], MessageType.Warning);
} }
if (PageState.QueryString.ContainsKey("returnurl"))
{
_returnUrl = PageState.QueryString["returnurl"];
}
if (PageState.QueryString.ContainsKey("name"))
{
_username = PageState.QueryString["name"];
}
if (PageState.QueryString.ContainsKey("token"))
{
var user = new User();
user.SiteId = PageState.Site.SiteId;
user.Username = _username;
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
if (user != null)
{
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username);
AddModuleMessage(Localizer["Success.Account.Verified"], MessageType.Info);
}
else
{
await logger.LogError(LogFunction.Security, "Email Verification Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Message.Account.NotVerfied"], MessageType.Warning);
}
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Login {Error}", ex.Message);
AddModuleMessage(Localizer["Error.LoadLogin"], MessageType.Error);
} }
} }
@ -145,65 +153,73 @@
private async Task Login() private async Task Login()
{ {
validated = true; try
var interop = new Interop(JSRuntime);
if (await interop.FormValid(login))
{ {
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password}; validated = true;
var interop = new Interop(JSRuntime);
if (!twofactor) if (await interop.FormValid(login))
{ {
user = await UserService.LoginUserAsync(user, false, false); var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password};
}
else
{
user = await UserService.VerifyTwoFactorAsync(user, _code);
}
if (user.IsAuthenticated) if (!twofactor)
{
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
{ {
// server-side Blazor needs to post to the Login page so that the cookies are set correctly user = await UserService.LoginUserAsync(user, false, false);
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
await interop.SubmitForm(url, fields);
} }
else else
{ {
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); user = await UserService.VerifyTwoFactorAsync(user, _code);
authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
} }
}
else if (user.IsAuthenticated)
{
if (user.TwoFactorRequired)
{ {
twofactor = true; await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
validated = false;
AddModuleMessage(Localizer["Message.TwoFactor"], MessageType.Info); if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
}
else
{
if (!twofactor)
{ {
await logger.LogInformation(LogFunction.Security, "Login Failed For Username {Username}", _username); // server-side Blazor needs to post to the Login page so that the cookies are set correctly
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error); var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
await interop.SubmitForm(url, fields);
} }
else else
{ {
await logger.LogInformation(LogFunction.Security, "Two Factor Verification Failed For Username {Username}", _username); var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
AddModuleMessage(Localizer["Error.TwoFactor.Fail"], MessageType.Error); authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
}
}
else
{
if (user.TwoFactorRequired)
{
twofactor = true;
validated = false;
AddModuleMessage(Localizer["Message.TwoFactor"], MessageType.Info);
}
else
{
if (!twofactor)
{
await logger.LogInformation(LogFunction.Security, "Login Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error);
}
else
{
await logger.LogInformation(LogFunction.Security, "Two Factor Verification Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.TwoFactor.Fail"], MessageType.Error);
}
} }
} }
} }
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
} }
else catch (Exception ex)
{ {
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning); await logger.LogError(ex, "Error Performing Login {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Login"], MessageType.Error);
} }
} }
@ -214,26 +230,34 @@
private async Task Forgot() private async Task Forgot()
{ {
if (_username != string.Empty) try
{ {
var user = await UserService.GetUserAsync(_username, PageState.Site.SiteId); if (_username != string.Empty)
if (user != null)
{ {
await UserService.ForgotPasswordAsync(user); var user = await UserService.GetUserAsync(_username, PageState.Site.SiteId);
await logger.LogInformation(LogFunction.Security, "Password Reset Notification Sent For Username {Username}", _username); if (user != null)
AddModuleMessage(Localizer["Message.ForgotUser"], MessageType.Info); {
await UserService.ForgotPasswordAsync(user);
await logger.LogInformation(LogFunction.Security, "Password Reset Notification Sent For Username {Username}", _username);
AddModuleMessage(Localizer["Message.ForgotUser"], MessageType.Info);
}
else
{
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning);
}
} }
else else
{ {
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning); AddModuleMessage(Localizer["Message.ForgotPassword"], MessageType.Info);
} }
}
else
{
AddModuleMessage(Localizer["Message.ForgotPassword"], MessageType.Info);
}
StateHasChanged(); StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Resetting Password {Error}", ex.Message);
AddModuleMessage(Localizer["Error.ResetPassword"], MessageType.Error);
}
} }
private void Reset() private void Reset()

View File

@ -155,7 +155,7 @@
} }
} }
if (log.PageId != null && log.ModuleId != null) if (log.PageId != null && log.ModuleId != null && log.ModuleId != -1)
{ {
var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value); var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value);
if (pagemodule != null) if (pagemodule != null)

View File

@ -192,4 +192,13 @@
<data name="Use" xml:space="preserve"> <data name="Use" xml:space="preserve">
<value>Use</value> <value>Use</value>
</data> </data>
<data name="Error.LoadLogin" xml:space="preserve">
<value>Error Loading Login</value>
</data>
<data name="Error.Login" xml:space="preserve">
<value>Error Performing Login</value>
</data>
<data name="Error.ResetPassword" xml:space="preserve">
<value>Error Resetting Password</value>
</data>
</root> </root>

View File

@ -34,7 +34,7 @@ namespace Oqtane.Themes.Controls
protected async Task LogoutUser() protected async Task LogoutUser()
{ {
await UserService.LogoutUserAsync(PageState.User); await UserService.LogoutUserAsync(PageState.User);
await LoggingService.Log(PageState.Alias, PageState.Page.PageId, PageState.ModuleId, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username); await LoggingService.Log(PageState.Alias, PageState.Page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username);
PageState.User = null; PageState.User = null;
var url = PageState.Alias.Path + "/" + PageState.Page.Path; var url = PageState.Alias.Path + "/" + PageState.Page.Path;

View File

@ -184,7 +184,7 @@ namespace Microsoft.Extensions.DependencyInjection
options.SignIn.RequireConfirmedPhoneNumber = false; options.SignIn.RequireConfirmedPhoneNumber = false;
// User settings // User settings
options.User.RequireUniqueEmail = true; options.User.RequireUniqueEmail = false; // changing to true will cause issues for legacy data
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
}); });

View File

@ -199,56 +199,73 @@ namespace Oqtane.Extensions
} }
User user = null; User user = null;
var identityuser = await _identityUserManager.FindByEmailAsync(email); bool duplicates = false;
IdentityUser identityuser = null;
try
{
identityuser = await _identityUserManager.FindByEmailAsync(email);
}
catch
{
// FindByEmailAsync will throw an error if the email matches multiple user accounts
duplicates = true;
}
if (identityuser == null) if (identityuser == null)
{ {
if (bool.Parse(httpContext.GetSiteSettings().GetValue("ExternalLogin:CreateUsers", "true"))) if (duplicates)
{ {
identityuser = new IdentityUser(); _logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Multiple Users Exist With Email Address {Email}. Login Denied.", email);
identityuser.UserName = email; }
identityuser.Email = email; else
identityuser.EmailConfirmed = true; {
var result = await _identityUserManager.CreateAsync(identityuser, DateTime.UtcNow.ToString("yyyy-MMM-dd-HH-mm-ss")); if (bool.Parse(httpContext.GetSiteSettings().GetValue("ExternalLogin:CreateUsers", "true")))
if (result.Succeeded)
{ {
user = new User identityuser = new IdentityUser();
identityuser.UserName = email;
identityuser.Email = email;
identityuser.EmailConfirmed = true;
var result = await _identityUserManager.CreateAsync(identityuser, DateTime.UtcNow.ToString("yyyy-MMM-dd-HH-mm-ss"));
if (result.Succeeded)
{ {
SiteId = httpContext.GetAlias().SiteId, user = new User
Username = email, {
DisplayName = email, SiteId = httpContext.GetAlias().SiteId,
Email = email, Username = email,
LastLoginOn = null, DisplayName = email,
LastIPAddress = "" Email = email,
}; LastLoginOn = null,
user = _users.AddUser(user); LastIPAddress = ""
};
user = _users.AddUser(user);
if (user != null) if (user != null)
{ {
var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>(); var _notifications = httpContext.RequestServices.GetRequiredService<INotificationRepository>();
string url = httpContext.Request.Scheme + "://" + httpContext.GetAlias().Name; string url = httpContext.Request.Scheme + "://" + httpContext.GetAlias().Name;
string body = "You Recently Used An External Account To Sign In To Our Site.\n\n" + url + "\n\nThank You!"; string body = "You Recently Used An External Account To Sign In To Our Site.\n\n" + url + "\n\nThank You!";
var notification = new Notification(user.SiteId, user, "User Account Notification", body); var notification = new Notification(user.SiteId, user, "User Account Notification", body);
_notifications.AddNotification(notification); _notifications.AddNotification(notification);
// add user login // add user login
await _identityUserManager.AddLoginAsync(identityuser, new UserLoginInfo(providerType, providerKey, "")); await _identityUserManager.AddLoginAsync(identityuser, new UserLoginInfo(providerType, providerKey, ""));
_logger.Log(user.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "User Added {User}", user); _logger.Log(user.SiteId, LogLevel.Information, "ExternalLogin", Enums.LogFunction.Create, "User Added {User}", user);
}
else
{
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add User {Email}", email);
}
} }
else else
{ {
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add User {Email}", email); _logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add Identity User {Email} {Error}", email, result.Errors.ToString());
} }
} }
else else
{ {
_logger.Log(user.SiteId, LogLevel.Error, "ExternalLogin", Enums.LogFunction.Create, "Unable To Add Identity User {Email} {Error}", email, result.Errors.ToString()); _logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Creation Of New Users Is Disabled For This Site. User With Email Address {Email} Will First Need To Be Registered On The Site.", email);
} }
} }
else
{
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Creation Of New Users Is Disabled For This Site. User With Email Address {Email} Will First Need To Be Registered On The Site.", email);
}
} }
else else
{ {