When using IdentityServer3.AccessTokenValidation in my .Net 4.8 (not core) WebAPI to secure the endpoints, the WebAPI always returns a 401 Not Authorized to the client app. The token is supplied by IDS4. When the client is calling my Asp.Net Core API, Authorization is successful. But when calling the .Net 4.8 AspNet WebApi, it is not.
Client MVC App Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "TestMvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.Scope.Add("testApi");
options.CallbackPath = "/auth";
options.SignedOutRedirectUri = "~/home";
});
}
The .Net Core API Startup that works:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.ApiName = "testApi";
options.RequireHttpsMetadata = false;
options.RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
});
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Startup.cs of the .Net 4.8 WebApi that always returns 401:
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.EnableSystemDiagnosticsTracing();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
var idsOptions = new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://localhost:5000",
RequiredScopes = new string[] { "testApi" },
RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role
};
app.UseIdentityServerBearerTokenAuthentication(idsOptions);
app.UseWebApi(config);
}
The Asp.Net Core Controller Endpoint that executes successfully
[Route("test")]
[Authorize(Roles = "[A role claim that is definitely present in access token]")]
public class TestController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Success");
}
}
The Asp.Net 4.8 Controller Endpoint that returns 401
[Route("test")]
[Authorize(Roles = "[A role claim that is definitely present in access token]")]
public class TestController : ApiController
{
[HttpGet]
public IHttpActionResult Get()
{
return Ok("Success");
}
}
MVC Client App Calling API:
public async Task<IActionResult> AccessApi()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var content = await client.GetStringAsync("http://localhost:5001/test");
ViewBag.Json = content;
return View("json");
}
The last lines of the IDS server log:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration dbug: IdentityServer4.Hosting.EndpointRouter[0] Request path /.well-known/openid-configuration matched to endpoint type Discovery dbug: IdentityServer4.Hosting.EndpointRouter[0] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint info: IdentityServer4.Hosting.IdentityServerMiddleware[0] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration dbug: IdentityServer4.Endpoints.DiscoveryEndpoint[0] Start discovery request info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 17.3987ms 200 application/json; charset=UTF-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration/jwks dbug: IdentityServer4.Hosting.EndpointRouter[0] Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery dbug: IdentityServer4.Hosting.EndpointRouter[0] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint info: IdentityServer4.Hosting.IdentityServerMiddleware[0] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks dbug: IdentityServer4.Endpoints.DiscoveryKeyEndpoint[0] Start key discovery request info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 16.6027ms 200 application/jwk-set+json; charset=UTF-8
The token is issued successfully and passed in the request headers to the API.
The API seems to be calling the discover endpoint correctly, but then nothing after that. I would expect the API to validate the incoming token with the IDS server, but there is no call to the IDS server for validation. Confirmed with both the IDS log and using Fiddler to check the traffic.
options.ApiNamein Core is the name of API resource, in the .NET setup it is configured as RequiredScope, cannot it be a difference? - Martin Staufcik