I'm migrating a legacy custom header thingy to IdentityServer client credentials flow.
So that both systems can run simultaneously I want to add a second authentication scheme to my API that supports the legacy systems during a changeover period.
I've created
public class MyProductAuthenticationHandler : AuthenticationHandler<MyProductAuthenticationSchemeOptions>
and hooked it up in Startup.cs with
.AddScheme<MyProductAuthenticationSchemeOptions, MyProductAuthenticationHandler>(MyProductAuthenticationSchemeOptions.AuthenticationScheme, _ => { });
and I can set a breakpoint in its HandleAuthenticateAsync and check that it's succeeding and making an AuthenticationTicket.
However, authorization subsequently fails (it still works for the JWT token authorization). I see these messages in the logging output.
MyProduct.Api.Services.Auth.MyProductAuthenticationHandler: Debug: AuthenticationScheme: MyProductwas successfully authenticated.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Debug: AuthenticationScheme: Bearer was not authenticated.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed.
MyProduct.Api.Services.Auth.MyProductAuthenticationHandler: Information: AuthenticationScheme: MyProduct was forbidden.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AuthenticationScheme: Bearer was forbidden.
MyProduct.Middleware.LoggingMiddleware: Warning: 403 @ GET /api/global/manage/tenants/TenantNameAvailable
The problem seems to be that
AuthenticationScheme: MyProduct was forbidden
but why is it forbidden after it authorized?
My policy is
options.AddPolicy(MyProductAuthorizationPolicy.GlobalTenantManagement, policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.AuthenticationSchemes.Add(MyProductAuthenticationSchemeOptions.AuthenticationScheme); // Obsolete. Remove after switching to client credentials flow.
policy.RequireAuthenticatedUser();
policy.RequireClaim("client_id", "client");
policy.RequireClaim("my_product_management", "global");
});
If I change my policy to
policy.AddAuthenticationSchemes(TruthLiteAuthenticationSchemeOptions.AuthenticationScheme);
policy.RequireAuthenticatedUser(); // If absent then there are no claims below.
policy.RequireAssertion((context) => {
int c = context.User.Claims.Count();
return true;
});
then then HandleAuthenticateAsync runs and I get the cliams, but
AuthenticationScheme: MyProduct was forbidden.
happens again and 403 is returned.