Reputation: 575
I am trying to have my own custom authentication for my server. But it is called for every endpoint even if it has the [AllowAnonymous] attribute on the method. With my current code, I can hit my breakpoint in the HandleAuthenticateAsync method everytime, even on the allow anonymous functions.
The AddCustomAuthentication adds the authenticationhandler correctly
public void ConfigureServices(IServiceCollection services)
{
//services.AddAuthorization();
services.AddAuthentication(options =>
{
// the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
options.DefaultAuthenticateScheme = "scheme";
options.DefaultChallengeScheme = "scheme";
})
.AddCustomAuthentication(o => { });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
...
public class CustomAuthenticationHandler : AuthenticationHandler<CustomAuthenticationOptions>
{
public RvxAuthenticationHandler(
IOptionsMonitor<RvxAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var token = Request.Headers["token"].ToString();
if (string.IsNullOrWhiteSpace(token))
{
return AuthenticateResult.Fail("Invalid Credentials");
}
return AuthenticateResult.Success(new AuthenticationTicket(new System.Security.Claims.ClaimsPrincipal(), "Hi"));
}
Upvotes: 19
Views: 6347
Reputation: 11
I guess Your problem is different, After exiting from the HandleAuthenticateAsync method it can not find the endpoint:
Upvotes: 0
Reputation: 1856
Add this to the top of your HandleAuthenticateAsync
method
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var endpoint = Context.GetEndpoint();
if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
{
return Task.FromResult(AuthenticateResult.NoResult());
}
....
}
This is what Microsoft use under the covers in the AuthorizeFiler
- https://github.com/dotnet/aspnetcore/blob/bd65275148abc9b07a3b59797a88d485341152bf/src/Mvc/Mvc.Core/src/Authorization/AuthorizeFilter.cs#L236
It will allow you to use the AllowAnonymous
attribute in controllers to bypass your custom AuthenticationHandler
.
Upvotes: 25
Reputation: 1480
This is how it is designed to work.
Authentication step is executed for every incoming call by the ASP.Net middleware added by your app.UseAuthentication()
call. The step only sets up an instance of IPrincipal
to the request.
If authentication succeeds, the request gets the IPrincipal
that you pass to the AuthenticationTicket
.
If it fails, the request gets an unauthenticated IIdentity
in its IPrincipal
(principal.Identity.IsAuthenticated
will be false
)
Then the request will still be passed to the next middleware and eventually to your endpoint method.
It's the AuthorizeAttribute
that will prevent the request from reaching protected methods, not any AuthenticationHandler<T>
.
Upvotes: 11