Skip to content

Commit 21b7f21

Browse files
authored
Use existing principal for single scheme (#37135)
1 parent b05ed6d commit 21b7f21

File tree

2 files changed

+39
-28
lines changed

2 files changed

+39
-28
lines changed

src/Security/Authorization/test/PolicyEvaluatorTests.cs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,26 @@ public async Task AuthenticateMergeSchemes()
5151
Assert.Equal(3, result.Principal.Identities.Count());
5252
}
5353

54+
[Fact]
55+
public async Task AuthenticateMergeSchemesPreservesSingleScheme()
56+
{
57+
// Arrange
58+
var evaluator = BuildEvaluator();
59+
var context = new DefaultHttpContext();
60+
var auth = new EchoAuthentication();
61+
var services = new ServiceCollection().AddSingleton<IAuthenticationService>(auth);
62+
context.RequestServices = services.BuildServiceProvider();
63+
var policy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes("A").RequireAssertion(_ => true).Build();
64+
65+
// Act
66+
var result = await evaluator.AuthenticateAsync(policy, context);
67+
68+
// Assert
69+
Assert.True(result.Succeeded);
70+
Assert.Single(result.Principal.Identities);
71+
Assert.Equal(auth.Principal, result.Principal);
72+
}
73+
5474

5575
[Fact]
5676
public async Task AuthorizeSucceedsEvenIfAuthenticationFails()
@@ -174,57 +194,42 @@ public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object res
174194
public class SadAuthentication : IAuthenticationService
175195
{
176196
public Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
177-
{
178-
return Task.FromResult(AuthenticateResult.Fail("Sad."));
179-
}
197+
=> Task.FromResult(AuthenticateResult.Fail("Sad."));
180198

181199
public Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
182-
{
183-
throw new System.NotImplementedException();
184-
}
200+
=> throw new NotImplementedException();
185201

186202
public Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
187-
{
188-
throw new System.NotImplementedException();
189-
}
203+
=> throw new NotImplementedException();
190204

191205
public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
192-
{
193-
throw new System.NotImplementedException();
194-
}
206+
=> throw new NotImplementedException();
195207

196208
public Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
197-
{
198-
throw new System.NotImplementedException();
199-
}
209+
=> throw new NotImplementedException();
200210
}
201211

202212
public class EchoAuthentication : IAuthenticationService
203213
{
214+
public ClaimsPrincipal Principal;
215+
204216
public Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
205217
{
206-
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(new ClaimsIdentity(scheme)), scheme)));
218+
Principal = new ClaimsPrincipal(new ClaimsIdentity(scheme));
219+
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Principal, scheme)));
207220
}
208221

209222
public Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
210-
{
211-
throw new System.NotImplementedException();
212-
}
223+
=> throw new NotImplementedException();
213224

214225
public Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
215-
{
216-
throw new System.NotImplementedException();
217-
}
226+
=> throw new NotImplementedException();
218227

219228
public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
220-
{
221-
throw new System.NotImplementedException();
222-
}
229+
=> throw new NotImplementedException();
223230

224231
public Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
225-
{
226-
throw new System.NotImplementedException();
227-
}
232+
=> throw new NotImplementedException();
228233
}
229234

230235
private class DummyRequirement : IAuthorizationRequirement {}

src/Shared/SecurityHelper/SecurityHelper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ internal static class SecurityHelper
2222
/// <param name="additionalPrincipal">The <see cref="ClaimsPrincipal"/> containing <see cref="ClaimsIdentity"/> to be added.</param>
2323
public static ClaimsPrincipal MergeUserPrincipal(ClaimsPrincipal? existingPrincipal, ClaimsPrincipal? additionalPrincipal)
2424
{
25+
// For the first principal, just use the new principal rather than copying it
26+
if (existingPrincipal == null && additionalPrincipal != null)
27+
{
28+
return additionalPrincipal;
29+
}
30+
2531
var newPrincipal = new ClaimsPrincipal();
2632

2733
// New principal identities go first

0 commit comments

Comments
 (0)