【问题标题】:Blazor IdentityServer AuthenthenticationBlazor IdentityServer 身份验证
【发布时间】:2021-04-22 02:22:36
【问题描述】:

目前我有三个独立的服务器。客户端在:5001,API 在:5002 和 IdentityServer 在:5003。我可以使用@attribute [Authorize] 对我的 Blazor 页面进行身份验证,但是当我调用 API 时出现 401 错误。如果我将 token_id 传递给邮递员并向其验证的 API 服务器发出请求。如果我从 Blazor 客户端发出请求,它将失败。我已将 CORS 列入白名单以排除此问题。如果我通过以下方式删除 API 上的受众检查:

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false
                    };

有效

客户端程序.cs

            builder.Services.AddHttpClient("api")
                .AddHttpMessageHandler(sp => 
                {
                    var handler = sp.GetService<AuthorizationMessageHandler>()
                        .ConfigureHandler(
                            authorizedUrls: new[] { "https://localhost:5002" },
                            scopes: new[] { "coredesk" });
                    return handler;
                });
            
            builder.Services.AddScoped(
                sp => sp.GetService<IHttpClientFactory>().CreateClient("api"));
            
            builder.Services.AddOidcAuthentication(options =>
            {
                builder.Configuration.Bind("oidc", options.ProviderOptions);
            });

客户端 appsettings.json

{
  "oidc": {
    "Authority": "https://localhost:5003/",
    "ClientId": "coredesk",
    "DefaultScopes": [
      "openid",
      "profile",
      "coredesk"
    ],
    "PostLogoutRedirectUri": "/",
    "ResponseType": "code"
  }
}

API 启动.cs

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.Authority = "https://localhost:5003";
                    options.Audience = "coredesk";
                });

IdentityServer Config.cs

        public static IEnumerable<IdentityResource> IdentityResources =>
            new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        
        public static IEnumerable<ApiResource> Apis =>
            new ApiResource[]
            {
                new ApiResource("coredesk", "CoreDesk API")
            };

        public static IEnumerable<ApiScope> ApiScopes =>
            new ApiScope[]
            {
                new ApiScope("coredesk"),
            };

        public static IEnumerable<Client> Clients =>
            new Client[]
            {
                new Client
                {
                    ClientId = "coredesk",
                    AllowedGrantTypes = GrantTypes.Code,
                    RequirePkce = true,
                    RequireClientSecret = false,
                    AllowedCorsOrigins = { "https://localhost:5001", "https://localhost:5002" },
                    AllowedScopes = { "openid", "profile", "coredesk" },
                    RedirectUris = { "https://localhost:5001/authentication/login-callback" },
                    PostLogoutRedirectUris = { "https://localhost:5001/" },
                    Enabled = true
                },
            };

【问题讨论】:

  • 当您收到 401 错误时,WWW-Authenticate 响应标头会说什么?错误示例如下所示:HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="invalid_token", error_description="签名无效"
  • 如果我删除 api 中的 Authorize 属性并运行调试器。我遵循的 Microsoft 文档和指南并未显示您必须将 Token 添加到标题中。我认为这是因为您不会将令牌存储在浏览器中 medium.com/@marcodesanctis2/…

标签: asp.net blazor identityserver4


【解决方案1】:

如果你查看AddJwtBearer 的源代码,你会发现这部分:

                // If no authorization header found, nothing to process further
                if (string.IsNullOrEmpty(authorization))
                {
                    return AuthenticateResult.NoResult();
                }

                if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                {
                    token = authorization.Substring("Bearer ".Length).Trim();
                }

                // If no token found, no further work possible
                if (string.IsNullOrEmpty(token))
                {
                    return AuthenticateResult.NoResult();
                }

这表明默认情况下(没有自定义)它需要在 Authorization 标头中提供令牌,如下所示:

GET /api/payments HTTP/1.1
Host: localhost:7001
Authorization: Bearer eyJhbGciOiJSUzI1NiIsIYwA...

为了进一步调试,我将删除授权属性,然后在其中一个操作方法中放置一个断点并检查 ClaimsPrincipal 用户对象包含的内容。

【讨论】:

  • 肯定是拿到令牌了。我刚刚尝试删除 API 上的 Audience 检查,它可以工作。我很确定我不会从任何地方错过 coredesk 范围。
  • WWW-Authenticate 标头说什么?您还可以查看 API 中的日志,Kestrel 确实提供了大量好的日志。
猜你喜欢
  • 2021-04-30
  • 2021-11-05
  • 2020-02-27
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2021-07-24
  • 1970-01-01
相关资源
最近更新 更多