title: ASP.NET core - simple API key authentication
body: <p>I am attempting to build a super simple API-key authentication for certain APIs in a controller. For this I have this in <code>ConfigureServices()</code></p>
  <pre><code>            services.AddAuthorization(options =&gt;
              {
                  options.AddPolicy(Auth.Constants.WebmasterPolicyName, policy =&gt;
                      policy.RequireAssertion(context =&gt;
                      {
                          if (context.Resource is HttpContext httpContext)
                          {
                              if (httpContext.Request.Headers.TryGetValue(&quot;X-API-KEY&quot;, out var header))
                              {
                                  var val = header.FirstOrDefault()?.ToLower();
                                  if (val == &quot;my-super-secret-key&quot;)
                                  {
                                      return Task.FromResult(true);
                                  }
                              }
                          }
                          return Task.FromResult(false);
                      }));
              });
  </code></pre>
  <p>I have decorated an API with this:</p>
  <pre><code>[HttpDelete(&quot;{itemId:guid}&quot;)]
  [Authorize(Policy = Auth.Constants.WebmasterPolicyName)]
  public async Task&lt;ActionResult&gt; DeleteCatalogItemAsync(Guid itemId)
  </code></pre>
  <p>This works perfectly, when I set the correct API key in the request.</p>
  <p>The problem is the negative case: When the key is missing or wrong, I will get a 500 error:</p>
  <pre><code>System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action&lt;AuthenticationOptions&gt; configureOptions).
     at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
     at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
     at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
     at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
     at AlwaysOn.CatalogService.Startup.&lt;&gt;c__DisplayClass5_0.&lt;&lt;Configure&gt;b__3&gt;d.MoveNext()
  --- End of stack trace from previous location ---
     at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.&lt;Invoke&gt;g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
  </code></pre>
  <p>But I'm not sure what to do with that message. I would just like it to return a 401 response to the client.</p>