Проверка подлинности .Net Core 2 OpenID Connect и несколько удостоверений - PullRequest
0 голосов
/ 09 октября 2018

Я все еще изучаю Identity Framework и пытаюсь настроить аутентификацию в моем приложении .Net Core 2 MVC.Любые предложения приветствуются, поскольку я даже не уверен, что то, что я делаю, правильно.


У меня есть требование интегрировать провайдера идентификации OpenID Connect для аутентификации и использоватьвторичный источник данных для авторизации .Неудобно, что я не могу использовать какие-либо претензии от IdP OIDC, кроме претензии на имя.Остальные заявки пользователей должны поступать из вторичного источника данных (который подключен к Identity Framework через настраиваемый объект UserStore и User).

Я использую поставщика OpenId Connect для обработки аутентификации.Это работает нормально и дает мне первую личность (из которой я могу использовать только одну претензию).Моя путаница начинается, когда мне нужно получить второе удостоверение пользователя, добавить его к принципалу и установить его по умолчанию Identity.Этот второй Identity предоставляет все заявки пользователей, включая роль.

Я понимаю, что у меня есть структура удостоверений, что у меня должен быть один ClaimsPrincipal с двумя удостоверениями, чтобы я мог подключиться к остальной части Identity Framework,Однако с двумя удостоверениями по умолчанию ClaimsPrincipal автоматически выберет первое удостоверение (которое я не могу использовать), поэтому мне кажется, что я должен создать пользовательское ClaimsPrincipal и установить PrimaryIdentitySelectorтак что мой второй идентификатор является основным.

public class MyClaimsPrincipal : ClaimsPrincipal
{
    private static readonly Func<IEnumerable<ClaimsIdentity>, ClaimsIdentity> IdentitySelector = SelectPrimaryIdentity;

    /// <summary>
    /// This method iterates through the collection of ClaimsIdentities and chooses an identity as the primary.
    /// </summary>
    private static ClaimsIdentity SelectPrimaryIdentity(IEnumerable<ClaimsIdentity> identities)
    {
        // Find and return the second identity
    }
}

Как только я получаю проверенный токен из IIDP OIDC, я выбираю второй идентификатор, создаю новый MyClaimsPrincipal, добавляю два идентификатора к новому принципалу.После этого я не уверен, что делать с этим новым принципалом.

Я пытался зарегистрировать пользователя через SignInManager, явно настроив пользователя в контексте HTTP и используя промежуточное ПО для преобразованияClaimsPrincipals до MyClaimsPrincipals но все это, похоже, ничего не делает.Я думаю, что упускаю суть.

Некоторые конкретные вопросы:

  • Это лучший способ сделать это?Как правило, из-за этого все сложно понять, нахожусь ли я на правильном пути.
  • Как только я создал пользовательский принципал, как мне «установить» его в контекст HTTP, чтобыэто постоянно?
  • Как аутентификация Cookie работает с аутентификацией OpenId Connect?Похоже, что OIDC каким-то образом передает пользователя в проверку подлинности Cookie, и для работы проверки подлинности OIDC требуется добавление проверки подлинности cookie.

1 Ответ

0 голосов
/ 09 октября 2018

При использовании схемы OpenID Connect важно знать, что эта схема никогда не будет работать сама по себе.Практически в каждом примере, который вы можете найти, вы увидите его в сочетании со схемой cookie.Причина этого очень проста: OIDC предназначен для аутентификации пользователя с помощью внешнего поставщика аутентификации.Но эта аутентификация только временная.Чтобы сохранить его локально в вашем приложении, вам необходимо войти в систему вашего пользователя.Обычно это делается с помощью схемы аутентификации cookie (хотя это может быть сделано другими способами).

Поток аутентификации для приложения, которое использует OIDC и куки, обычно работает следующим образом:

  1. Пользователь обращается к вашему приложению.
  2. Аутентификация : Схема cookie, схема аутентификации по умолчанию, будет пытаться аутентифицировать пользователя.Если cookie не существует, обработчик вызовит аутентификацию.
  3. Задача : Схема OIDC, схема вызова по умолчанию, будет вызывать пользователя и перенаправлять навнешний поставщик аутентификации.
  4. Пользователь будет аутентифицироваться с внешним поставщиком аутентификации и будет перенаправлен обратно в приложение.
  5. Обратный вызов вызова : Схема OIDC примет ответот внешнего поставщика проверки подлинности завершите вызов и создайте принципал заявок.
  6. Вход : схема OIDC выполнит вход в этот принципал с помощью настроенной схемы входа (схема cookie)).
  7. Схема cookie-файлов будет регистрировать пользователя и создавать cookie-файл, который сохраняется в браузере пользователя.
  8. При последующем запросе к вашему приложению пользователь будет включать в себя действительный cookie-файл,таким образом, схема cookie может успешно аутентифицировать пользователя, не оспаривая схему OIDC.дюйма

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

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

Вы можете использовать TicketReceived событие для этой цели:

public void ConfigureServices(IServiceCollection services)
{
    // …

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
        .AddCookie()
        .AddOpenIdConnect(options =>
        {
            // …

            options.Events.OnTicketReceived = OnOpenIdConnectTicketReceived;
        });
}

public static Task OnOpenIdConnectTicketReceived(TicketReceivedContext context)
{
    if (context.Principal.Identity is ClaimsIdentity identity)
    {
        identity.AddClaim(new Claim("foo", "bar"));
    }

    return Task.CompletedTask;
}
...