After adding [Authorize]
to a controller, I'm always getting a 401 from it. While debugging, I see the return AuthenticateResult.Success
being reached, but the code of the controller never is.
What am I doing wrong?
Below is the code for my Startup class and Custom auth classes.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials());
});
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Custom Scheme";
options.DefaultChallengeScheme = "Custom Scheme";
}).AddCustomAuth(o => { });
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("CorsPolicy");
var options = new RewriteOptions().AddRedirectToHttps();
app.UseRewriter(options);
app.UseAuthentication();
app.UseMvc();
}
}
public class CustomAuthOptions : AuthenticationSchemeOptions
{
public ClaimsIdentity Identity { get; set; }
public CustomAuthOptions()
{
}
}
public static class CustomAuthExtensions
{
public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
{
return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
}
}
internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
string token = Request.Headers["Authorization"];
if (string.IsNullOrEmpty(token))
return AuthenticateResult.Fail("Failing string");
// Using external service to validate token and get user id
int Id = GetUserId(token);
return AuthenticateResult.Success(
new AuthenticationTicket(
new ClaimsPrincipal(
new ClaimsIdentity(
new List<Claim>() { new Claim(ClaimTypes.Sid, Id.ToString()) })),
Scheme.Name));
}
}
The problem is caused by the way you create an instance of ClaimsIdentity
in CustomAuthHandler.HandleAuthenticateAsync()
. The value of principal.Identity.IsAuthenticated
will be false
that makes AuthorizeAttribute
to consider your request unathorized.
The reason why IsAuthenticated
is set to false is described here in detail. To fix it, just use ClaimsIdentity
constructor overload that takes authenticationType
:
return AuthenticateResult.Success(
new AuthenticationTicket(
new ClaimsPrincipal(
new ClaimsIdentity(
new List<Claim>() { new Claim(ClaimTypes.Sid, Id.ToString()) }, Scheme.Name)),
Scheme.Name));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With