Auth: Always call prior handlers during Challenge

This commit is contained in:
Hao Kung 2016-09-21 11:20:41 -07:00
parent 22d2fe99c6
commit e12838e38f
2 changed files with 55 additions and 7 deletions

View File

@ -311,6 +311,11 @@ namespace Microsoft.AspNetCore.Authentication
return TaskCache.CompletedTask;
}
/// <summary>
/// Override this method to deal with a challenge that is forbidden.
/// </summary>
/// <param name="context"></param>
/// <returns>The returned boolean is ignored.</returns>
protected virtual Task<bool> HandleForbiddenAsync(ChallengeContext context)
{
Response.StatusCode = 403;
@ -323,7 +328,7 @@ namespace Microsoft.AspNetCore.Authentication
/// changing the 401 result to 302 of a login page or external sign-in location.)
/// </summary>
/// <param name="context"></param>
/// <returns>True if no other handlers should be called</returns>
/// <returns>The returned boolean is no longer used.</returns>
protected virtual Task<bool> HandleUnauthorizedAsync(ChallengeContext context)
{
Response.StatusCode = 401;
@ -333,7 +338,6 @@ namespace Microsoft.AspNetCore.Authentication
public async Task ChallengeAsync(ChallengeContext context)
{
ChallengeCalled = true;
var handled = false;
if (ShouldHandleScheme(context.AuthenticationScheme, Options.AutomaticChallenge))
{
switch (context.Behavior)
@ -347,18 +351,18 @@ namespace Microsoft.AspNetCore.Authentication
}
goto case ChallengeBehavior.Unauthorized;
case ChallengeBehavior.Unauthorized:
handled = await HandleUnauthorizedAsync(context);
await HandleUnauthorizedAsync(context);
Logger.AuthenticationSchemeChallenged(Options.AuthenticationScheme);
break;
case ChallengeBehavior.Forbidden:
handled = await HandleForbiddenAsync(context);
await HandleForbiddenAsync(context);
Logger.AuthenticationSchemeForbidden(Options.AuthenticationScheme);
break;
}
context.Accept();
}
if (!handled && PriorHandler != null)
if (PriorHandler != null)
{
await PriorHandler.ChallengeAsync(context);
}

View File

@ -75,6 +75,49 @@ namespace Microsoft.AspNetCore.Authentication
Assert.Equal(1, handler.AuthCount);
}
// Prior to https://github.com/aspnet/Security/issues/930 we wouldn't call prior if handled
[Fact]
public async Task AuthHandlerChallengeAlwaysCallsPriorHandler()
{
var handler = await TestHandler.Create("Alpha");
var previous = new PreviousHandler();
handler.PriorHandler = previous;
await handler.ChallengeAsync(new ChallengeContext("Alpha"));
Assert.True(previous.ChallengeCalled);
}
private class PreviousHandler : IAuthenticationHandler
{
public bool ChallengeCalled = false;
public Task AuthenticateAsync(AuthenticateContext context)
{
throw new NotImplementedException();
}
public Task ChallengeAsync(ChallengeContext context)
{
ChallengeCalled = true;
return Task.FromResult(0);
}
public void GetDescriptions(DescribeSchemesContext context)
{
throw new NotImplementedException();
}
public Task SignInAsync(SignInContext context)
{
throw new NotImplementedException();
}
public Task SignOutAsync(SignOutContext context)
{
throw new NotImplementedException();
}
}
private class CountOptions : AuthenticationOptions { }
private class CountHandler : AuthenticationHandler<CountOptions>
@ -109,6 +152,8 @@ namespace Microsoft.AspNetCore.Authentication
{
private TestHandler() { }
public AuthenticateResult Result = AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), "whatever"));
public static async Task<TestHandler> Create(string scheme)
{
var handler = new TestHandler();
@ -124,7 +169,7 @@ namespace Microsoft.AspNetCore.Authentication
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), "whatever")));
return Task.FromResult(Result);
}
}
@ -220,7 +265,6 @@ namespace Microsoft.AspNetCore.Authentication
set
{
throw new NotImplementedException();
}
}