如何调试 JWT 承载错误 "invalid_token"

How to debug JWT Bearer Error "invalid_token"

我正在尝试使用 jwt 保护现有的 AspNet Core 2.0 / angular 4 应用程序。我在客户端使用 angular2-jwt,它工作得很好。但是,当涉及到我的 WebApi 时,我的令牌总是被拒绝(使用 angular2-jwt 中的 AuthHttp 来启动我的请求,甚至使用邮递员)。我得到的唯一响应是 401 Bearer error="invalid_token"。我用 jwt.io chrome 扩展名检查过它,它看起来很好(签名、观众、发行人)。我在 IIS 日志中找不到任何关于它被视为无效的原因。所以我的问题是如何获得有关令牌问题的更多信息? 任何帮助将不胜感激。

我的startup.cs

供参考
public class Startup
  {

public static void Main(string[] args)
{
  var host = new WebHostBuilder()
      .UseKestrel()
      .UseContentRoot(Directory.GetCurrentDirectory())
      .UseIISIntegration()
      .UseStartup<Startup>()
      .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<Controls.JWTConf>(Configuration.GetSection("jwt"));


  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
     .AddJwtBearer(options =>
     {
       options.TokenValidationParameters =
                       new TokenValidationParameters
                       {
                         ValidateIssuer = true,
                         ValidateAudience = true,
                         ValidateLifetime = true,
                         ValidateIssuerSigningKey = true,
                         ValidIssuer = jwtConf.GetValue<string>("issuer"),
                         ValidAudience = jwtConf.GetValue<string>("audience"),
                         IssuerSigningKey = Security.JwtSecurityKey.Create(jwtConf.GetValue<string>("keyBase"))
                       };
     });



  services.AddMvc(
          config =>
          {
            var policy = new AuthorizationPolicyBuilder()
                             .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                             .RequireClaim(ClaimTypes.Name)
                             .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
          }
    ).AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

  services.AddNodeServices();

  string conn = this.Configuration.GetConnectionString("optimumDB");

  services.AddDbContext<TracDbContext>(options =>
      options.UseSqlServer(conn));

  // Register the Swagger generator, defining one or more Swagger documents
  services.AddSwaggerGen(c =>
  {
    c.SwaggerDoc("v1", new Info { Title = "Angular 4.0 Universal & 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 =>
    {
      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 => !x.Request.Path.Value.StartsWith("/swagger", StringComparison.OrdinalIgnoreCase), builder =>
    {
      builder.UseMvc(routes =>
      {
        routes.MapSpaFallbackRoute(
            name: "spa-fallback",
            defaults: new { controller = "Home", action = "Index" });
      });
    });
  }
  else
  {
    app.UseMvc(routes =>
    {
      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");

  }
}

  }

我的令牌生成控制器

  [Route("api/token")]
  [AllowAnonymous]
  public class TokenController : Controller
  {

private IOptions<JWTConf> jwt;

public TokenController(IOptions<JWTConf> 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));
}
  }

最后是拒绝令牌的控制器:

  [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<Departement> Get()
{
  return new GroupedJobs(Db.GetJobs().ToList());
}

[HttpGet]
[Route("api/Jobs/{id}")]
public JOB_CLIENT Get(int id)
{
  return Db.GetDetailsJob(id);
}

 }

发现问题...原来我在存储我的令牌时用引号括起来。所以发送的授权 header 看起来像这样

Bearer "TOKEN"

而不是

Bearer TOKEN

我对整个事情都不熟悉,我认为引号是由 AuthHtpp 添加的,并且是协议的一部分。