Identity Server 4 | MVC | Установить пользователя в контексте с помощью RequestPasswordTokenAsync - PullRequest
0 голосов
/ 14 апреля 2020

Прежде всего - я проверяю в Google и переполнение стека 2 дня .... Я нашел тысячи примеров и учебных пособий, у которых все еще не хватает точки, и у меня нет полной картинки в голове.

Итак:

Моя архитектура:

1) Сервер идентификации 2) 5 +/- MVC веб-сайтов (например, веб-сайт Production, глобальный администратор, служба поддержки и т. Д. c ...) (которые были защищены сервером идентификации) 3) Десятки микросервисов (которые были защищены сервером идентификации)

Сейчас - Что я не до конца понимаю:

1) Логин: сейчас я настроить поток перенаправления. Я имею в виду .... на веб-сайте я устанавливаю Identity Server как:

 services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = "https://localhost:44396";
                options.RequireHttpsMetadata = true;

                options.ClientId = "<<Here is client ID>>";
                options.ClientSecret = "<<HERE IS PASSWORD>>";
                options.ResponseType = "code id_token";

                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Add("api1.read");
                options.Scope.Add("offline_access");
            });

И

 app.UseHttpsRedirection();

            app.UseAuthentication();

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

Теперь, если пользователь пытается открыть страницу с атрибутом Autorize - пользователь перенаправляет на войдите на сервер идентификации и вернитесь на защищенную страницу. Все работает хорошо.

Но ....

1) Я хочу войти на страницу MVC. Без перенаправления на Identity Server. Я проверил inte rnet и обнаружил, что мне нужно использовать identityserver resource owner password flow

Затем я устанавливаю IdentityServer как:

 new Client {
                    ClientId = "myclient",
                    ClientName = "My first client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,// GrantTypes.HybridAndClientCredentials,
                    ClientSecrets = new List<Secret> { new Secret("superSecretPassword".Sha256())},
                    AllowedScopes = new List<string> { "openid", "profile", "api1.read", IdentityServerConstants.StandardScopes.Email},
                    AllowOfflineAccess = true,
                    RedirectUris = { "https://localhost:44321/signin-oidc" },
                    RequireConsent = false
                 },

И в My MVC я могу получить токен:

public static async Task HandleToken(this HttpClient client, string authority, string clientId, string secret, string apiName)
        {

            var accessToken = await client.GetRefreshTokenAsync(authority, clientId, secret, apiName);
            client.SetBearerToken(accessToken);
        }

        private static async Task<string> GetRefreshTokenAsync(this HttpClient client, string authority, string clientId, string secret, string apiName)
        {
            var disco = await client.GetDiscoveryDocumentAsync(authority);
            if (disco.IsError) throw new Exception(disco.Error);

            var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                UserName = "<<HERE IS USERNAME>>",
                Password = "<<HERE IS PASSWORD>>",
                Address = disco.TokenEndpoint,
                ClientId = clientId,
                ClientSecret = secret,
                Scope = apiName
            });




 var user_info = await client.GetUserInfoAsync(new UserInfoRequest() { Address = disco.UserInfoEndpoint, Token = tokenResponse.AccessToken });

Here I have all user claims and Now I want set them in Controller => User




                if (!tokenResponse.IsError) return tokenResponse.AccessToken;
                return null;
            }

Теперь я получаю токен ..... Хорошо ........., но

2 Вопросы:

1) Как мне установить личность пользователя внутри Controller.User (ClaimsPrincipal)?

**** ОБНОВЛЕНИЕ Я нашел одно решение

Я могу использовать HttpContext.SignInAsync и после того, как я получил токен и информацию пользователя из кода выше - я могу войдите в мой проект Web MVC и настройте заявки пользователей вручную. Если это хороший подход?

2) Все манипуляции с данными профиля пользователя, такими как ChangePassword, Update FirstName, LastName и т. Д. c ... Как мне это сделать ?? Создать микросервис для членства в удостоверении?

PS - В IdentityServer я использую Asp Удостоверение:

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

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

            var builder = services.AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                })
                .AddInMemoryIdentityResources(Config.Ids)
                .AddInMemoryApiResources(Config.Apis)
                .AddInMemoryClients(Config.Clients)
                .AddAspNetIdentity<ApplicationUser>();

И последний вопрос:

Если я хочу использовать DynamoDB как пользовательский магазин - тогда мне нужно собрать по кастомному Identity Provider? (Исправить ??)

Я нашел это решение в github, и мне просто нужно обновить до Asp Core 3.1

https://github.com/c0achmcguirk/AspNetIdentity_DynamoDB

1 Ответ

0 голосов
/ 14 апреля 2020

Для первого вопроса вам просто нужно настроить свой API для Identity Server, после чего он будет заполнен автоматически, когда клиент сделает правильный запрос. (который включает в себя его токен доступа)

Пример конфигурации API

public void ConfigureServices(IServiceCollection services)
{
  services.AddControllers();
  services.AddCors(r => r.AddDefaultPolicy(o =>
                                           o.AllowAnyOrigin()
                                           .AllowAnyMethod()
                                           .AllowAnyHeader()));
  services.AddAuthentication()
           .AddJwtBearer(options =>
                        {
                          options.Audience = "apix"; // this apis scope
                          options.Authority = "http://localhost:5000"; // Identity server url                                                
                         });

  services.AddAuthorization(options =>
  {
     options.DefaultPolicy =
                     new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser()
                    .Build();
            });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

          // ...
            app.UseCors();

            app.UseAuthentication();
            app.UseAuthorization();

          // ...
        }

И вам также необходимо украсить ваш метод API с помощью атрибута [Authorize].

По второму вопросу это вопрос предпочтения. Существует шаблон с именем QuickStart, который включает в себя пользовательские операции с IdentityServer4, который обрабатывает это MVC способом. Вы также можете создавать веб-API и выставлять их. И вам может не понадобиться создавать отдельный микросервис для этого, поскольку IdentityServer сам по себе является веб-приложением.

В последнем вопросе люди обычно модифицируют старые репозитории, чтобы они работали с DynamoDb. Вот так one

Редактировать: Для вопроса How to set up the MVC to set User Claims after ResourceOwner flow login

Вам необходимо внедрить службу IProfileService и зарегистрировать ее в автозагрузке. , (IdentityServer)

public async  Task GetProfileDataAsync(ProfileDataRequestContext context)
{
  var subject = context.Subject;
  var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
  var user = await _userManager.FindByIdAsync(subjectId); 
  var claims = GetClaimsFromUser(user,context.Caller); // here is the magic method arranges claims according to user and caller
  context.IssuedClaims = claims.ToList();
}
...