Как передать утверждения из ответа WS-Federation в Identity

Я довольно новичок в .net core 2.1, я подумал, что если я собираюсь построить/перестроить проект, я мог бы также использовать новую вещь. Итак, я некоторое время боролся с основной идентификацией ASP.NET — документация определенно оставляет желать лучшего.

Я успешно внедрил аутентификацию - я перенаправляюсь в свою ADFS и обратно, и пользователи входят в систему.

Потом стал смотреть через Авторизацию. Сначала я пробовал на основе ролей, но я читал, что роли мало используются, и, кроме того, я не мог понять, почему роли, назначенные пользователям, не проходят проверки авторизации (ClaimsPrincipal.IsInRole и политики для бритвенных страниц).

Я решил использовать авторизацию на основе утверждений, полагая, что могу использовать утверждения, предоставленные через WS-Federation. строки - однако я не вижу ни одного из этих утверждений в ClaimsPrincipal (HttpContext.User) после входа в систему.

Прервав поток во время входа в систему, я вижу этот вызов

_signInManager.GetExternalLoginInfoAsync()

определенно получает ожидаемые требования от ADFS, но явно не вникает в то, что происходит после этого.

Как я уже сказал, я довольно туманно понимаю, как это работает внутри компании, и TBH, я действительно не хочу слишком глубоко разбираться в мельчайших подробностях, мне просто нужно знать, что я могу авторизоваться на основе групповых требований из ADFS.

Мой проект является более или менее стандартным веб-сайтом asp.net core 2.1 по умолчанию с выбранной авторизацией отдельных учетных записей, затем я добавил модификации для WS-Federation, и жюри подстроило действие входа в систему, чтобы перенаправить прямо в ADFS, а не запрашивать для Это.

Пожалуйста, дайте мне знать, если вам нужно разъяснение, но суть его такова:

Как мне получить групповые утверждения из ADFS в ASP.NET Core Identity, чтобы я мог ссылаться на них следующим образом:

services.AddAuthorization(options =>
            {
                options.AddPolicy("RequireAdminGroup", policy =>
                    policy.RequireClaim("Group", "AD Admin Group Name")
                );
            });

Кроме того, не стесняйтесь указывать мне на любой ответ, который я пропустил. Целый день читал документы и искал в Интернете, а сегодня совсем не продвинулся!


person Kruft    schedule 06.07.2018    source источник
comment
На самом деле у меня нет решения для моего собственного вопроса, но вместо этого я полностью проигнорировал функцию ASP.NET Core Identity и напрямую использовал Ws-Federation, как указано в документация. Это позволило мне использовать User.Identity.Claims, который заполняется вызовом ADFS с любыми утверждениями, которые я настроил (в данном случае, группами).   -  person Kruft    schedule 19.07.2018
comment
Не могли бы вы опубликовать решение, которое вы придумали, в качестве ответа? Я пытаюсь сделать то же самое и пока безуспешно. В частности, я не могу получить доступ к утверждениям после проверки подлинности и не знаю, что я делаю неправильно.   -  person Savantes    schedule 12.09.2018
comment
Я реализовал почти точно то, что есть в документации, на которую я ссылался в своем последнем комментарии. Я добавлю «ответ», чтобы изложить его немного лучше.   -  person Kruft    schedule 14.09.2018


Ответы (2)


Идентификация работает корректно. Вы просто неправильно обратились к претензиям. Попробуйте следующее внутри страницы Razor.

@inject UserManager<ApplicationUser> UserManager
@{

  var claims = await UserManager.GetClaimsAsync(await UserManager.GetUserAsync(User));
}

Для политик вы можете использовать класс ClaimTypes в Startup.cs, чтобы получить хорошо известные Claims Ex.:

policy.RequireClaim(ClaimTypes.WindowsAccountName));
person SmokingDax    schedule 28.11.2018
comment
Спасибо за ваш вклад. Это больше всего отвечает на мой первоначальный вопрос, хотя в итоге я пошел другим путем :) - person Kruft; 26.02.2019

Чтобы добавить дополнительную информацию, вот как я обошел проблему. Функция ASP.NET Core Identity была намного более тяжелой, чем мне хотелось/необходимо, и документации не хватало. Он также более или менее похитил утверждения из источника федерации, а затем заменил их своими собственными значениями. Поскольку мне нужно было только получить групповые утверждения, отправленные ADFS, и использовать их в политиках, я сделал что-то вроде:

Удалите ВСЕ ссылки на ASP.NET Core Identity. Я не помню, что они пришли мне в голову, но их должно быть довольно очевидно, чтобы найти.

services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
        })
        .AddWsFederation(options =>
        {
            options.MetadataAddress = "https://federationservicesurl/";
            options.Wtrealm = "realmname";
            options.SignOutWreply = "https://signoutaddress if you want it";

        })
        .AddCookie(options =>
        {
            options.AccessDeniedPath = "/AccessDenied"; // If you need one
            options.ExpireTimeSpan = TimeSpan.FromMinutes(20); // Or from config
        });

Это добавляет параметры аутентификации, промежуточное ПО ws-federation и файлы cookie для его работы. Затем вы добавляете авторизацию:

            services.AddAuthorization(options =>
        {
            // Any Admins
            options.AddPolicy("RequireGroup", policy =>
                policy.RequireClaim("http://schemas.xmlsoap.org/claims/Group", "Group 1", "Group 2")
            );

            //... more policies
        }

и, наконец, вы можете использовать эти политики. В моем случае я использую Razor Pages, поэтому у меня просто диапазон AuthorizeFolder/AuthorizePage.

services.AddRazorPagesOptions(options =>
        {
            options.Conventions.AllowAnonymousToPage("/AccessDenied");
            options.Conventions.AllowAnonymousToPage("/SignedOut");
            options.Conventions.AllowAnonymousToPage("/SignOut");

            options.Conventions.AuthorizeFolder("/Network", "RequireGroup");
            options.Conventions.AuthorizePage("/About", "RequireGroup");

            // ... more directives
        })

И это просто работает. Если вы хотите также скрыть фрагменты интерфейса, вы можете сделать это. Опять же, я использую Razor, а не чистый MVC, поэтому я не уверен, как реализовать это в MVC, но я делаю это в своем файле cshtml вверху:

@inject IAuthorizationService AuthorizationService
@{
    var requiregroup= (await AuthorizationService.AuthorizeAsync(User, "RequireGroup"));
}

а потом:

@if (requiregroup.Succeeded)
{
    <div>some content that requires the policy RequireGroup</div>
}

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

И вот как я это реализовал. Если у кого-то есть какие-либо отзывы, чтобы сказать мне, что я сделал что-то ужасно неправильное, я открыт для этого :)

person Kruft    schedule 13.09.2018
comment
Я не буду здесь описывать, как настроить WS-Federation в ADFS для фактической отправки утверждений. Это не совсем в рамках. Впрочем, это не так уж сложно — просто погуглите. - person Kruft; 14.09.2018