title: How to debug JWT Bearer Error "invalid_token"
body: <p>I'm trying to secure an existing AspNet Core 2.0 / angular 4 app using jwt. I'm using angular2-jwt for the client part and it works just fine. However when it comes to my WebApi, my token is always rejected(using AuthHttp from angular2-jwt to launch my requests or even with postman). The only response I get is 401 Bearer error="invalid_token".  I've checked it with the jwt.io chrome extension and it seems just fine(signature, audience, issuer). I can't find anything in the IIS logs either as to why it is deemed invalid. So my question is how can I get more information on what is wrong with the token ?
  Any help will be much appreciated.</p>
  
  <p>For reference here's my startup.cs</p>
  
  <pre><code>public class Startup
    {
  
  public static void Main(string[] args)
  {
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup&lt;Startup&gt;()
        .Build();
  
    host.Run();
  }
  public Startup(IHostingEnvironment env)
  {
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
  }
  
  public IConfigurationRoot Configuration { get; }
  
  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
  
    IConfigurationSection jwtConf = this.Configuration.GetSection("jwt");
  
    services.Configure&lt;Controls.JWTConf&gt;(Configuration.GetSection("jwt"));
  
  
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
       .AddJwtBearer(options =&gt;
       {
         options.TokenValidationParameters =
                         new TokenValidationParameters
                         {
                           ValidateIssuer = true,
                           ValidateAudience = true,
                           ValidateLifetime = true,
                           ValidateIssuerSigningKey = true,
                           ValidIssuer = jwtConf.GetValue&lt;string&gt;("issuer"),
                           ValidAudience = jwtConf.GetValue&lt;string&gt;("audience"),
                           IssuerSigningKey = Security.JwtSecurityKey.Create(jwtConf.GetValue&lt;string&gt;("keyBase"))
                         };
       });
  
  
  
    services.AddMvc(
            config =&gt;
            {
              var policy = new AuthorizationPolicyBuilder()
                               .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                               .RequireClaim(ClaimTypes.Name)
                               .Build();
              config.Filters.Add(new AuthorizeFilter(policy));
            }
      ).AddJsonOptions(options =&gt; options.SerializerSettings.ContractResolver = new DefaultContractResolver());
  
    services.AddNodeServices();
  
    string conn = this.Configuration.GetConnectionString("optimumDB");
  
    services.AddDbContext&lt;TracDbContext&gt;(options =&gt;
        options.UseSqlServer(conn));
  
    // Register the Swagger generator, defining one or more Swagger documents
    services.AddSwaggerGen(c =&gt;
    {
      c.SwaggerDoc("v1", new Info { Title = "Angular 4.0 Universal &amp; ASP.NET Core advanced starter-kit web API", Version = "v1" });
    });
  }
  
  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, TracDbContext context)
  {
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
  
    app.UseStaticFiles();
  
  
    app.UseAuthentication();
  
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
      app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
      {
        HotModuleReplacement = true,
        HotModuleReplacementEndpoint = "/dist/__webpack_hmr"
      });
      app.UseSwagger();
      app.UseSwaggerUI(c =&gt;
      {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
      });
  
      // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
  
  
      app.MapWhen(x =&gt; !x.Request.Path.Value.StartsWith("/swagger", StringComparison.OrdinalIgnoreCase), builder =&gt;
      {
        builder.UseMvc(routes =&gt;
        {
          routes.MapSpaFallbackRoute(
              name: "spa-fallback",
              defaults: new { controller = "Home", action = "Index" });
        });
      });
    }
    else
    {
      app.UseMvc(routes =&gt;
      {
        routes.MapRoute(
         name: "default",
         template: "{controller=Home}/{action=Index}/{id?}");
  
        routes.MapRoute(
         "Sitemap",
         "sitemap.xml",
         new { controller = "Home", action = "SitemapXml" });
  
        routes.MapSpaFallbackRoute(
          name: "spa-fallback",
          defaults: new { controller = "Home", action = "Index" });
  
      });
      app.UseExceptionHandler("/Home/Error");
  
    }
  }
  
    }
  </code></pre>
  
  <p>My token generating controller </p>
  
  <pre><code>  [Route("api/token")]
    [AllowAnonymous]
    public class TokenController : Controller
    {
  
  private IOptions&lt;JWTConf&gt; jwt;
  
  public TokenController(IOptions&lt;JWTConf&gt; jwtConf)
  {
    this.jwt = jwtConf;
  }
  
  [HttpPost]
  public IActionResult Create([FromBody]string userCode)
  {
    Model.Entities.Utilisateur user = new Model.Entities.Utilisateur { ID_UTILISATEUR = 6 };
  
    JwtToken token = new JwtTokenBuilder()
                        .AddSecurityKey(JwtSecurityKey.Create(this.jwt.Value.keyBase))
                        .AddSubject("User")
                        .AddIssuer(this.jwt.Value.issuer)
                        .AddAudience(this.jwt.Value.audience)
                        .AddClaim(ClaimTypes.Name,user.ID_UTILISATEUR.ToString())
                        .AddExpiry(1440)
                        .Build();
  
    var tok = new { token = token.Value };
  
    //return Ok(token);
    return Ok(JsonConvert.SerializeObject(tok));
  }
    }
  </code></pre>
  
  <p>And finally the controller that rejects the token :</p>
  
  <pre><code>  [Produces("application/json")]
    public class JobsController : BaseController
    {
  public JobsController(IConfiguration config, TracDbContext db) : base(config, db)
  {
  
  }
  
  // GET: api/Jobs
  [HttpGet]
  [Route("api/Jobs")]
  public IEnumerable&lt;Departement&gt; Get()
  {
    return new GroupedJobs(Db.GetJobs().ToList());
  }
  
  [HttpGet]
  [Route("api/Jobs/{id}")]
  public JOB_CLIENT Get(int id)
  {
    return Db.GetDetailsJob(id);
  }
  
   }
  </code></pre>