Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
eede42a
Fix PasskeySignInAsync to return SignInResult.Failed for expired sess…
GrantTotinov Jul 1, 2026
6f8843f
Potential fix for pull request finding
GrantTotinov Jul 1, 2026
ba63855
Apply Copilot suggestions: add .Verifiable() and verify handler not c…
GrantTotinov Jul 1, 2026
fdec8f0
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 1, 2026
ddec2c7
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 2, 2026
9d6741c
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 12, 2026
ad0d0fd
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 14, 2026
245d308
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 15, 2026
c683309
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 19, 2026
1eb52f4
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 20, 2026
a8e1c68
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 22, 2026
4ab7a8a
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 24, 2026
8ff4eab
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Jul 29, 2026
4ab05a5
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Aug 3, 2026
964997f
Merge branch 'main' into fix-passkey-signin-expired-session
GrantTotinov Aug 13, 2026
50375ae
Update src/Identity/Core/src/SignInManager.cs
halter73 Aug 19, 2026
f6fc452
Apply batched suggestions from code review
halter73 Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Identity/Core/src/SignInManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,18 @@ private async Task<SignInResult> PasskeySignInCoreAsync(string credentialJson)
{
ArgumentException.ThrowIfNullOrEmpty(credentialJson);

var passkeyInfo = await RetrievePasskeyAuthenticationInfoAsync();
Comment thread
halter73 marked this conversation as resolved.
Outdated
if (passkeyInfo is null)
{
return SignInResult.Failed;
}
Comment thread
GrantTotinov marked this conversation as resolved.
Comment thread
halter73 marked this conversation as resolved.
if (!string.Equals(PasskeyOperations.Assertion, passkeyInfo.Operation, StringComparison.Ordinal))
{
throw new InvalidOperationException(
$"Expected passkey operation '{PasskeyOperations.Assertion}', but got '{passkeyInfo.Operation}'. " +
$"This may indicate that you have not previously called '{nameof(SignInManager<>)}.{nameof(MakePasskeyRequestOptionsAsync)}()'.");
}

var assertionResult = await PerformPasskeyAssertionAsync(credentialJson);
if (!assertionResult.Succeeded)
{
Expand Down
30 changes: 30 additions & 0 deletions src/Identity/test/Identity.Test/SignInManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,36 @@ public async Task PasskeySignInReturnsLockedOutWhenLockedOut()
auth.Verify();
}

[Fact]
public async Task PasskeySignInReturnsFailedWhenSessionChallengeHasExpired()
{
// Setup
var user = new PocoUser { UserName = "Foo" };
var passkeyHandler = new Mock<IPasskeyHandler<PocoUser>>();
var manager = SetupUserManager(user, passkeyHandler: passkeyHandler.Object);
var context = new DefaultHttpContext();
var auth = MockAuth(context);

// Do NOT call SetupPasskeyAuth — simulates expired/missing session
auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.TwoFactorUserIdScheme))
.ReturnsAsync(AuthenticateResult.Fail("Session expired."))
.Verifiable();
auth.Setup(a => a.SignOutAsync(context, IdentityConstants.TwoFactorUserIdScheme, It.IsAny<AuthenticationProperties>()))
.Returns(Task.CompletedTask)
.Verifiable();

var helper = SetupSignInManager(manager.Object, context);

// Act
var signInResult = await helper.PasskeySignInAsync(credentialJson: "<some-passkey>");

// Assert
Assert.False(signInResult.Succeeded);
Assert.Same(SignInResult.Failed, signInResult);
passkeyHandler.Verify(h => h.PerformAssertionAsync(It.IsAny<PasskeyAssertionContext>()), Times.Never);
auth.Verify();
Comment thread
GrantTotinov marked this conversation as resolved.
}

private static void SetupPasskeyAuth(HttpContext context, Mock<IAuthenticationService> auth)
{
// Calling AuthenticateAsync will return a failure result
Expand Down
Loading