401 Несанкционированный с использованием IdentityServer3.AccessTokenValidation - PullRequest
0 голосов
/ 02 апреля 2020

При использовании IdentityServer3.AccessTokenValidation в моем. Net 4.8 (не основном) WebAPI для защиты конечных точек, WebAPI всегда возвращает 401 Not Authorized для клиентского приложения. Токен предоставляется IDS4. Когда клиент вызывает мой Asp. Net Core API, авторизация прошла успешно. Но при вызове. Net 4.8 как pNet WebApi, это не так.

Клиент MVC Запуск приложения. ConfigureServices:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
                .AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.ClientId = "TestMvc";
                    options.ClientSecret = "secret";
                    options.ResponseType = "code"; 
                    options.GetClaimsFromUserInfoEndpoint = true;
                    options.SaveTokens = true;
                    options.Scope.Add("testApi");
                    options.CallbackPath = "/auth";
                    options.SignedOutRedirectUri = "~/home";
                });
        } 

. Net Core API Startup, который работает:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://localhost:5000";
                options.ApiName = "testApi";
                options.RequireHttpsMetadata = false;
                options.RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
            });
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

Startup.cs из. Net 4.8 WebApi, который всегда возвращает 401:

public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
            config.EnableSystemDiagnosticsTracing();

            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);

            var idsOptions = new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                RequiredScopes = new string[] { "testApi" },
                RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role
            };
            app.UseIdentityServerBearerTokenAuthentication(idsOptions);

            app.UseWebApi(config);
        }

Конечная точка основного контроллера Asp. Net, которая успешно выполняется

[Route("test")]
[Authorize(Roles = "[A role claim that is definitely present in access token]")]
public class TestController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok("Success");
    }
}

Asp. Net 4.8 Конечная точка контроллера, которая возвращает 401

[Route("test")]
[Authorize(Roles = "[A role claim that is definitely present in access token]")]
public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult Get()
    {
        return Ok("Success");
    }
}

MVC API вызова клиентского приложения:

public async Task<IActionResult> AccessApi()
        {
            var accessToken = await HttpContext.GetTokenAsync("access_token");

            var client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var content = await client.GetStringAsync("http://localhost:5001/test");

            ViewBag.Json = content;
            return View("json");
        }

Последние строки журнала сервера IDS:

info: Microsoft.AspNetCore.Hosting.Diagnostics [1] Запрос на запуск HTTP / 1.1 GET http://localhost: 5000 / .well-known / openid-configuration dbug : IdentityServer4.Hosting.EndpointRouter [0] Путь запроса /.well-known/openid-configuration соответствует типу конечной точки Discovery dbug: IdentityServer4.Hosting.EndpointRouter [0] Конечная точка включена: обнаружение успешно создано обработчик: IdentityServer4.Endpoints.DiscoveryEndpoint info: IdentityServer4.Hosting.IdentityServerMiddleware [0] Вызов конечной точки IdentityServer: IdentityServer4.Endpoints.DiscoveryEndpoint для /.well-known/openid-configuration dbug.D_Derver_Descovery : Microsoft.AspNetCore.Hosting.Diagnostics [2] Запрос завершен в 17.3987ms 200 application / json; charset = UTF-8 info: Microsoft.AspNetCore.Hosting.Diagnostics [1] Запрос на запуск HTTP / 1.1 GET http://localhost: 5000 / .well-known / openid-configuration / jwks dbug: IdentityServer4.Hosting .EndpointRouter [0] Путь запроса /.well-known/openid-configuration/jwks сопоставлен с типом конечной точки. Обнаружение dbug: IdentityServer4.Hosting.EndpointRouter [0] Конечная точка включена: обнаружение, успешно созданный обработчик: IdentityServer4.Endpoints.DiscoveryKeyEndpointer: Ident .Hosting.IdentityServerMiddleware [0] Вызов конечной точки IdentityServer: IdentityServer4.Endpoints.DiscoveryKeyEndpoint для /.well-known/openid-configuration/jwks dbug: IdentityServer4.Endpoints.DiscoveryKeyEndpoint [0] запрос на получение файла. Диагностика [2] Запрос выполнен в 16.6027ms 200 application / jwk-set + json; charset = UTF-8

Токен успешно выдан и передан в заголовках запросов в API.

Кажется, что API правильно вызывает конечную точку обнаружения, но после этого ничего не происходит который. Я ожидал бы, что API проверит входящий токен с сервера IDS, но нет никакого вызова к серверу IDS для проверки. Подтверждено как журналом IDS, так и использованием Fiddler для проверки трафика c.

1 Ответ

0 голосов
/ 03 мая 2020

Это может быть вызвано несколькими причинами, чтобы убедиться, что нам нужен журнал ASP. NET проекта API. Вот некоторые предлагаемые исправления для подобных проблем:

  1. В Statup.cs классе проекта IdentityServer
    • Измените AccessTokenJwtType на JWT, значение по умолчанию для IdentityServer4 равно at+jwt, но . Net Framework Api (OWIN / Katana) требует JWT.
    • Добавьте /resources aud, установив для EmitLegacyResourceAudienceClaim значение true, это удаляется на IdentityServer4.

Вы можете проверить токен доступа на https://jwt.ms/, проверив "typ" и "aud".

var builder = services.AddIdentityServer(                
                options =>
                {
                    options.AccessTokenJwtType = "JWT"; 
                    options.EmitLegacyResourceAudienceClaim = true;
                });
В Statup.cs классе. Net Framework Api project, установите ValidationMode в ValidationMode.Local, конечная точка проверки маркера доступа, используемая этим методом, удалена на IdentityServer4.

var idsOptions = new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                RequiredScopes = new string[] { "testApi" },
                RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
                ValidationMode = ValidationMode.Local,
            };

У меня есть пример рабочей реализации здесь , а также сообщение в блоге содержит более подробную информацию https://nahidfa.com/posts/identityserver4-and-asp-.net-web-api/

Я настоятельно рекомендую вам собирать логи API, это помогает найти актуальную проблему в вашем случае и найти решение. здесь - это пример включения OWIN log на Api.

...