Skip to content

Commit ca5c85e

Browse files
author
Paul Johnson
authored
v9 fix misc issues external member login (#12093)
* Add missing override for SetTokenAsync * Fix mismatch between expected scheme prefix and exception message * Store tokens on member update
1 parent 44e8808 commit ca5c85e

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/Umbraco.Infrastructure/Security/MemberUserStore.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public override Task<IdentityResult> UpdateAsync(MemberIdentityUser user, Cancel
181181
{
182182
// we have to remember whether Logins property is dirty, since the UpdateMemberProperties will reset it.
183183
var isLoginsPropertyDirty = user.IsPropertyDirty(nameof(MemberIdentityUser.Logins));
184+
var isTokensPropertyDirty = user.IsPropertyDirty(nameof(MemberIdentityUser.LoginTokens));
184185

185186
MemberDataChangeType memberChangeType = UpdateMemberProperties(found, user);
186187
if (memberChangeType == MemberDataChangeType.FullSave)
@@ -203,6 +204,16 @@ public override Task<IdentityResult> UpdateAsync(MemberIdentityUser user, Cancel
203204
x.ProviderKey,
204205
x.UserData)));
205206
}
207+
208+
if (isTokensPropertyDirty)
209+
{
210+
_externalLoginService.Save(
211+
found.Key,
212+
user.LoginTokens.Select(x => new ExternalLoginToken(
213+
x.LoginProvider,
214+
x.Name,
215+
x.Value)));
216+
}
206217
}
207218

208219
return Task.FromResult(IdentityResult.Success);
@@ -535,6 +546,37 @@ protected override async Task<IdentityUserRole<string>> FindUserRoleAsync(string
535546
return found;
536547
}
537548

549+
/// <summary>
550+
/// Overridden to support Umbraco's own data storage requirements
551+
/// </summary>
552+
/// <remarks>
553+
/// The base class's implementation of this calls into FindTokenAsync and AddUserTokenAsync, both methods will only work with ORMs that are change
554+
/// tracking ORMs like EFCore.
555+
/// </remarks>
556+
/// <inheritdoc />
557+
public override Task SetTokenAsync(MemberIdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
558+
{
559+
cancellationToken.ThrowIfCancellationRequested();
560+
ThrowIfDisposed();
561+
562+
if (user == null)
563+
{
564+
throw new ArgumentNullException(nameof(user));
565+
}
566+
567+
IIdentityUserToken token = user.LoginTokens.FirstOrDefault(x => x.LoginProvider.InvariantEquals(loginProvider) && x.Name.InvariantEquals(name));
568+
if (token == null)
569+
{
570+
user.LoginTokens.Add(new IdentityUserToken(loginProvider, name, value, user.Id));
571+
}
572+
else
573+
{
574+
token.Value = value;
575+
}
576+
577+
return Task.CompletedTask;
578+
}
579+
538580
private MemberIdentityUser AssignLoginsCallback(MemberIdentityUser user)
539581
{
540582
if (user != null)

src/Umbraco.Web.Website/Security/MemberAuthenticationBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public override AuthenticationBuilder AddRemoteScheme<TOptions, THandler>(string
4141
// Validate that the prefix is set
4242
if (!authenticationScheme.StartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix))
4343
{
44-
throw new InvalidOperationException($"The {nameof(authenticationScheme)} is not prefixed with {Constants.Security.BackOfficeExternalAuthenticationTypePrefix}. The scheme must be created with a call to the method {nameof(SchemeForMembers)}");
44+
throw new InvalidOperationException($"The {nameof(authenticationScheme)} is not prefixed with {Constants.Security.MemberExternalAuthenticationTypePrefix}. The scheme must be created with a call to the method {nameof(SchemeForMembers)}");
4545
}
4646

4747
// add our login provider to the container along with a custom options configuration

0 commit comments

Comments
 (0)