2

I'm trying to use multiple AuthenticationFilter attributes with the my web API controller so they get invoked one by one and stop when finally one of authenticates successfully (equivalent to logical OR).

[TokenAuthentication]
[DbAuthentication]
public class FooController : ApiController
{
    // actions
}

Both attributes derive from a common base class. This way I avoid repeating code and I can quickly add some new authentication if needed.

public abstract class AuthenticationBase : ActionFilterAttribute, IAuthenticationFilter
{
    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated) return Task.FromResult(0);

        var isValidRequest = VerifyRequest(context);
        if (!isValidRequest)
        {
            context.ErrorResult = new AuthenticationFailureResult(context.Request);
            return Task.FromResult(context.ErrorResult);
        }

        if (HttpContext.Current != null)
        {
            var identity = GetIdentity();
            var claims = GetClaims();
            identity.AddClaims(claims);

            HttpContext.Current.User = new ClaimsPrincipal(identity);
        }

        return Task.FromResult(0);
    }

    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        return Task.FromResult(0);
    }
}

public class TokenAuthentication : AuthenticationBase
{
    protected override GenericIdentity GetIdentity()
    {
           // auth type dependent impl
    }

    protected override bool VerifyRequest(HttpAuthenticationContext context)
    {
           // auth type dependent impl
    }
}

Problem is, that they are evaluated on the base of a logical AND - means, that if the first authentication fails, the second one is not invoked. More precisely the second attribute always directly jumps into the ChallengeAsync method without ever calling AuthenticateAsync. I tried to solve the problem according to the answer to this question, but since I'm using the ApiController I can't overwrite InvokeAuthorizationFilters... I'm kinda stuck here and need some directions on how to solve this. I'm still pretty new to the .NET MVC, so I'm not even sure if this approach is the right one.

Community
  • 1
  • 1
wodzu
  • 3,004
  • 3
  • 25
  • 41

0 Answers0