Skip to content

Commit f9e06d6

Browse files
committed
Restore HttpRequestContext.Principal after executing inner message handlers
- #119 nits: use `var` more in affected tests
1 parent 986889d commit f9e06d6

File tree

4 files changed

+85
-35
lines changed

4 files changed

+85
-35
lines changed

src/System.Web.Http.Owin/PassiveAuthenticationMessageHandler.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
using System.Threading.Tasks;
1010
using System.Web.Http.Controllers;
1111
using System.Web.Http.Filters;
12-
using System.Web.Http.Hosting;
1312
using System.Web.Http.Owin.Properties;
14-
using Microsoft.Owin;
1513
using Microsoft.Owin.Security;
1614

1715
namespace System.Web.Http.Owin
@@ -37,27 +35,36 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
3735
throw new ArgumentNullException("request");
3836
}
3937

40-
SetCurrentPrincipalToAnonymous(request);
41-
42-
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
38+
HttpResponseMessage response;
39+
var previousPrincipal = SetCurrentPrincipal(request, _anonymousPrincipal.Value);
40+
try
41+
{
42+
response = await base.SendAsync(request, cancellationToken);
43+
}
44+
finally
45+
{
46+
SetCurrentPrincipal(request, previousPrincipal);
47+
}
4348

4449
SuppressDefaultAuthenticationChallenges(request);
4550

4651
return response;
4752
}
4853

49-
private static void SetCurrentPrincipalToAnonymous(HttpRequestMessage request)
54+
private static IPrincipal SetCurrentPrincipal(HttpRequestMessage request, IPrincipal principal)
5055
{
5156
Contract.Assert(request != null);
5257

5358
HttpRequestContext requestContext = request.GetRequestContext();
54-
5559
if (requestContext == null)
5660
{
5761
throw new ArgumentException(OwinResources.Request_RequestContextMustNotBeNull, "request");
5862
}
5963

60-
requestContext.Principal = _anonymousPrincipal.Value;
64+
var previousPrincipal = requestContext.Principal;
65+
requestContext.Principal = principal;
66+
67+
return previousPrincipal;
6168
}
6269

6370
private static void SuppressDefaultAuthenticationChallenges(HttpRequestMessage request)

src/System.Web.Http/Hosting/SuppressHostPrincipalMessageHandler.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,39 @@ public class SuppressHostPrincipalMessageHandler : DelegatingHandler
2525
() => new ClaimsPrincipal(new ClaimsIdentity()), isThreadSafe: true);
2626

2727
/// <inheritdoc />
28-
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
28+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
2929
CancellationToken cancellationToken)
3030
{
3131
if (request == null)
3232
{
3333
throw new ArgumentNullException("request");
3434
}
3535

36-
SetCurrentPrincipalToAnonymous(request);
37-
38-
return base.SendAsync(request, cancellationToken);
36+
var previousPrincipal = SetCurrentPrincipal(request, _anonymousPrincipal.Value);
37+
try
38+
{
39+
return await base.SendAsync(request, cancellationToken);
40+
}
41+
finally
42+
{
43+
SetCurrentPrincipal(request, previousPrincipal);
44+
}
3945
}
4046

41-
private static void SetCurrentPrincipalToAnonymous(HttpRequestMessage request)
47+
private static IPrincipal SetCurrentPrincipal(HttpRequestMessage request, IPrincipal principal)
4248
{
4349
Contract.Assert(request != null);
4450

4551
HttpRequestContext requestContext = request.GetRequestContext();
46-
4752
if (requestContext == null)
4853
{
4954
throw new ArgumentException(SRResources.Request_RequestContextMustNotBeNull, "request");
5055
}
5156

52-
requestContext.Principal = _anonymousPrincipal.Value;
57+
var previousPrincipal = requestContext.Principal;
58+
requestContext.Principal = principal;
59+
60+
return previousPrincipal;
5361
}
5462
}
5563
}

test/System.Web.Http.Owin.Test/PassiveAuthenticationMessageHandlerTest.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,50 @@ public async Task SendAsync_Throws_WhenAuthenticationManagerIsNull()
104104
public async Task SendAsync_SetsRequestContextPrincipalToAnonymous_BeforeCallingInnerHandler()
105105
{
106106
// Arrange
107+
var requestContextMock = new Mock<HttpRequestContext>(MockBehavior.Strict);
108+
var sequence = new MockSequence();
109+
var initialPrincipal = new GenericPrincipal(new GenericIdentity("generic user"), new[] { "generic role" });
107110
IPrincipal requestContextPrincipal = null;
108-
Mock<HttpRequestContext> requestContextMock = new Mock<HttpRequestContext>(MockBehavior.Strict);
109111
requestContextMock
112+
.InSequence(sequence)
113+
.SetupGet(c => c.Principal)
114+
.Returns(initialPrincipal);
115+
requestContextMock
116+
.InSequence(sequence)
110117
.SetupSet(c => c.Principal = It.IsAny<IPrincipal>())
111-
.Callback<IPrincipal>((value) => requestContextPrincipal = value);
118+
.Callback<IPrincipal>(value => requestContextPrincipal = value);
119+
120+
// SendAsync also restores the old principal.
121+
requestContextMock
122+
.InSequence(sequence)
123+
.SetupGet(c => c.Principal)
124+
.Returns(requestContextPrincipal);
125+
requestContextMock
126+
.InSequence(sequence)
127+
.SetupSet(c => c.Principal = initialPrincipal);
128+
112129
IPrincipal principalBeforeInnerHandler = null;
113130
HttpMessageHandler inner = new LambdaHttpMessageHandler((ignore1, ignore2) =>
114131
{
115132
principalBeforeInnerHandler = requestContextPrincipal;
116133
return Task.FromResult<HttpResponseMessage>(null);
117134
});
118135
HttpMessageHandler handler = CreateProductUnderTest(inner);
119-
IOwinContext context = CreateOwinContext();
136+
var context = CreateOwinContext();
120137

121-
using (HttpRequestMessage request = new HttpRequestMessage())
138+
using (var request = new HttpRequestMessage())
122139
{
123140
request.SetOwinContext(context);
124141
request.SetRequestContext(requestContextMock.Object);
125142

126143
// Act
127-
HttpResponseMessage ignore = await handler.SendAsync(request, CancellationToken.None);
144+
await handler.SendAsync(request, CancellationToken.None);
128145
}
129146

130147
// Assert
148+
Assert.Equal(requestContextPrincipal, principalBeforeInnerHandler);
131149
Assert.NotNull(principalBeforeInnerHandler);
132-
IIdentity identity = principalBeforeInnerHandler.Identity;
150+
var identity = principalBeforeInnerHandler.Identity;
133151
Assert.NotNull(identity);
134152
Assert.False(identity.IsAuthenticated);
135153
Assert.Null(identity.Name);

test/System.Web.Http.Test/Hosting/SuppressHostPrincipalMessageHandlerTest.cs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,29 @@ namespace System.Web.Http.Hosting
1414
public class SuppressHostPrincipalMessageHandlerTest
1515
{
1616
[Fact]
17-
public void SendAsync_DelegatesToInnerHandler()
17+
public async Task SendAsync_DelegatesToInnerHandler()
1818
{
1919
// Arrange
2020
HttpRequestMessage request = null;
21-
CancellationToken cancellationToken = default(CancellationToken);
22-
Task<HttpResponseMessage> expectedResult = new Task<HttpResponseMessage>(() => null);
21+
var cancellationToken = default(CancellationToken);
2322
HttpMessageHandler innerHandler = new LambdaHttpMessageHandler((r, c) =>
2423
{
2524
request = r;
2625
cancellationToken = c;
27-
return expectedResult;
26+
return Task.FromResult<HttpResponseMessage>(null);
2827
});
2928
HttpMessageHandler handler = CreateProductUnderTest(innerHandler);
30-
CancellationToken expectedCancellationToken = new CancellationToken(true);
29+
var expectedCancellationToken = new CancellationToken(true);
3130

32-
using (HttpRequestMessage expectedRequest = CreateRequestWithContext())
31+
using (var expectedRequest = CreateRequestWithContext())
3332
{
3433
// Act
35-
Task<HttpResponseMessage> result = handler.SendAsync(expectedRequest, expectedCancellationToken);
34+
var result = await handler.SendAsync(expectedRequest, expectedCancellationToken);
3635

3736
// Assert
3837
Assert.Same(expectedRequest, request);
3938
Assert.Equal(expectedCancellationToken, cancellationToken);
40-
Assert.Same(expectedResult, result);
39+
Assert.Null(result);
4140
}
4241
}
4342

@@ -59,14 +58,31 @@ await Assert.ThrowsArgumentAsync(
5958
}
6059

6160
[Fact]
62-
public void SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler()
61+
public async Task SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler()
6362
{
6463
// Arrange
64+
var requestContextMock = new Mock<HttpRequestContext>(MockBehavior.Strict);
65+
var sequence = new MockSequence();
66+
var initialPrincipal = new GenericPrincipal(new GenericIdentity("generic user"), new[] { "generic role" });
6567
IPrincipal requestContextPrincipal = null;
66-
Mock<HttpRequestContext> requestContextMock = new Mock<HttpRequestContext>();
6768
requestContextMock
69+
.InSequence(sequence)
70+
.SetupGet(c => c.Principal)
71+
.Returns(initialPrincipal);
72+
requestContextMock
73+
.InSequence(sequence)
6874
.SetupSet(c => c.Principal = It.IsAny<IPrincipal>())
69-
.Callback<IPrincipal>((value) => requestContextPrincipal = value);
75+
.Callback<IPrincipal>(value => requestContextPrincipal = value);
76+
77+
// SendAsync also restores the old principal.
78+
requestContextMock
79+
.InSequence(sequence)
80+
.SetupGet(c => c.Principal)
81+
.Returns(requestContextPrincipal);
82+
requestContextMock
83+
.InSequence(sequence)
84+
.SetupSet(c => c.Principal = initialPrincipal);
85+
7086
IPrincipal principalBeforeInnerHandler = null;
7187
HttpMessageHandler inner = new LambdaHttpMessageHandler((ignore1, ignore2) =>
7288
{
@@ -75,17 +91,18 @@ public void SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler(
7591
});
7692
HttpMessageHandler handler = CreateProductUnderTest(inner);
7793

78-
using (HttpRequestMessage request = new HttpRequestMessage())
94+
using (var request = new HttpRequestMessage())
7995
{
8096
request.SetRequestContext(requestContextMock.Object);
8197

8298
// Act
83-
handler.SendAsync(request, CancellationToken.None);
99+
await handler.SendAsync(request, CancellationToken.None);
84100
}
85101

86102
// Assert
103+
Assert.Equal(requestContextPrincipal, principalBeforeInnerHandler);
87104
Assert.NotNull(principalBeforeInnerHandler);
88-
IIdentity identity = principalBeforeInnerHandler.Identity;
105+
var identity = principalBeforeInnerHandler.Identity;
89106
Assert.NotNull(identity);
90107
Assert.False(identity.IsAuthenticated);
91108
Assert.Null(identity.Name);

0 commit comments

Comments
 (0)