/// <summary>
        /// Authenticates a request by ensuring the X-Api-Key header is present with an
        /// API key that exists in a backing store
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKeyHeaderValues))
            {
                return(AuthenticateResult.NoResult());
            }

            var providedKey = apiKeyHeaderValues.FirstOrDefault();

            if (apiKeyHeaderValues.Count == 0 || string.IsNullOrWhiteSpace(providedKey))
            {
                return(AuthenticateResult.NoResult());
            }

            var exists = await apiKeyService.ApiKeyExistsAsync(providedKey);

            if (!exists)
            {
                Log.Warning("An invalid API key was tried during request");
                return(AuthenticateResult.Fail("Invalid api key"));
            }

            var claims = new List <Claim>
            {
                new Claim("apiKey", providedKey)
            };

            var identity   = new ClaimsIdentity(claims, Options.AuthenticationType);
            var identities = new List <ClaimsIdentity> {
                identity
            };
            var principal = new ClaimsPrincipal(identities);
            var ticket    = new AuthenticationTicket(principal, Options.Scheme);

            // Make the API key accessible via scoped class ApiKeyProvider
            apiKeyProvider.ApiKey = providedKey;

            return(AuthenticateResult.Success(ticket));
        }