Skip to content

Commit 026e80e

Browse files
authored
Avoid an exception on sign out when the principal is populated from an incomplete external login (#18078)
* Avoid an exception on signout when the principal is populated from an incomplete external login. * Tidied up comment.
1 parent a3b77cf commit 026e80e

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,20 @@ public override Task<IdentityResult> DeleteAsync(
281281
cancellationToken.ThrowIfCancellationRequested();
282282
ThrowIfDisposed();
283283

284-
IUser? user = _userService.GetUserById(UserIdToInt(userId));
284+
// In the external login flow - see BackOfficeController.ExternalSignInAsync - we can have a situation where an
285+
// error has occured but the user is signed in. For that reason, at the end of the process, if errors are
286+
// recorded, the user is signed out.
287+
// Before signing out, we request the user in order to update the security stamp - see UmbracoSignInManager.SignOutAsync.
288+
// But we can have a situation where the signed in principal has the ID from the external provider, which may not be something
289+
// we can parse to an integer.
290+
// If that's the case, return null rather than throwing an exception. Without an Umbraco user, we can't update the security stamp,
291+
// so no need to fail here.
292+
if (!TryUserIdToInt(userId, out var userIdAsInt))
293+
{
294+
return Task.FromResult((BackOfficeIdentityUser?)null)!;
295+
}
296+
297+
IUser? user = _userService.GetUserById(userIdAsInt);
285298
if (user == null)
286299
{
287300
return Task.FromResult((BackOfficeIdentityUser?)null)!;

src/Umbraco.Infrastructure/Security/UmbracoUserStore.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,29 @@ protected UmbracoUserStore(IdentityErrorDescriber describer)
3333

3434
protected static int UserIdToInt(string? userId)
3535
{
36-
if (int.TryParse(userId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
36+
if (TryUserIdToInt(userId, out int result))
3737
{
3838
return result;
3939
}
4040

41+
throw new InvalidOperationException($"Unable to convert user ID ({userId})to int using InvariantCulture");
42+
}
43+
44+
protected static bool TryUserIdToInt(string? userId, out int result)
45+
{
46+
if (int.TryParse(userId, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
47+
{
48+
return true;
49+
}
50+
4151
if (Guid.TryParse(userId, out Guid key))
4252
{
4353
// Reverse the IntExtensions.ToGuid
44-
return BitConverter.ToInt32(key.ToByteArray(), 0);
54+
result = BitConverter.ToInt32(key.ToByteArray(), 0);
55+
return true;
4556
}
4657

47-
throw new InvalidOperationException($"Unable to convert user ID ({userId})to int using InvariantCulture");
58+
return false;
4859
}
4960

5061
protected static string UserIdToString(int userId) => string.Intern(userId.ToString(CultureInfo.InvariantCulture));

0 commit comments

Comments
 (0)