Today I encountered a strange issue in an ASP.NET Core Web API application. Although I didn’t had authentication nor authorization configured(or at least that was what I thought) in my application, I still got a security related error when I tried to call any of the API endpoints:
System.InvalidOperationException:
No
authenticationScheme
was
specified,
and
there
was
no
DefaultForbidScheme
found.
The
default
schemes
can
be
set
using
either
AddAuthentication(string
defaultScheme)
or
AddAuthentication(Action<AuthenticationOptions>
configureOptions).
at
Microsoft.AspNetCore.Authentication.AuthenticationService.ForbidAsync(HttpContext
context,
String
scheme,
AuthenticationProperties
properties)
at
Microsoft.AspNetCore.Mvc.ForbidResult.ExecuteResultAsync(ActionContext
context)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|22_0(ResourceInvoker
invoker,
IActionResult
result)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker
invoker,
Task
lastTask,
State
next,
Scope
scope,
Object
state,
Boolean
isCompleted)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed
context)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State&
next,
Scope&
scope,
Object&
state,
Boolean&
isCompleted)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
---
End
of
stack
trace
from
previous
location
---
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker
invoker,
Task
lastTask,
State
next,
Scope
scope,
Object
state,
Boolean
isCompleted)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker
invoker)
at
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker
invoker)
at
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint
endpoint,
Task
requestTask,
ILogger
logger)
at
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext
context)
at
Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext
httpContext)
at
Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext
httpContext,
ISwaggerProvider
swaggerProvider)
at
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext
context)
Here is my middleware configuration:
var builder = WebApplication.CreateBuilder(args); | |
// Add services to the container. | |
builder.Services.AddControllers(); | |
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | |
builder.Services.AddEndpointsApiExplorer(); | |
builder.Services.AddSwaggerGen(); | |
var app = builder.Build(); | |
// Configure the HTTP request pipeline. | |
app.UseSwagger(); | |
app.UseSwaggerUI(); | |
app.UseHttpsRedirection(); | |
app.MapControllers(); | |
app.Run(); |
As you can see no sign of any form of authentication. So what was causing this error?
[HttpPost] | |
public async Task<IActionResult> Send(SendMailMessage message, CancellationToken token) | |
{ | |
if (BlockedAddressesFound(message)) | |
{ | |
// 👇 This is the cause of our trouble | |
return this.Forbid(); | |
} | |
var task = (CancellationToken token)=> ScheduleMailSend(message,token); | |
await _taskQueue.QueueBackgroundWorkItemAsync(task); | |
return Ok(); | |
} |
After taking a second look at my controller implementation I noticed the problem. I was returning a Forbid actionresult.
The ForbidResult will generate a 403 response and searches for a configured authenticationscheme to decide how this 403 response should be handled. (In some cases the 403 response will result in a redirect to a login page). As there was no authenticationscheme configured it resulted in the error message above.
To fix it I decided to use the ProblemDetails response instead.