OpenIdConnect с .NET Core 2.2 MVC в направлении IdentityServer3 с использованием ScopePolicy. Как вы получаете области в принципале пользователя?

Кажется, что для настройки аутентификации OpenIdConnect от .NET Core 2.2 до IdentityServer3 мне нужно настроить с помощью общего вызова AddOpenIdConnect(), и для того, чтобы политика области работала, я переопределил OnTokenValidated, где я анализирую полученный токен доступа, и добавляю привязывает его к объекту ClaimsPrincipal.

Я не нашел другого способа заставить политику области действия работать. Хотя это кажется немного хакерским. Есть ли лучший или более простой способ, поэтому мне не нужно переопределять события или, по крайней мере, не анализировать токен доступа? В любом случае он анализируется в структуре, поэтому я подозреваю, что для получения областей действия в принципале утверждений были доступны другие функции.

Перемещая наш код с .NET 4.5.2 на .NET Core 2.2, мне нужно настроить аутентификацию для нашего IdentityServer3 сервера совсем другим способом.

Я надеялся, что новые функции в более поздних фреймворках позволят упростить настройку аутентификации в отношении IdentityServer3, но я не нашел подходящего примера.

Я видел, как кто-то говорил, что пакет IdentityServer4.AccessTokenValidation NuGet может работать с IdentityServer3, но единственный пример, который я нашел, был с простой проверкой подлинности JWT, не допускающей неявный поток входа пользователя.

Следовательно, я использовал стандартные библиотеки ASP.NET Core для настройки openidconnect, а затем мне нужно настроить код, чтобы он заработал.

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

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    app.UseMvc();
}

public void ConfigureServices(IServiceCollection services)
{
    // Without this, I get "Correlation failed." error from Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddAuthentication(o => {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    }).AddCookie().AddOpenIdConnect(o =>
    {
        o.Authority = "https://myidentityserver3.myfirm.com";
        o.ClientId = "myidentityserver3clientname";
        o.SignedOutRedirectUri = "https://localhost:50011/signout";

        o.ResponseType = "id_token token";
        o.SaveTokens = true;
        o.Scope.Add("openid");
        o.Scope.Add("roles");
        o.Scope.Add("profile");
        o.Scope.Add("customrequiredscopeforapi");
        o.GetClaimsFromUserInfoEndpoint = false;

        {
            var old = o.Events.OnTokenValidated;
            o.Events.OnTokenValidated = async ctx =>
            {
                if (old != null) await old(ctx);
                var token = MyCustomAuthUtils.ParseBearerToken(ctx.ProtocolMessage.AccessToken);
                foreach (var scope in token.Scopes)
                {
                    ctx.Principal.AddIdentity(new ClaimsIdentity(new[] { new Claim("Scope", scope) }));
                }
                // Our controllers need access token to call other web api's, so putting it here.
                // Not sure if that is a good way to do it.
                ctx.Principal.AddIdentity(new ClaimsIdentity(new[] { new Claim("access_token", ctx.ProtocolMessage.AccessToken) }));
            };
        }
    });

    var mvcBuilder = services.AddMvc(o =>
    {
        o.Filters.Add(new AuthorizeFilter(ScopePolicy.Create("customrequiredscopeforapi")));
    });
    services.AddAuthorization();
}

person Bjarne    schedule 25.07.2019    source источник


Ответы (1)


Во-первых, вам не нужно вручную декодировать токен доступа, просто используйте ctx.SecurityToken.Claims в событии OnTokenValidated, чтобы получить все утверждения, включенные в токен.

Я не уверен, почему вам нужно использовать scope для определения разрешения. Параметр области действия в конвейере, совместимом с OIDC, определяет:

  • Разрешения, которые авторизованное приложение должно иметь для данного сервера ресурсов
  • Какие стандартные утверждения профиля должны быть включены в токен идентификатора (если пользователь соглашается предоставить эту информацию приложению)

Вы можете использовать role, чтобы определить, может ли текущий пользователь, вошедший в систему, получить доступ к защищенному ресурсу. А промежуточное ПО OpenID Connect поможет сопоставить принцип role утверждения с требованием.

person Nan Yu    schedule 26.07.2019
comment
Я ожидал найти области видимости и в качестве утверждений, но их нет ни там, ни в ctx.SecurityToken, поэтому, чтобы заставить Microsoft.AspNetCore.Authorization.ScopePolicy работать, я не нашел другого способа, кроме как добавить их вручную. Может быть, мне не хватает какой-то настройки, чтобы они по умолчанию включались в качестве утверждений. То, почему люди здесь решили использовать области для ограничения доступа, немного неясно, и их больше нет. Возможно, мы можем обойтись только ролями, но я не хочу менять это, чтобы переместить код в .NET Core, если вышеописанного обходного пути достаточно. - person Bjarne; 19.08.2019