c#HttpRequestMessage授权使用IdentityServer返回401

时间:2019-09-08 09:01:50

标签: c# asp.net-core identityserver4

我有一个正在运行的用于演示目的的IdentityServer4服务器(我已遵循IdentityServer4文档中的入门指南)。我可以从中获取令牌,并且在使用Postman时可以使用此令牌从受保护的资源中获取信息。

但是当我尝试从我的C#代码中使用此令牌时,我收到401响应(Postman中的相同令牌工作正常)。我在代码中设置请求的方式如下:

httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "{token string}");

我知道服务器接受令牌。我添加了一个控制台,用于在到达服务器的不同请求中写入令牌,并将其与我从Postman获得的内容进行比较。这是我的输出:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 87
>>>>>>>>>>>>> PATH: /connect/token
>>>>>>>>>>>>> AUTH:
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /connect/token matched to endpoint type Token
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
dbug: IdentityServer4.Endpoints.TokenEndpoint[0]
      Start token request.
dbug: IdentityServer4.Validation.ClientSecretValidator[0]
      Start client validation
dbug: IdentityServer4.Validation.BasicAuthenticationSecretParser[0]
      Start parsing Basic Authentication secret
dbug: IdentityServer4.Validation.PostBodySecretParser[0]
      Start parsing for secret in post body
dbug: IdentityServer4.Validation.SecretParser[0]
      Parser found secret: PostBodySecretParser
dbug: IdentityServer4.Validation.SecretParser[0]
      Secret id found: client
dbug: IdentityServer4.Stores.ValidatingClientStore[0]
      client configuration validation for client client succeeded.
dbug: IdentityServer4.Validation.SecretValidator[0]
      Secret validator success: HashedSharedSecretValidator
dbug: IdentityServer4.Validation.ClientSecretValidator[0]
      Client validation success
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      Start token request validation
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      Start client credentials token request validation
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      client credentials token request validation success
info: IdentityServer4.Validation.TokenRequestValidator[0]
      Token request validation success, {
        "ClientId": "client",
        "GrantType": "client_credentials",
        "Scopes": "api1",
        "Raw": {
          "grant_type": "client_credentials",
          "client_id": "client",
          "client_secret": "***REDACTED***",
          "username": "",
          "password": "***REDACTED***"
        }
      }
dbug: IdentityServer4.Services.DefaultClaimsService[0]
      Getting claims for access token for client: client
dbug: IdentityServer4.Endpoints.TokenEndpoint[0]
      Token request success.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 343.2786ms 200 application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/api/values/ application/json; charset=utf-8 4
>>>>>>>>>>>>> PATH: /api/values/
>>>>>>>>>>>>> AUTH: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjYyNGM5MmFkZGZmNGMzN2I1ZDFmMTdmZjI2ZGQ4MmQ0IiwidHlwIjoiSldUIn0.eyJuYmYiOjE1Njc5MzMwMTcsImV4cCI6MTU2NzkzNjYxNywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJhcGkxIl0sImNsaWVudF9pZCI6ImNsaWVudCIsInNjb3BlIjpbImFwaTEiXX0.wILiCZ_H8-8ZyIYjxwt_Z7Mixr6wk1bwF0n2MTLrSkT7lZUShM1LFrmRaMAj37vJMN86a4q-WmBfqWhsxmfn8IqYn7GwlWOFIzbeHgaiqL0I4FsBPNzXNmBt_jkmMVwfLrxFWQ7b-6rucXvcNJjr9hUKQ-3jhF3nw7Za9D-YclnBH8NOOg5V1z7lTQOAU-5B7YbZut9uh1RYnOO2Spqg-EQ8Qd00Yy4sdNLidH1yZi6MoTgNhqmx4mV64oQERrdAzMPdw2-DlWYk8Ujd-qixNwCHHAlA35XlQZFHnZSrOrJwTNJBF-xGypbBQvLtqbWxD3ZnvuZcQ-ItGiIF9CFX-g
info>>>>>>>>>>>>> PATH: /.well-known/openid-configuration
>>>>>>>>>>>>> AUTH:
: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
dbug: IdentityServer4.Endpoints.DiscoveryEndpoint[0]
      Start discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 44.5515ms 200 application/json; charset=UTF-8
>>>>>>>>>>>>> PATH: /.well-known/openid-configuration/jwks
>>>>>>>>>>>>> AUTH:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration/jwks
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
dbug: IdentityServer4.Endpoints.DiscoveryKeyEndpoint[0]
      Start key discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 26.8755ms 200 application/jwk-set+json; charset=UTF-8
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[2]
      Successfully validated the token.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 242.3834ms 307
info: Microsoft.AspNetCore.Server.Kestrel[32]
      Connection id "0HLPK7A0C1DTP", Request id "0HLPK7A0C1DTP:00000001": the application completed without reading the entire request body.
info>>>>>>>>>>>>> PATH: /api/values/
>>>>>>>>>>>>> AUTH:
: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/api/values/ application/json; charset=utf-8 4
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'AuthServerDemo.Controllers.ValuesController.Get (AuthServerDemo)'
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Route matched with {action = "Get", controller = "Values"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[System.String]] Get() on controller AuthServerDemo.Controllers.ValuesController (AuthServerDemo).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action AuthServerDemo.Controllers.ValuesController.Get (AuthServerDemo) in 27.7154ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'AuthServerDemo.Controllers.ValuesController.Get (AuthServerDemo)'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 88.7948ms 401
info: Microsoft.AspNetCore.Server.Kestrel[32]
      Connection id "0HLPK7A0C1DTR", Request id "0HLPK7A0C1DTR:00000001": the application completed without reading the entire request body.

调用api/values端点时,我看到请求已被令牌接受。然后,它先呼叫.well-known/openid-configuration,再呼叫.well-known/openid-configuration/jwks,再呼叫api/values,但这一次是用空的授权令牌。

如果将此与Postman呼叫进行比较,则在第二次致电api/values端点时,它确实具有授权令牌。

我的请求设置中缺少什么?有人可以解释在服务器端进行的额外调用以及为什么对api/values的调用要进行两次吗?

1 个答案:

答案 0 :(得分:-1)

您需要按如下所示在API项目中配置IdentityServer EndPoint

public void ConfigureServices(IServiceCollection services)
{

    services.AddMvcCore()
    .AddAuthorization()
    .AddJsonFormatters();

    services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = "http://localhost:5000";//IdentityServer4 Endpoint
        options.RequireHttpsMetadata = false;

        options.ApiName = "api1";//Name of resource
    });

}