Проблемы с сервером идентификации AuthenticationScheme: на предъявителя был запрошен токен, полученный с помощью учетных данных клиента. Как узнать основную ошибку? - PullRequest
0 голосов
/ 20 апреля 2020

У меня проблемы с аутентификацией некоторых запросов на интеграционные тесты при работе с Identity Server 4 (ASP. NET Core 3.1).

Моя настройка следующая:

Конфигурация сервера идентификации

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Email(),
        new IdentityResources.Profile(),
    };
}

public static IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource("resourceapi", "Resource API")
        {
            Scopes = {new Scope("api.read")}
        }
    };
}

public static IEnumerable<Client> GetClients()
{
    return new[]
    {
        new Client
        {
            RequireConsent = false,
            ClientId = "MY_CLIENT_ID",
            ClientName = "My Client Name",
            // code is required for SPA, client credentials for test runner
            AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
            AllowedScopes = {"openid", "profile", "email", "api.read"},
            RedirectUris = {"http://localhost:4201/auth-callback"},
            PostLogoutRedirectUris = {"http://localhost:4201/"},
            AllowedCorsOrigins = {"http://localhost:4201"},
            AllowAccessTokensViaBrowser = true,
            AccessTokenLifetime = 3600,
            RequireClientSecret = false
        }
    };
}


services.AddIdentity<AppUser, IdentityRole>()
    .AddEntityFrameworkStores<AppIdentityDbContext>()
    .AddDefaultTokenProviders();

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    // this adds the operational data from DB (codes, tokens, consents)
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration.GetConnectionString("Default"));
        // this enables automatic token cleanup. this is optional.
        options.EnableTokenCleanup = true;
        options.TokenCleanupInterval = 30; // interval in seconds
    })
    //.AddInMemoryPersistedGrants()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddAspNetIdentity<AppUser>();

ASP. NET Базовый клиент

// this is called from Startup.ConfigureServices
public static void ConfigureSecurity(this IServiceCollection services, IConfiguration configuration)
{
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(o =>
    {
        o.Authority = configuration.GetSection("Idam").GetValue<string>("BaseUrl");  // http://localhost:54916
        o.Audience = configuration.GetSection("Idam").GetValue<string>("Audience");  // "resourceapi"
        o.RequireHttpsMetadata = false;
    });

    services.AddAuthorization();
}

Код интеграционных тестов

var client = new HttpClient();
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = $"{IdentityServerUrl}/connect/token",
    ClientId = "MY_CLIENT_ID",
    ClientSecret = IdentityServerPass,
    Scope = "api.read"

}).ConfigureAwait(false);
tokenResponse.HttpResponse.EnsureSuccessStatusCode();

Здесь я получаю токен на предъявителя, но не кажется быть принятым (Identity Server выдает ошибку ниже). Это выглядит следующим образом:

{
  "nbf": 1587392198,
  "exp": 1587395798,
  "iss": "http://localhost:54916",
  "aud": "resourceapi",
  "client_id": "STACKOVERFLOW_METRO_MIRROR",
  "scope": [
    "api.read"
  ]
}


> IdentityServer4.Hosting.IdentityServerMiddleware: Information:
> Invoking IdentityServer endpoint:
> IdentityServer4.Endpoints.TokenEndpoint for /connect/token
> IdentityServer4.Validation.TokenRequestValidator: Information: Token
> request validation success, {   "ClientId":
> "STACKOVERFLOW_METRO_MIRROR",   "ClientName": "My Client Name",
> "GrantType": "client_credentials",   "Scopes": "api.read",   "Raw": {
>     "grant_type": "client_credentials",
>     "scope": "api.read",
>     "client_id": "MY_CLIENT_ID",
>     "client_secret": "***REDACTED***"   } } Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request
> starting HTTP/1.1 GET
> http://localhost:44324/api/GeneralData/GetAllTags  
> Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware:
> Information: No cached response available for this request.
> Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:
> Information: Authorization failed.
> Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:
> Information: AuthenticationScheme: Bearer was challenged.

Так как моя установка также включает в себя SPA, который может успешно пройти аутентификацию (вход в систему с помощью формы входа Identity Server -> get token -> API использует токен с успехом), я расшифровал такой маркер, чтобы увидеть, вижу ли я какое-либо существенное различие, которое может показать, чего мне не хватает в процессе проверки подлинности:

{
  "nbf": 1587393059,
  "exp": 1587396659,
  "iss": "http://localhost:54916",
  "aud": "resourceapi",
  "client_id": "MY_CLIENT_ID",
  "sub": "fd351b3b-dfb2-4f2f-8987-af9d23c9dc6e",
  "auth_time": 1587393055,
  "idp": "local",
  "given_name": "test",
  "email": "test@example.com",
  "scope": [
    "openid",
    "email",
    "profile",
    "api.read"
  ],
  "amr": [
    "pwd"
  ]
}

ASP. NET Core Web API Startup.cs

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

    services.ConfigureSettings(Configuration);
    services.ConfigureSecurity(Configuration);
    services.ConfigureMvc();
    services.BindLogging();

    services.ConfigureRedisCache(Configuration);
    services.ConfigureApiExplorer();
    services.AddHttpContextAccessor();

    services.AddDbContext(Configuration);
    ConfigureAuditNet();

    services.AddCorsAndPolicy();

    services.ConfigureHangfire(Configuration);

    services.AddSignalR();
    services.AddAutoMapper(typeof(QuestionProfile).Assembly);
    services.AddHealthChecks();

    services
        .AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
    ILoggingService logger, IHostApplicationLifetime lifetime, IServiceProvider serviceProvider,
    ISoApiDailyRequestInfoService soApiDailyRequestInfoService)
{
    app.UseResponseCaching();

    app.UseMiddleware<ResponseTimeMiddleware>();

    app.ProtectHangfireDashboard();

    app.ConfigureExceptionPage(env);

    app.StartHangFireJobs(serviceProvider, Configuration);

    ConfigureApplicationLifetime(logger, lifetime, soApiDailyRequestInfoService);

    app.UseHttpsRedirection();

    app.UseRouting();
    app.UseCors("CorsPolicy");

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

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

        endpoints.MapHub<PostHub>("/post");
        endpoints.MapHealthChecks("/health");
    });

    app.ConfigureAuditMiddleware();
    app.UseSwagger();
}

К сожалению, на сервере Identity выдается очень общая ошибка c, и я вижу, чего мне здесь не хватает.

Вопрос: Проблемы с сервером идентификации AuthenticationScheme: Bearer was challenged для токена полученные учетные данные клиента. Как узнать основную ошибку?

1 Ответ

0 голосов
/ 21 апреля 2020

В stratup.cs Настройте метод, пожалуйста, убедитесь, что последовательность app.Use ... правильная.

Например app.UseAuthentication(); до app.UseMvc()

...