I have a dotnet core v3 web api that uses both Azure AD and Api key authentication. I would like to use bearer tokens on most controller methods but a few require api key access. The bearer token authentication and authorization is working fine. But I am unable to get the api key auth going.
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, ApiKeyAuthenticationHandler>("Api-Key", null);
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme,
"Api-Key")
.RequireAuthenticatedUser()
.Build();
options.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
options.AddPolicy("RequireApiKeyRole",
policy => policy.RequireRole("ApiKeyRole"));
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization();
});
}
The api key authentication handler
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var authorizationHeaders = Request.Headers["Authorization"];
var apiKeyHeader = authorizationHeaders.FirstOrDefault(
header => header.StartsWith(Scheme.Name, StringComparison.OrdinalIgnoreCase));
string apiKey = apiKeyHeader.Substring(Scheme.Name.Length).Trim();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "ApiKeyRole")
};
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
Controller
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet]
[Authorize(Policy = "RequireApiKeyRole")]
public ActionResult Get()
{
return Ok("Success");
}
}
This does not work. I am getting authenticated and the role is set. But I get a 403 response.