From 28eb233420779e8cfdb7baab92eb1dbf02527a26 Mon Sep 17 00:00:00 2001 From: artem-dudarev Date: Thu, 8 Aug 2024 12:34:24 +0200 Subject: [PATCH 1/5] Ignore expired password when using external sign in --- .../Schemas/UserType.cs | 20 ++++++++++++++----- ...rce.ProfileExperienceApiModule.Data.csproj | 4 ++-- .../module.manifest | 4 ++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs index 9ec29e88..270bd1da 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs @@ -1,15 +1,18 @@ using System; using System.Linq; using System.Threading.Tasks; +using GraphQL; using GraphQL.Resolvers; using GraphQL.Types; using MediatR; using Microsoft.Extensions.Options; -using VirtoCommerce.Xapi.Core.Helpers; -using VirtoCommerce.Xapi.Core.Services; using VirtoCommerce.Platform.Core.Security; +using VirtoCommerce.Platform.Security.Extensions; using VirtoCommerce.ProfileExperienceApiModule.Data.Aggregates.Contact; using VirtoCommerce.ProfileExperienceApiModule.Data.Queries; +using VirtoCommerce.Xapi.Core.Extensions; +using VirtoCommerce.Xapi.Core.Helpers; +using VirtoCommerce.Xapi.Core.Services; namespace VirtoCommerce.ProfileExperienceApiModule.Data.Schemas { @@ -31,7 +34,6 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan Field(x => x.ModifiedDate, true); Field(x => x.NormalizedEmail, true); Field(x => x.NormalizedUserName, true); - Field(x => x.PasswordExpired); Field(x => x.PhoneNumber, true); Field(x => x.PhoneNumberConfirmed); Field(x => x.PhotoUrl, true); @@ -42,8 +44,11 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan Field(x => x.TwoFactorEnabled); Field(x => x.UserName); Field(x => x.UserType, true); - Field("forcePasswordChange", resolve: x => x.Source.PasswordExpired, description: "Make this user change their password when they sign in next time"); - Field("passwordExpiryInDays", resolve: x => GetPasswordExpiryInDays(userOptionsExtended.Value, x.Source), description: "Password expiry in days"); + + Field("PasswordExpired", resolve: x => IsExternalSignIn(x) ? false : x.Source.PasswordExpired); + Field("forcePasswordChange", resolve: x => IsExternalSignIn(x) ? false : x.Source.PasswordExpired, description: "Make this user change their password when they sign in next time"); + Field("passwordExpiryInDays", resolve: x => IsExternalSignIn(x) ? null : GetPasswordExpiryInDays(userOptionsExtended.Value, x.Source), description: "Password expiry in days"); + AddField(new FieldType { @@ -91,6 +96,11 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan }); } + private static bool IsExternalSignIn(IResolveFieldContext context) + { + return context.Source.Id == context.GetCurrentUserId() && context.GetCurrentPrincipal().IsExternalSignIn(); + } + private static int? GetPasswordExpiryInDays(UserOptionsExtended userOptionsExtended, ApplicationUser user) { var result = (int?)null; diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj index 6ae397a1..ac783a4c 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj @@ -19,9 +19,9 @@ - + - + diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest index c3c946a3..53895e9b 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest @@ -4,9 +4,9 @@ 3.813.0 - 3.841.0 + 3.848.0-alpha.12968-vcst-1431 - + From b4cb1cbd6a056a3ed3312998c72f78348b407198 Mon Sep 17 00:00:00 2001 From: artem-dudarev Date: Thu, 8 Aug 2024 13:12:27 +0200 Subject: [PATCH 2/5] Refactoring --- .../Schemas/UserType.cs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs index 270bd1da..ca12943e 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs @@ -45,9 +45,9 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan Field(x => x.UserName); Field(x => x.UserType, true); - Field("PasswordExpired", resolve: x => IsExternalSignIn(x) ? false : x.Source.PasswordExpired); - Field("forcePasswordChange", resolve: x => IsExternalSignIn(x) ? false : x.Source.PasswordExpired, description: "Make this user change their password when they sign in next time"); - Field("passwordExpiryInDays", resolve: x => IsExternalSignIn(x) ? null : GetPasswordExpiryInDays(userOptionsExtended.Value, x.Source), description: "Password expiry in days"); + Field("passwordExpired", resolve: x => GetPasswordExpired(x)); + Field("forcePasswordChange", resolve: x => GetPasswordExpired(x), description: "Make this user change their password when they sign in next time"); + Field("passwordExpiryInDays", resolve: x => GetPasswordExpiryInDays(x, userOptionsExtended.Value), description: "Password expiry in days"); AddField(new FieldType @@ -96,16 +96,19 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan }); } - private static bool IsExternalSignIn(IResolveFieldContext context) + private static bool GetPasswordExpired(IResolveFieldContext context) { - return context.Source.Id == context.GetCurrentUserId() && context.GetCurrentPrincipal().IsExternalSignIn(); + return context.Source.PasswordExpired && !IsExternalSignIn(context); } - private static int? GetPasswordExpiryInDays(UserOptionsExtended userOptionsExtended, ApplicationUser user) + private static int? GetPasswordExpiryInDays(IResolveFieldContext context, UserOptionsExtended userOptionsExtended) { var result = (int?)null; + var user = context.Source; + if (!user.PasswordExpired && + !IsExternalSignIn(context) && userOptionsExtended.RemindPasswordExpiryInDays > 0 && userOptionsExtended.MaxPasswordAge != null && userOptionsExtended.MaxPasswordAge.Value > TimeSpan.Zero) @@ -122,5 +125,10 @@ private static bool IsExternalSignIn(IResolveFieldContext conte return result; } + + private static bool IsExternalSignIn(IResolveFieldContext context) + { + return context.Source.Id == context.GetCurrentUserId() && context.GetCurrentPrincipal().IsExternalSignIn(); + } } } From 92f40d81366488a9eecb9354f2a9ebc680505be0 Mon Sep 17 00:00:00 2001 From: artem-dudarev Date: Thu, 8 Aug 2024 13:18:34 +0200 Subject: [PATCH 3/5] Make passwordExpired not nullable --- .../Schemas/UserType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs index ca12943e..8cc36d6f 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/UserType.cs @@ -45,7 +45,7 @@ public UserType(IContactAggregateRepository contactAggregateRepository, IUserMan Field(x => x.UserName); Field(x => x.UserType, true); - Field("passwordExpired", resolve: x => GetPasswordExpired(x)); + Field>("passwordExpired", resolve: x => GetPasswordExpired(x)); Field("forcePasswordChange", resolve: x => GetPasswordExpired(x), description: "Make this user change their password when they sign in next time"); Field("passwordExpiryInDays", resolve: x => GetPasswordExpiryInDays(x, userOptionsExtended.Value), description: "Password expiry in days"); From ae548db9a044d41f57ce924122a9f2e10ee59aca Mon Sep 17 00:00:00 2001 From: artem-dudarev Date: Fri, 9 Aug 2024 12:08:10 +0200 Subject: [PATCH 4/5] Ignore expired password when using external sign in --- .../Schemas/ProfileSchema.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/ProfileSchema.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/ProfileSchema.cs index 044758bc..eeefe175 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/ProfileSchema.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/ProfileSchema.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Logging; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.Platform.Security.Authorization; +using VirtoCommerce.Platform.Security.Extensions; using VirtoCommerce.ProfileExperienceApiModule.Data.Aggregates; using VirtoCommerce.ProfileExperienceApiModule.Data.Aggregates.Contact; using VirtoCommerce.ProfileExperienceApiModule.Data.Aggregates.Organization; @@ -756,7 +757,9 @@ userName isAdministrator roles { name } userType memberId storeId // PT-1654: Fix Authentication public async Task CheckAuthAsync(IResolveFieldContext context, object resource, string permission = null, bool checkPasswordExpired = true) { - var userId = context.GetCurrentUserId(); + var principal = context.GetCurrentPrincipal(); + var userId = principal.GetCurrentUserId(); + var isExternalSignIn = principal.IsExternalSignIn(); var signInManager = _signInManagerFactory(); try @@ -767,11 +770,12 @@ public async Task CheckAuthAsync(IResolveFieldContext context, object resource, UserName = Xapi.Core.ModuleConstants.AnonymousUser.UserName, }; - if (checkPasswordExpired && user.PasswordExpired) + if (checkPasswordExpired && user.PasswordExpired && !isExternalSignIn) { throw AuthorizationError.PasswordExpired(); } + // Why do we create a new principal??? var userPrincipal = await signInManager.CreateUserPrincipalAsync(user); if (!string.IsNullOrEmpty(permission) && PermissionRequired(user, resource)) From d873b5401e7b22e872aa49a6d5011bee98cc68fb Mon Sep 17 00:00:00 2001 From: artem-dudarev Date: Sat, 10 Aug 2024 01:57:27 +0200 Subject: [PATCH 5/5] Update dependencies --- .../VirtoCommerce.ProfileExperienceApiModule.Data.csproj | 4 ++-- .../module.manifest | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj index ac783a4c..388e5700 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj @@ -19,9 +19,9 @@ - + - + diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest index 53895e9b..6d0d0596 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest @@ -4,9 +4,9 @@ 3.813.0 - 3.848.0-alpha.12968-vcst-1431 + 3.848.0 - +