Avoid an exception on sign out when the principal is populated from an incomplete external login #18078
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Prerequisites
Potentially fixes: #18002
Description
This one has proved tricky as I've not been able to reproduce - but I've seen two people who can, so it's a real issue. I can sort of see what's happening, and believe this will fix it, but it's difficult to fully get to the bottom of it without being able to reproduce the issue and verify the fix.
So I've mostly diagnosed by following the stack trace on the issue:
In
ExternalSignInAsync
, at the end of the method, if there has been an error, we callSignOutAsync
. This attempts to retrieve the current Umbraco user, in order to update the security stamp. It seems that in some cases - at least in the once who have been able to reproduce - the current principal at this point has an ID that's not the integer Umbraco ID, but the provider key from the external login provider.In the Google case, it's a long integer, so the previous
UserIdToInt
method would throw an exception. I've added a newTryUserIdToInt
instead, and where that fails returned a null user (the same as if we had a valid integer but no matching user in the database). That way the sign out method will just not update the security stamp - it can't anyway if it hasn't found an Umbraco user) - rather it will continue with the other sign out steps and return to the caller for the usual error handling of external logins.Presumably the real issue here is something else, which is why we have this "partially logged in" state. With this update, we would now see the errors as we wouldn't get this exception thrown on the sign out, so hopefully it'll reveal what's going on. Which may be something to do with the reproducer's environment, or maybe something else to resolve in Umbraco.
To Test:
TryUserIdToInt
method and see whatuserId
has arrived here. For me, it's always the Umbraco integer ID, but perhaps you'll see the long integer Google provider key, in which case you may be able to see what's actually going on to get in this situation.