title: AuthenticationHandler error AuthenticationScheme: Bearer was forbidden
body: <p>I'm making a small service using ASP.NET Core. The first complicated thing I'm facing now is to authenticate an user into my system.</p>
  
  <p>Let me introduce about my authentication flow:</p>
  
  <p>+)<strong>Client</strong> -> <strong>call (api/account/authorize)</strong> -> <strong>System check whether client is valid or not</strong> -> <strong>Send token back to client as him/her is valid</strong>.</p>
  
  <p>+) <strong>Client</strong> -> <strong>uses the obtained token</strong> -> <strong>requests to api/account/filter</strong> -> <strong>Service validates the token and throw the information back</strong>.</p>
  
  <p>I've read some tutorials about JWT, but the response doesn't include enough information as I need. <strong>I want</strong> :</p>
  
  <ul>
  <li><strong>Throw 401</strong> and <strong>a message describes that status code</strong> , i.e: "<strong>ACCOUNT_DISABLED</strong>", "<strong>ACCOUNT_PENDING</strong>", "<strong>ACCOUNT_PERMISSION_INSUFFICIENT</strong>", ... not just 401.</li>
  </ul>
  
  <p>Therfore, I implemented my own Authenticate validator:</p>
  
  <pre><code>public class BearerAuthenticationHandler : AuthenticationHandler&lt;BearerAuthenticationOption&gt;
  {
      #region Properties
  
      /// &lt;summary&gt;
      /// Inject dependency service into the handler.
      /// &lt;/summary&gt;
      private readonly JwtTokenSetting _encryptionSetting;
  
      /// &lt;summary&gt;
      /// Inject dependency service into the handler.
      /// &lt;/summary&gt;
      private readonly IEncryptionService _encryptionService;
  
      /// &lt;summary&gt;
      /// Inject time service to handler.
      /// &lt;/summary&gt;
      private readonly ITimeService _timeService;
  
      private readonly IRepositoryAccount _repositoryAccount;
  
      #endregion
  
      #region Constructors
  
      /// &lt;summary&gt;
      /// Initialize an instance of handler with specific dependency injections.
      /// &lt;/summary&gt;
      /// &lt;param name="encryptionSetting"&gt;&lt;/param&gt;
      /// &lt;param name="encryptionService"&gt;&lt;/param&gt;
      /// &lt;param name="timeService"&gt;&lt;/param&gt;
      /// &lt;param name="repositoryAccount"&gt;&lt;/param&gt;
      public BearerAuthenticationHandler(JwtTokenSetting encryptionSetting, IEncryptionService encryptionService, ITimeService timeService, IRepositoryAccount repositoryAccount)
      {
          _encryptionSetting = encryptionSetting;
          _encryptionService = encryptionService;
          _timeService = timeService;
          _repositoryAccount = repositoryAccount;
      }
  
      #endregion
  
      #region Methods
  
      protected override async Task&lt;AuthenticateResult&gt; HandleAuthenticateAsync()
      {
          #region Token analyzation
  
          // Find the authorization key in request.
          var authorizationKey =
              Request.Headers.Keys.FirstOrDefault(x =&gt; x.Equals("authorization", StringComparison.OrdinalIgnoreCase));
  
          // Authorization key is not found in the request.
          if (string.IsNullOrWhiteSpace(authorizationKey))
              return AuthenticateResult.Fail("No authorization is found in request header.");
  
          // Find the token in Authorization.
          var authorizationValue = Request.Headers[authorizationKey].ToString();
  
          // Authentication scheme prefix.
          var authenticationScheme = $"{Options.AuthenticationScheme} ";
  
          // No token has been specified.
          if (string.IsNullOrWhiteSpace(authorizationValue) || !authorizationValue.StartsWith(authenticationScheme, StringComparison.OrdinalIgnoreCase))
              return AuthenticateResult.Fail("No bearer token is found in request header.");
  
          // Cut the string to obtain bearer token.
          var accessToken = authorizationValue.Substring(authenticationScheme.Length);
  
          #endregion
  
          #region Token validation
  
          // Decrypt the token.
          var tokenDetailViewModel = _encryptionService.Decrypt&lt;TokenDetailViewModel&gt;(accessToken, _encryptionSetting.Key);
  
          // No detail has been found.
          if (tokenDetailViewModel == null)
          {
              InitializeHttpResponse(Response, HttpStatusCode.Unauthorized, new HttpResponseViewModel
              {
                  Message = "TOKEN_INVALID"
              });
  
              return AuthenticateResult.Fail("Token is invalid");
          }
  
          // Find the current unix time on server.
          var unixTime = _timeService.UtcToUnix(DateTime.UtcNow);
  
          // Token is expired.
          if (unixTime &gt; tokenDetailViewModel.Expire)
          {
              InitializeHttpResponse(Response, HttpStatusCode.Unauthorized, new HttpResponseViewModel
              {
                  Message = "TOKEN_EXPIRED"
              });
  
              return AuthenticateResult.Fail("Token is expired");
          }
  
          // Account filter construction.
          var filterAccountViewModel = new FilterAccountViewModel
          {
              Email = tokenDetailViewModel.Email,
              EmailComparison = TextComparision.Equal,
              Password = tokenDetailViewModel.Password,
              PasswordComparision = TextComparision.EqualIgnoreCase,
              Statuses = new[] { AccountStatus.Active }
          };
  
          // Find the first condition statisfied account in the database.
          var account = await _repositoryAccount.FindAccountAsync(filterAccountViewModel);
  
          // Account cannot be found in the database.
          if (account == null)
          {
              InitializeHttpResponse(Response, HttpStatusCode.Unauthorized, new HttpResponseViewModel
              {
                  Message = "ACCOUNT_INVALID"
              });
              return AuthenticateResult.Fail("Account is invalid");
          }
  
          #endregion
  
          var claimsIdentity = new ClaimsIdentity();
          claimsIdentity.AddClaim(new Claim(nameof(JwtClaim.Email), account.Email));
          claimsIdentity.AddClaim(new Claim(nameof(JwtClaim.Status), nameof(account.Status)));
  
          // Update user into context.
          var claimPrincipal = new ClaimsPrincipal(claimsIdentity);
  
          // Initialize an authentication ticket.
          var authenticationTicket = new AuthenticationTicket(claimPrincipal, new AuthenticationProperties
          {
              AllowRefresh = true,
              ExpiresUtc = DateTime.UtcNow.AddMinutes(30),
              IsPersistent = true,
              IssuedUtc = DateTime.UtcNow
          }, "Bearer");
  
          return AuthenticateResult.Success(authenticationTicket);
      }
  
      /// &lt;summary&gt;
      /// Initialize an application/json response.
      /// &lt;/summary&gt;
      /// &lt;param name="httpResponse"&gt;&lt;/param&gt;
      /// &lt;param name="httpStatusCode"&gt;&lt;/param&gt;
      /// &lt;param name="httpResponseViewModel"&gt;&lt;/param&gt;
      private void InitializeHttpResponse(HttpResponse httpResponse, HttpStatusCode httpStatusCode, HttpResponseViewModel httpResponseViewModel)
      {
          // Response must be always application/json.
          httpResponse.ContentType = "application/json";
          httpResponse.StatusCode = (int)httpStatusCode;
  
          if (httpResponseViewModel == null)
              return;
  
          using (var streamWriter = new StreamWriter(httpResponse.Body))
          {
              streamWriter.AutoFlush = true;
              streamWriter.WriteLineAsync(JsonConvert.SerializeObject(httpResponseViewModel));
          }
      }
  
      #endregion
  }
  </code></pre>
  
  <p>Here is my AccountController:</p>
  
  <pre><code>[Route("api/[controller]")]
  public class AccountController : Controller
  {
      private readonly IRepositoryAccount _repositoryAccount;
  
      private readonly IEncryptionService _encryptionService;
  
      private readonly ITimeService _timeService;
  
      private readonly JwtTokenSetting _jwtTokenSetting;
  
      public AccountController(IRepositoryAccount repositoryAccount, IEncryptionService encryptionService, ITimeService timeService,
          IOptions&lt;JwtTokenSetting&gt; jwtTokenSetting)
      {
          _repositoryAccount = repositoryAccount;
          _encryptionService = encryptionService;
          _timeService = timeService;
          _jwtTokenSetting = jwtTokenSetting.Value;
      }
  
      [HttpPost("authorize")]
      [AllowAnonymous]
      public async Task&lt;IActionResult&gt; Authorize([FromBody] LoginViewModel loginViewModel)
      {
          // Find the encrypted password of login information.
          var filterAccountViewModel = new FilterAccountViewModel();
          filterAccountViewModel.Email = loginViewModel.Email;
          filterAccountViewModel.EmailComparison = TextComparision.Equal;
          filterAccountViewModel.Password = _encryptionService.FindEncryptPassword(loginViewModel.Password);
          filterAccountViewModel.PasswordComparision = TextComparision.EqualIgnoreCase;
          filterAccountViewModel.Statuses = new[] {AccountStatus.Active};
  
          // Initialize HttpResponseViewModel.
          var httpResponseViewModel = new HttpResponseViewModel();
  
          // Find the account.
          var account = await _repositoryAccount.FindAccountAsync(filterAccountViewModel);
  
          // Account is not found.
          if (account == null)
          {
              Response.ContentType = "application/json";
              using (var streamWriter = new StreamWriter(Response.Body))
              {
                  httpResponseViewModel.Message = "ACCOUNT_INVALID";
                  await streamWriter.WriteLineAsync(JsonConvert.SerializeObject(httpResponseViewModel));
              }
  
              return new UnauthorizedResult();
          }
  
          // Initialize token detail.
          var tokenDetailViewModel = new TokenDetailViewModel
          {
              Email = loginViewModel.Email,
              Password = filterAccountViewModel.Password,
              Expire = _timeService.UtcToUnix(DateTime.UtcNow.AddSeconds(_jwtTokenSetting.Expire))
          };
  
          // Initialize token information and throw to client for their future use.
          var tokenGeneralViewModel = new TokenGeneralViewModel
          {
              AccessToken = _encryptionService.Encrypt(tokenDetailViewModel, _jwtTokenSetting.Key),
              Expire = _jwtTokenSetting.Expire
          };
  
          return Ok(tokenGeneralViewModel);
      }
  
  
      [HttpPost("filter")]
      [Authorize(ActiveAuthenticationSchemes = "Bearer")]
      public IEnumerable&lt;string&gt; FindAllAccounts()
      {
          Response.StatusCode = (int)HttpStatusCode.Accepted;
          return new[] { "1", "2", "3", "4" };
      }
  }
  </code></pre>
  
  <p>When I use the token generated by api/account/authorize to access api/account/filter. An error was thrown to me :</p>
  
  <p><strong>AuthenticationScheme: Bearer was forbidden</strong></p>
  
  <p>Can anyone please tell me why ? Is my implementation the best approach or not ?</p>
  
  <p>Thank you,</p>