ASP.NET JSON Web 令牌“401 未授权”

ASP.NET JSON Web Token "401 Unauthorized"

我正在使用分离的资源和身份验证服务器。 当我成功获得 JSON 网络令牌时,我用 jwt.io 检查它,令牌格式一切正常,而且它是秘密的。

请求已授权header:

Authorization: Bearer TOKEN_HERE

响应总是“401 Unauthorized”:

{
  "message": "Authorization has been denied for this request."
}

这是我的 Startup.cs 来自资源服务器

using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Newtonsoft.Json.Serialization;
using Owin;
using System.Web.Http;
using Test.Database;
using Test.Infrastructure;
using Microsoft.WindowsAzure.ServiceRuntime;

[assembly: OwinStartup(typeof(Test.API.Startup))]
namespace Custodesk.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.CreatePerOwinContext(() => 
                ApplicationDbContext.Create(RoleEnvironment.GetConfigurationSettingValue("SqlConnectionString")));
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            GlobalConfiguration.Configuration.SuppressDefaultHostAuthentication();

            ConfigureOAuthTokenConsumption(app);

            GlobalConfiguration.Configure(config =>
            {
                //global filters
                config.Filters.Add(new AuthorizeAttribute());

                // Web API routes
                config.MapHttpAttributeRoutes();
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

                config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

            app.UseCors(CorsOptions.AllowAll);

            app.UseWebApi(GlobalConfiguration.Configuration);
        }

        private void ConfigureOAuthTokenConsumption(IAppBuilder app)
        {
            var issuer = "http://localhost";
            var audience = "Universal_application";
            var secret = Helper.GetHash("helper_class_to_get_the_same_hash_as_authentication_server");

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = AuthenticationMode.Active,
                    AllowedAudiences = new[] { audience },
                    IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                    {
                        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
                    }
                });

        }
    }
}

这里是解密令牌的例子:

{
  "typ": "JWT",
  "alg": "HS256"
}
{
  "nameid": "b22a825e-60ce-45ed-b2cb-b2ee46a47936",
  "unique_name": "begunini",
  "role": [
    "Owner",
    "Admin",
    "ManagerViewer"
  ],
  "iss": "http://localhost",
  "aud": "Universal_application",
  "exp": 1454876502,
  "nbf": 1454876202
}

我已经检查了 Secret,两边(auth 和 resource servers)都一样。 观众配,发行者也。 已经尝试将 System.IdentityModel.Tokens.Jwt 降级到版本 3.0.2 但没有成功

我猜配置顺序有问题,但没有任何帮助。

有什么想法吗?

TL;DR:您是否尝试删除 GlobalConfiguration.Configuration.SuppressDefaultHostAuthentication()

使用此方法时,Web API 删除由主机或在 Web API 之前注册的中间件创建并添加到 OWIN 上下文的用户主体(在您的情况下,由 JWT承载中间件)。

此方法旨在与 HostAuthenticationFilterHostAuthenticationAttribute 一起使用,它直接调用与指定身份验证类型对应的身份验证中间件,并将生成的用户主体持久保存在 OWIN 上下文中。

由于您使用的 SuppressDefaultHostAuthentication 没有 HostAuthenticationAttribute,Web API 总是会看到未经身份验证的请求,这就是它们被 AuthorizeAttribute 拒绝的原因。