Ключ подписи не найден - IdentityServer4, OpenSSL и ASP.NET Core API - PullRequest
0 голосов
/ 21 января 2019

Я получаю следующий ответ при использовании Postman для отправки запроса GET с токеном носителя на мой API:

Статус: 401 Несанкционированный

WWW-Authenticate → Ошибка носителя = "invalid_token", error_description = "Ключ подписи не найден"

Мое решение включает в себя сервер авторизации под управлением IdentityServer4 и RESTful API, встроенный в ASP.NET Core 2.2

Сервер авторизации настроен с тестовым ресурсом, клиентом и пользователем. Он отвечает на запросы токенов, используя учетные данные тестового пользователя. Я получаю токен авторизации без проблем.

Мой API имеет один контроллер значений, украшенный фильтром действия [Авторизовать]. Перед добавлением фильтра он отвечал, как и ожидалось, на запросы GET. После этого отвечает 401 статус, когда токен не отправляется, но проблема в том, что я также получаю 401, когда я включаю токен в заголовок запроса. Я получаю ответ, в котором говорится, что ключ подписи не найден.

Я также настроил IdentityServer4 для входа в консоль, но на самом деле я не вижу зарегистрированных сообщений после ответа 401.

Решения, предлагаемые в стеке потока для подобных сценариев, не решили мою проблему Я подтвердил, что настроенное имя API соответствует client_id в моем заголовке запроса токена, в данном случае «logbookapi». Я отправляю токен, используя ключ заголовка Authorization, и добавляю токен в качестве значения «Носитель».

// API - Startup.cs
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConfiguration>(Configuration);
        services.AddScoped<ILogbookRepository, LogbookRepository>();

        services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options => new IdentityServerAuthenticationOptions
        {
            ApiName = "logbookapi",
            Authority = "http://localhost:5000",
            RequireHttpsMetadata = false
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddCors();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseCors(builder => builder.WithOrigins("http://localhost:6200/logbook")
        .AllowAnyHeader()
        .AllowAnyMethod()
        .AllowAnyOrigin()
        .AllowCredentials());

        app.UseAuthentication();
        app.UseMvc();
    }
}


// Authorization Server - Startup.cs
public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
            .AddSigningCredential(new X509Certificate2(@"C:\Program Files\Git\usr\bin\logbookapi.pfx", "password"))
            .AddInMemoryApiResources(InMemoryConfiguration.ApiResources())
            .AddInMemoryClients(InMemoryConfiguration.Clients())
            .AddTestUsers(InMemoryConfiguration.Users().ToList());

        services.AddMvc();

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseDeveloperExceptionPage();

        app.UseIdentityServer();

        app.UseStaticFiles();

        app.UseMvcWithDefaultRoute();
    }
}


// Authorization Server - in-memory config
public static class InMemoryConfiguration
{
    public static IEnumerable<ApiResource> ApiResources()
    {
        return new[]
        {
            new ApiResource("logbookapi", "Logbook API")
        };
    }

    public static IEnumerable<Client> Clients()
    {
        return new[]
        {
            new Client
            {
                ClientId = "w4lkr", // unique name for this in-memory client
                ClientSecrets = new[]
                {
                    new Secret("secret".Sha256()) // client secret hashed
                },
                AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials, // allow authorization via username/password and authorization token
                AllowedScopes = new[] // which scopes this client is allowed to use
                {
                    "logbookapi"
                }
            }
        };
    }

    public static IEnumerable<TestUser> Users()
    {
        return new[]
        {
            new TestUser
            {
                SubjectId = "1",
                Username = "mail@curtwalker.com",
                Password = "password"
            }
        };
    }
}


// API - values controller
[Route("api/[controller]")]
[Authorize]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return "value";
    }

    // POST api/values
    [HttpPost]
    public void Post([FromBody] string value)
    {
    }

    // PUT api/values/5
    [HttpPut("{id}")]
    public void Put(int id, [FromBody] string value)
    {
    }

    // DELETE api/values/5
    [HttpDelete("{id}")]
    public void Delete(int id)
    {
    }
}

Желаемый результат для ответа API:

{ "value1", "value2" } 

как показано в контроллере значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...