Skip to content

Commit

Permalink
Merge hotfix
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm360 committed Nov 10, 2021
2 parents 0e5a5ef + 4c41298 commit ce0f1a4
Show file tree
Hide file tree
Showing 18 changed files with 296 additions and 89 deletions.
3 changes: 2 additions & 1 deletion src/EthernaSSO.Domain/Helpers/UsernameHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public static class UsernameHelper
{
// Consts.
public const string AllowedUsernameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._";
public const string UsernameRegex = "^[a-zA-Z0-9_]{5,20}$";
public const string UsernameRegex = "^[a-zA-Z0-9_]{5,25}$";
public const string UsernameValidationErrorMessage = "Allowed characters are a-z, A-Z, 0-9, _. Permitted length is between 5 and 25.";

// Methods.
public static bool IsValidUsername(string username) =>
Expand Down
5 changes: 1 addition & 4 deletions src/EthernaSSO.Persistence/ModelMaps/UserMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ public static ReferenceSerializer<UserBase, string> ReferenceSerializer(
mm.MapIdMember(m => m.Id);
mm.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId));
});
config.AddModelMapsSchema<UserBase>("834af7e2-c858-410a-b7b9-bdaf516fa215", mm =>
{
mm.MapMember(m => m.EtherAddress);
});
config.AddModelMapsSchema<UserBase>("834af7e2-c858-410a-b7b9-bdaf516fa215", mm => { });
config.AddModelMapsSchema<UserWeb2>("a1976133-bb21-40af-b6de-3a0f7f7dc676", mm => { });
config.AddModelMapsSchema<UserWeb3>("521125ff-f337-4606-81de-89dc0afb35b0", mm => { });
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Etherna.SSOServer.Domain.Events;
using Etherna.SSOServer.Domain.Helpers;
using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Etherna.SSOServer.Services.Domain;
using Etherna.SSOServer.Services.Settings;
using IdentityServer4.Services;
Expand Down Expand Up @@ -49,7 +50,7 @@ public class InputModel : IValidatableObject
public string? InvitationCode { get; set; }

[Required]
[RegularExpression(UsernameHelper.UsernameRegex, ErrorMessage = "Allowed characters are a-z, A-Z, 0-9, _. Permitted length is between 5 and 20.")]
[RegularExpression(UsernameHelper.UsernameRegex, ErrorMessage = UsernameHelper.UsernameValidationErrorMessage)]
[Display(Name = "Username")]
public string Username { get; set; } = default!;

Expand Down Expand Up @@ -150,7 +151,7 @@ public async Task<IActionResult> OnGetCallbackAsync(string? invitationCode, stri
if (logger.IsEnabled(LogLevel.Debug) && authResult.Principal is not null)
{
var externalClaims = authResult.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
logger.LogDebug("External claims: {@claims}", externalClaims);
logger.ExternalClaims(externalClaims);
}

// Get external login info and user.
Expand Down Expand Up @@ -185,7 +186,7 @@ await eventDispatcher.DispatchAsync(new UserLoginSuccessEvent(
clientId: context?.Client?.ClientId,
provider: info.LoginProvider,
providerUserId: info.ProviderKey));
logger.LogInformation($"{info.Principal.Identity.Name} logged in with {info.LoginProvider} provider.");
logger.LoggedInWithProvider(info.Principal.Identity.Name!, info.LoginProvider);

// Identify redirect.
return await ContextedRedirectAsync(context, returnUrl);
Expand Down Expand Up @@ -245,7 +246,7 @@ await eventDispatcher.DispatchAsync(new UserLoginSuccessEvent(
clientId: context?.Client?.ClientId,
provider: info.LoginProvider,
providerUserId: info.ProviderKey));
logger.LogInformation($"User created an account using {info.LoginProvider} provider.");
logger.CreatedAccountWithProvider(user.Id, info.LoginProvider);

// Redirect to add verified email page.
return RedirectToPage("SetVerifiedEmail", new { email, returnUrl });
Expand Down
5 changes: 3 additions & 2 deletions src/EthernaSSO/Areas/Identity/Pages/Account/Login.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Etherna.DomainEvents;
using Etherna.SSOServer.Domain.Events;
using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authentication;
Expand Down Expand Up @@ -119,7 +120,7 @@ await userManager.FindByEmailAsync(Input.UsernameOrEmail) :
{
// Rise event and create log.
await eventDispatcher.DispatchAsync(new UserLoginSuccessEvent(user, clientId: context?.Client?.ClientId));
logger.LogInformation("User logged in.");
logger.LoggedInWithPassword(user.Id);

// Identify redirect.
return await ContextedRedirectAsync(context, returnUrl);
Expand All @@ -132,7 +133,7 @@ await userManager.FindByEmailAsync(Input.UsernameOrEmail) :

else if (result.IsLockedOut)
{
logger.LogWarning("User account locked out.");
logger.LockedOutLoginAttempt(user.Id);
return RedirectToPage("./Lockout");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Etherna.DomainEvents;
using Etherna.SSOServer.Domain.Events;
using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authorization;
Expand Down Expand Up @@ -109,19 +110,19 @@ public async Task<IActionResult> OnPostAsync(string? returnUrl = null)

// Rise event and create log.
await eventDispatcher.DispatchAsync(new UserLoginSuccessEvent(user, clientId: context?.Client?.ClientId));
logger.LogInformation($"User with ID '{user.Id}' logged in with 2fa.");
logger.LoggedInWith2FA(user.Id);

// Identify redirect.
return await ContextedRedirectAsync(context, returnUrl);
}
else if (result.IsLockedOut)
{
logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
logger.LockedOutLoginAttempt(user.Id);
return RedirectToPage("./Lockout");
}
else
{
logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id);
logger.Invalid2FACodeAttempt(user.Id);
ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
return Page();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -38,14 +39,16 @@ public class InputModel
}

// Fields.
private readonly SignInManager<UserBase> _signInManager;
private readonly ILogger<LoginWithRecoveryCodeModel> _logger;
private readonly ILogger<LoginWithRecoveryCodeModel> logger;
private readonly SignInManager<UserBase> signInManager;

// Constructor.
public LoginWithRecoveryCodeModel(SignInManager<UserBase> signInManager, ILogger<LoginWithRecoveryCodeModel> logger)
public LoginWithRecoveryCodeModel(
ILogger<LoginWithRecoveryCodeModel> logger,
SignInManager<UserBase> signInManager)
{
_signInManager = signInManager;
_logger = logger;
this.logger = logger;
this.signInManager = signInManager;
}

// Properties.
Expand All @@ -58,7 +61,7 @@ public LoginWithRecoveryCodeModel(SignInManager<UserBase> signInManager, ILogger
public async Task<IActionResult> OnGetAsync(string? returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
var user = await signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
Expand All @@ -76,29 +79,29 @@ public async Task<IActionResult> OnPostAsync(string? returnUrl = null)
return Page();
}

var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
var user = await signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
}

var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty);

var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
var result = await signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);

if (result.Succeeded)
{
_logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id);
logger.LoggedInWithRecoveryCode(user.Id);
return LocalRedirect(returnUrl ?? Url.Content("~/"));
}
if (result.IsLockedOut)
{
_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
logger.LockedOutLoginAttempt(user.Id);
return RedirectToPage("./Lockout");
}
else
{
_logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id);
logger.InvalidRecoveryCodeAttempt(user.Id);
ModelState.AddModelError(string.Empty, "Invalid recovery code entered.");
return Page();
}
Expand Down
3 changes: 2 additions & 1 deletion src/EthernaSSO/Areas/Identity/Pages/Account/Logout.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Etherna.DomainEvents;
using Etherna.SSOServer.Domain.Events;
using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
Expand Down Expand Up @@ -116,7 +117,7 @@ private async Task<IActionResult> Logout()
{
await signInManager.SignOutAsync();

logger.LogInformation("User logged out.");
logger.LoggedOut();
var user = await userManager.GetUserAsync(User);
await eventDispatcher.DispatchAsync(new UserLogoutSuccessEvent(user));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
Expand Down Expand Up @@ -45,19 +46,19 @@ public class InputModel
}

// Fields.
private readonly UserManager<UserBase> _userManager;
private readonly SignInManager<UserBase> _signInManager;
private readonly ILogger<ChangePasswordModel> _logger;
private readonly ILogger<ChangePasswordModel> logger;
private readonly SignInManager<UserBase> signInManager;
private readonly UserManager<UserBase> userManager;

// Constructor.
public ChangePasswordModel(
UserManager<UserBase> userManager,
ILogger<ChangePasswordModel> logger,
SignInManager<UserBase> signInManager,
ILogger<ChangePasswordModel> logger)
UserManager<UserBase> userManager)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
this.logger = logger;
this.signInManager = signInManager;
this.userManager = userManager;
}

// Properties.
Expand All @@ -70,13 +71,13 @@ public ChangePasswordModel(
// Methods.
public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
var user = await userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'.");
}

var hasPassword = await _userManager.HasPasswordAsync(user);
var hasPassword = await userManager.HasPasswordAsync(user);
if (!hasPassword)
{
return RedirectToPage("./SetPassword");
Expand All @@ -92,13 +93,13 @@ public async Task<IActionResult> OnPostAsync()
return Page();
}

var user = await _userManager.GetUserAsync(User);
var user = await userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'.");
}

var changePasswordResult = await _userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword);
var changePasswordResult = await userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword);
if (!changePasswordResult.Succeeded)
{
foreach (var error in changePasswordResult.Errors)
Expand All @@ -108,8 +109,8 @@ public async Task<IActionResult> OnPostAsync()
return Page();
}

await _signInManager.RefreshSignInAsync(user);
_logger.LogInformation("User changed their password successfully.");
await signInManager.RefreshSignInAsync(user);
logger.PasswordChanged(user.Id);
StatusMessage = "Your password has been changed.";

return RedirectToPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

using Etherna.SSOServer.Domain;
using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Etherna.SSOServer.Services.Domain;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -158,7 +159,7 @@ private async Task DeleteUserHelperAsync(UserBase user)

await signInManager.SignOutAsync();

logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);
logger.AccountDeleted(userId, userId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
Expand Down Expand Up @@ -70,7 +71,7 @@ public async Task<IActionResult> OnPostAsync()
if (!disable2faResult.Succeeded)
throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{userManager.GetUserId(User)}'.");

logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", userManager.GetUserId(User));
logger.Disabled2FA(userManager.GetUserId(User));
StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app";
return RedirectToPage("./TwoFactorAuthentication");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
Expand Down Expand Up @@ -47,7 +48,7 @@ public async Task<IActionResult> OnPostAsync()
if (user == null)
return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'.");

logger.LogInformation($"User with ID '{userManager.GetUserId(User)}' asked for their personal data.");
logger.DownloadedPersonalData(userManager.GetUserId(User));

// Only include personal data for download
var personalData = new Dictionary<string, object?>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using Etherna.SSOServer.Domain.Models;
using Etherna.SSOServer.Extensions;
using Etherna.SSOServer.Services.Settings;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -118,7 +119,7 @@ public async Task<IActionResult> OnPostAsync()

await userManager.SetTwoFactorEnabledAsync(user, true);
var userId = await userManager.GetUserIdAsync(user);
logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId);
logger.Enabled2FAWithAuthApp(userId);

StatusMessage = "Your authenticator app has been verified.";

Expand Down Expand Up @@ -157,7 +158,7 @@ private string FormatKey(string unformattedKey)
int currentPosition = 0;
while (currentPosition + 4 < unformattedKey.Length)
{
result.Append(unformattedKey.Substring(currentPosition, 4)).Append(' ');
result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' ');
currentPosition += 4;
}
if (currentPosition < unformattedKey.Length)
Expand Down
Loading

0 comments on commit ce0f1a4

Please sign in to comment.