Skip to content

Commit c98fdef

Browse files
authored
Merge pull request #60878 from dotnet/wtgodbe/MergeInt23
[release/2.3] Merge from internal
2 parents e1b8a6d + 9984746 commit c98fdef

File tree

3 files changed

+79
-14
lines changed

3 files changed

+79
-14
lines changed

eng/PatchConfig.props

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Later on, this will be checked using this condition:
1515

1616
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.3.1' ">
1717
<PackagesInPatch>
18+
Microsoft.AspNetCore.Identity;
1819
</PackagesInPatch>
1920
</PropertyGroup>
2021
</Project>

src/Identity/Core/src/SignInManager.cs

+13
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,19 @@ public virtual async Task<bool> CanSignInAsync(TUser user)
162162
public virtual async Task RefreshSignInAsync(TUser user)
163163
{
164164
var auth = await Context.AuthenticateAsync(IdentityConstants.ApplicationScheme);
165+
if (!auth.Succeeded || auth.Principal?.Identity?.IsAuthenticated != true)
166+
{
167+
Logger.LogError("RefreshSignInAsync prevented because the user is not currently authenticated. Use SignInAsync instead for initial sign in.");
168+
return;
169+
}
170+
var authenticatedUserId = UserManager.GetUserId(auth.Principal);
171+
var newUserId = await UserManager.GetUserIdAsync(user);
172+
if (authenticatedUserId == null || authenticatedUserId != newUserId)
173+
{
174+
Logger.LogError("RefreshSignInAsync prevented because currently authenticated user has a different UserId. Use SignInAsync instead to change users.");
175+
return;
176+
}
177+
165178
var authenticationMethod = auth?.Principal?.FindFirstValue(ClaimTypes.AuthenticationMethod);
166179
await SignInAsync(user, auth?.Properties, authenticationMethod);
167180
}

src/Identity/test/Identity.Test/SignInManagerTest.cs

+65-14
Original file line numberDiff line numberDiff line change
@@ -548,38 +548,37 @@ public async Task CanExternalSignIn(bool isPersistent, bool supportsLockout)
548548
[InlineData(true, false)]
549549
[InlineData(false, true)]
550550
[InlineData(false, false)]
551-
public async Task CanResignIn(
552-
// Suppress warning that says theory methods should use all of their parameters.
553-
// See comments below about why this isn't used.
554-
#pragma warning disable xUnit1026
555-
bool isPersistent,
556-
#pragma warning restore xUnit1026
557-
bool externalLogin)
551+
public async Task CanResignIn(bool isPersistent, bool externalLogin)
558552
{
559553
// Setup
560554
var user = new PocoUser { UserName = "Foo" };
561555
var context = new DefaultHttpContext();
562556
var auth = MockAuth(context);
563557
var loginProvider = "loginprovider";
564-
var id = new ClaimsIdentity();
558+
var id = new ClaimsIdentity("authscheme");
565559
if (externalLogin)
566560
{
567561
id.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider));
568562
}
569-
// REVIEW: auth changes we lost the ability to mock is persistent
570-
//var properties = new AuthenticationProperties { IsPersistent = isPersistent };
571-
var authResult = AuthenticateResult.NoResult();
563+
564+
var claimsPrincipal = new ClaimsPrincipal(id);
565+
var properties = new AuthenticationProperties { IsPersistent = isPersistent };
566+
var authResult = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, properties, "authscheme"));
572567
auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
573568
.Returns(Task.FromResult(authResult)).Verifiable();
574569
var manager = SetupUserManager(user);
570+
manager.Setup(m => m.GetUserId(claimsPrincipal)).Returns(user.Id.ToString());
575571
var signInManager = new Mock<SignInManager<PocoUser>>(manager.Object,
576572
new HttpContextAccessor { HttpContext = context },
577573
new Mock<IUserClaimsPrincipalFactory<PocoUser>>().Object,
578574
null, null, new Mock<IAuthenticationSchemeProvider>().Object)
579575
{ CallBase = true };
580-
//signInManager.Setup(s => s.SignInAsync(user, It.Is<AuthenticationProperties>(p => p.IsPersistent == isPersistent),
581-
//externalLogin? loginProvider : null)).Returns(Task.FromResult(0)).Verifiable();
582-
signInManager.Setup(s => s.SignInAsync(user, It.IsAny<AuthenticationProperties>(), null)).Returns(Task.FromResult(0)).Verifiable();
576+
577+
signInManager.Setup(s => s.SignInAsync(user,
578+
It.Is<AuthenticationProperties>(p => p.IsPersistent == isPersistent),
579+
externalLogin ? loginProvider : null))
580+
.Returns(Task.FromResult(0)).Verifiable();
581+
583582
signInManager.Object.Context = context;
584583

585584
// Act
@@ -590,6 +589,58 @@ public async Task CanResignIn(
590589
signInManager.Verify();
591590
}
592591

592+
[Fact]
593+
public async Task ResignInNoOpsAndLogsErrorIfNotAuthenticated()
594+
{
595+
var user = new PocoUser { UserName = "Foo" };
596+
var context = new DefaultHttpContext();
597+
var auth = MockAuth(context);
598+
var manager = SetupUserManager(user);
599+
var logger = new TestLogger<SignInManager<PocoUser>>();
600+
var signInManager = new Mock<SignInManager<PocoUser>>(manager.Object,
601+
new HttpContextAccessor { HttpContext = context },
602+
new Mock<IUserClaimsPrincipalFactory<PocoUser>>().Object,
603+
null, logger, new Mock<IAuthenticationSchemeProvider>().Object)
604+
{ CallBase = true };
605+
auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
606+
.Returns(Task.FromResult(AuthenticateResult.NoResult())).Verifiable();
607+
608+
await signInManager.Object.RefreshSignInAsync(user);
609+
610+
Assert.Contains("RefreshSignInAsync prevented because the user is not currently authenticated. Use SignInAsync instead for initial sign in.", logger.LogMessages);
611+
auth.Verify();
612+
signInManager.Verify(s => s.SignInAsync(It.IsAny<PocoUser>(), It.IsAny<AuthenticationProperties>(), It.IsAny<string>()),
613+
Times.Never());
614+
}
615+
616+
[Fact]
617+
public async Task ResignInNoOpsAndLogsErrorIfAuthenticatedWithDifferentUser()
618+
{
619+
var user = new PocoUser { UserName = "Foo" };
620+
var context = new DefaultHttpContext();
621+
var auth = MockAuth(context);
622+
var manager = SetupUserManager(user);
623+
var logger = new TestLogger<SignInManager<PocoUser>>();
624+
var signInManager = new Mock<SignInManager<PocoUser>>(manager.Object,
625+
new HttpContextAccessor { HttpContext = context },
626+
new Mock<IUserClaimsPrincipalFactory<PocoUser>>().Object,
627+
null, logger, new Mock<IAuthenticationSchemeProvider>().Object)
628+
{ CallBase = true };
629+
var id = new ClaimsIdentity("authscheme");
630+
var claimsPrincipal = new ClaimsPrincipal(id);
631+
var authResult = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, new AuthenticationProperties(), "authscheme"));
632+
auth.Setup(a => a.AuthenticateAsync(context, IdentityConstants.ApplicationScheme))
633+
.Returns(Task.FromResult(authResult)).Verifiable();
634+
manager.Setup(m => m.GetUserId(claimsPrincipal)).Returns("different");
635+
636+
await signInManager.Object.RefreshSignInAsync(user);
637+
638+
Assert.Contains("RefreshSignInAsync prevented because currently authenticated user has a different UserId. Use SignInAsync instead to change users.", logger.LogMessages);
639+
auth.Verify();
640+
signInManager.Verify(s => s.SignInAsync(It.IsAny<PocoUser>(), It.IsAny<AuthenticationProperties>(), It.IsAny<string>()),
641+
Times.Never());
642+
}
643+
593644
[Theory]
594645
[InlineData(true, true, true, true)]
595646
[InlineData(true, true, false, true)]

0 commit comments

Comments
 (0)