Странное поведение при принятии аутентификации Bearer и OpenIdConnect от одного клиента с IdentityServer4 - PullRequest
2 голосов
/ 07 марта 2019

У меня возникли некоторые проблемы после внесения некоторых изменений в Образец решения IdentityServer4 Quickstart , в частности образец 8_AspNetIdentity.

Я предвожу это, говоря, что не уверен, что чтоЯ пытаюсь сделать, просто не поддерживается, или если я делаю это неправильно.

Этот пример решения содержит следующие проекты, относящиеся к моему вопросу:

  • a IdentityServer,
  • клиент MVC (с именем MVCClient), который использует OpenIdConnect для аутентификации своих пользователей,
  • клиент веб-API (с именем API), который использует аутентификацию на предъявителя для своих пользователей
  • консольприложение (названное ResourceOwnerClient), предназначенное для клиента API

Что я пытаюсь сделать, это объединить проект API с MVCClient, чтобы MVCClient мог как аутентифицировать пользователей со своего сайта MVCс OIDC, а также с ResourceOwnerClient с использованием аутентификации на предъявителя.

Я внес следующие изменения в файл Startup.cs MVCClient:

  1. изменено services.AddMvc(); на:

    services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder(new[]
            {
                JwtBearerDefaults.AuthenticationScheme,
                CookieAuthenticationDefaults.AuthenticationScheme,
                "oidc"
            })
            .RequireAuthenticatedUser()
            .Build();
    
        config.Filters.Add(new AuthorizeFilter(policy));
    });
    
  2. добавлены опции однонаправленного канала JWT к services.AddAuthentication():

    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    {
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;
        options.Audience = "api1";
    })
    

Теперь технически это сработало, поскольку и ResourceOwnerClient, и пользователи MVC могут успешно проходить аутентификацию с MVCClient.Однако у меня есть одно предупреждение:

Когда я аутентифицируюсь с пользователем со стороны MVC, я заметил, что у моего текущего пользователя есть две личности.Обе идентичны с точки зрения требований и т. Д. Это происходит только тогда, когда я ставлю точку останова в MVCClient, на IdentityServer есть только одна идентификационная информация.

enter image description here

На IdentityServer я зарегистрировал UserClaimsPrincipalFactory, который добавляет мои собственные пользовательские утверждения в ClaimsIdentity.В двух удостоверениях на IdentityServer я вижу дубликаты утверждений.Таким образом, вместо одного удостоверения с двумя настраиваемыми утверждениями, я вижу два удостоверения, каждое из которых имеет 4 настраиваемых утверждения.Метод CreateAsync в моем UserClaimsPrincipalFactory также получает удар 5 раз для одного входа в систему.

Хотя это поведение странное, похоже, что оно не оказывает каких-либо негативных последствий.Но это только доказательство концепции для более крупного приложения, которое я создаю, и я боюсь, что из-за него в будущем могут возникнуть проблемы.

Если кто-то пытался делать подобные вещи раньшеили знает, почему это может происходить, любая помощь будет принята.

1 Ответ

3 голосов
/ 07 марта 2019

Хотя с этим дизайном не должно случиться ничего плохого, я бы полностью переделал его.Зачем?Потому что вы смешиваете Client и ApiResource, и они должны быть логически разделены.Client - это приложение , с которым взаимодействует какой-то пользователь, даже если это было безголовое приложение (т. Е. Автоматизированная служба);в то время как ApiResource состоит из ресурсов, предоставляемых клиентам , поэтому ни один пользователь не может взаимодействовать с ним напрямую.

Вы можете добавить две аутентификации на IdentityServer, одну как API (и добавить как JwtBearer), а другую как Клиент (и добавить как Cookies).Затем вы можете использовать [Authorize(AuthenticationSchemes = "JwtBearer")] и = "Cookies" в зависимости от функции этого Action / Controller.

Оставляя это в стороне, проблема в том, что ваше приложение получает один идентификатор для стороны MVC и один для APIсторона, так как он не может сказать, какой вы хотите.

Просто у вас есть идея, вот как выглядит один из моих IdentityServer с ASP.NET Core Identtiy, где вы можете войти в систему, используя егопользовательский интерфейс, а также поразить конечные точки REST с помощью JwtToken:

services
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
        options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
    })
    .AddIdentityServerAuthentication(JwtBearerDefaults.AuthenticationScheme, options =>
    {
        options.Authority = Configuration["IdentityServerUrl"];
        options.ApiName = Configuration["ApiName"];

        options.RequireHttpsMetadata = false;
    })
    .AddCookie(IdentityConstants.ApplicationScheme, o =>
    {
        o.LoginPath = new PathString("/Account/Login");
        o.Events = new CookieAuthenticationEvents()
        {
            OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
        };
    })
    .AddCookie(IdentityConstants.ExternalScheme, o =>
    {
        o.Cookie.Name = IdentityConstants.ExternalScheme;
        o.ExpireTimeSpan = TimeSpan.FromMinutes(5.0);
    })
    .AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>
    {
        o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;
    })
    .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
    {
        o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
        o.ExpireTimeSpan = TimeSpan.FromMinutes(5.0);
    });
...