.net Core Аутентификация только с WS-Fed - PullRequest
1 голос
/ 06 марта 2019

Мы добавляем новое базовое веб-приложение .net в существующую среду, центром которой является Identity Server 2 для аутентификации. При создании нового приложения у меня возникают проблемы с использованием существующей аутентификации.

Цель состоит в том, чтобы каждая страница в новом приложении требовала входа в систему. Новое приложение имеет несколько пользовательских таблиц, но для него не требуется база данных Identity по умолчанию (AspNetUsers и т. Д.), А также не требуются собственные диалоговые окна входа в систему (восстановление пароля и т. Д.).

Для этого я добавил следующее в наш файл Startup.cs в ConfigureServices ():

01:services.AddTransient<IUserStore<ApplicationUser>, E360UserStore<ApplicationUser>>();
02:services.AddTransient<IRoleStore<ApplicationRole<string>>, E360RoleStore<ApplicationRole<string>>>();
03:
04:var authenticationConfigSection = Configuration.GetSection("Authentication");
05:
06:services.AddAuthentication(/*"WsFederation"*/)
07:        .AddWsFederation(authenticationScheme: "WsFederation",
08:                         displayName: "Single Signin",
09:                         configureOptions: options =>
10:                         {
11:                             // MetadataAddress represents the Identity Server instance used to authenticate users.
12:                             options.MetadataAddress = authenticationConfigSection.GetValue<string>("MetadataAddress");
13:
14:                             // Wtrealm is the app's relying party identifier in the IS instance.
15:                             options.Wtrealm = authenticationConfigSection.GetValue<string>("Wtrealm");
16:
17:                             //options.SignInScheme = "WsFederation";
18:                         });
19:
20:services.AddMvc(config =>
21:                {
22:                    var policy = new AuthorizationPolicyBuilder(/*"WsFederation"*/)
23:                                 .RequireAuthenticatedUser()
24:                                 .Build();
25:
26:                    config.Filters.Add(new AuthorizeFilter(policy));
28:                })
29:        .AddJsonOptions(o => o.SerializerSettings.ContractResolver = new DefaultContractResolver())
30:        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

В результате выдается сообщение об ошибке: «Не указана схема аутентификации и не найден DefaultChallengeScheme». Итак, я пытаюсь раскомментировать три строки "WsFederation", по одной за раз.

Сначала я пытаюсь раскомментировать последний:

22:var policy = new AuthorizationPolicyBuilder("WsFederation")
23:             .RequireAuthenticatedUser()
24:             .Build();

Это приводит к аналогичной, но другой ошибке: «Не был указан AuthenticationScheme, и не найдено DefaultAuthenticateScheme».

Если я вместо этого раскомментирую одну из других строк (или обе):

06:services.AddAuthentication("WsFederation")    
17:options.SignInScheme = "WsFederation";

Это приводит к ошибке: «SignInScheme для удаленного обработчика аутентификации не может быть установлен на себя. Если он не был установлен явно, используется AuthenticationOptions.DefaultSignInScheme или DefaultScheme.»

Если я настрою приложение для «обычной» аутентификации, например:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

services.AddDefaultIdentity<ApplicationUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

Затем я получаю диалог входа в систему с кнопкой справа, помеченной «Единый вход», которая работает просто отлично. Заявки от входа в систему WsFederation сопоставляются с пользователями, созданными вручную в сгенерированной базе данных удостоверений.

Мое намерение с E360UserStore и E360RoleStore в новой модели состоит в том, чтобы сопоставить IdentityUser в FindByIdAsync () (я не смог проверить это):

public class ApplicationUser : IdentityUser
{
    public User User { get; set; }

    public ApplicationUser(User user)
    {
        base.Id = User.IdentityGuid.ToString("D");
        base.Email = user.Person.EmailAddress;
        base.NormalizedEmail = user.Person.EmailAddress.ToLowerInvariant();
        base.UserName = user.Username;
        base.NormalizedUserName = user.Username.ToLowerInvariant();
        base.EmailConfirmed = true;
        User = user;
    }
}

Кажется, я не могу найти секретный соус, который удаляет логин по умолчанию и вместо этого автоматически перенаправляет на логин Identity Server.

Спасибо за чтение!

Обновление:

@ Ритмис предположил, что мне не хватало определения файлов cookie, которые бы указывали на то, что приложение «вошло», что является отличным наблюдением, но я все еще не нашел ничего, так как не понимаю, как перейти от WS-Fed для куки-аутентификации (для идентификации текущего пользователя). Я изменил свой код ConfigureServices, как показано ниже, что заставляет программу немедленно перенаправлять на сервер идентификации, что идеально, и после входа в систему она перенаправляет обратно в конечную точку с поддержкой ws, которая затем перенаправляет обратно на начальную страницу. Все это хорошие новости, но на начальной странице пользователь все еще не видит, как он вошел в систему. Файл cookie создается, но я не вижу, как, где или если логин преобразуется из ws-feed в файл cookie? Я определил пользовательские классы IUserStore и IRoleStore, но они не используются или даже не создаются.

services.AddAuthentication(sharedOptions =>
                           {
                               sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                               sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                               sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
                           })
        .AddWsFederation(authenticationScheme: "WsFederation",
                         displayName: "Single Signin",
                         configureOptions: options =>
                                           {
                                               // MetadataAddress represents the Identity Server instance used to authenticate users.
                                               options.MetadataAddress = authenticationConfigSection.GetValue<string>("MetadataAddress");

                                               // Wtrealm is the app's relying party identifier in the IS instance.
                                               options.Wtrealm = authenticationConfigSection.GetValue<string>("Wtrealm");

                                               //options.SignInScheme = "WsFederation";
                                           })
        .AddCookie(options =>
                   {
                       options.Cookie.SameSite = SameSiteMode.None;
                       options.Cookie.Name = "AuthCookie";
                       options.AccessDeniedPath = "/error/accessdenied";
                   });

services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
services.AddTransient<IUserStore<ApplicationUser>, MyUserStore<ApplicationUser>>();
services.AddTransient<IRoleStore<ApplicationRole<string>>, MyRoleStore<ApplicationRole<string>>>();

1 Ответ

0 голосов
/ 19 марта 2019

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

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

...