Как сделать авторизацию на основе ролей с использованием identityserver4 для архитектуры микросервисов? - PullRequest
0 голосов
/ 10 июня 2019

Предыстория:
Я разрабатываю аутентификацию и авторизацию для микросервисов с использованием IdentityServer4, но у меня проблема с авторизацией. У меня есть две службы:
- сервис с identityserver4, это мой сервис аутентификации
- тестовый проект MVC

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

Проблемная ситуация:
1. У пользователя нет токена авторизации. Попробуйте открыть страницу с атрибутом [Authorize(Roles = "Admin")] на сайте MVC и перенаправить на страницу службы аутентификации. 2. Пользователь вводит логин и пароль.
3. Получил токен с Role = Admin, перенаправьте обратно на сайт MVC на сервисе аутентификации.
4. Страница открыта для пользователя, потому что у него была роль администратора.
5. Удалите пользователя из роли администратора в службе аутентификации.
6. Перезагрузите страницу и страница снова открылась нормально для этого пользователя, и это правильно, потому что в токене у него была роль администратора.

Вопрос: Как я могу актуализировать токен после изменения ролей или утверждений на стороне службы аутентификации?

Конфигурация IdentityServer:

public static IEnumerable<Client> GetClients()
        {
            return new Client[]
            {
                new Client
                {
                    ClientId = "Epp.Web.Mvc",
                    ClientName = "Единый Портал Потребителей",
                    AllowedGrantTypes = new List<string>{GrantType.Hybrid},
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256())
                    },
                    RequireConsent = false,
                    AllowAccessTokensViaBrowser = true,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AlwaysSendClientClaims = true,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "epp",
                        "roles"
                    },
                    RedirectUris = new List<string>
                    {
                        "http://localhost:5002/signin-oidc",
                        "https://localhost:5003/signin-oidc"
                    },
                    PostLogoutRedirectUris = new List<string>{ "http://localhost:5002/signout-callback-oidc" },
                    AccessTokenLifetime = 60 * 10 
                }
            };
        }

MVC Запуск:

services.AddAuthentication(options =>
                {
                    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = "oidc";
                })
                .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromHours(2))
                .AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                        options.Authority = "https://localhost:5001";
                        options.ClientId = "Epp.Web.Mvc";
                        options.ResponseType = "code id_token";
                        options.ClientSecret = "secret";

                        options.GetClaimsFromUserInfoEndpoint = true;
                        options.SaveTokens = true;
                        options.RequireHttpsMetadata = false;


                        options.Scope.Add(IdentityServerConstants.StandardScopes.OpenId);
                        options.Scope.Add(IdentityServerConstants.StandardScopes.Profile);
                        options.Scope.Add("epp");
                        options.Scope.Add("roles");
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            NameClaimType = "name",
                            RoleClaimType = "role"
                        };
                    });

Ответы [ 2 ]

1 голос
/ 10 июня 2019

На самом деле речь идет не об OpenId-Connect или сервере идентификации.Это более общий вопрос о том, как долго хранить некоторые кэшированные (защищенные) данные.JWT является неизменным по своему дизайну, поэтому вы можете рассматривать его как своего рода кеш.Когда срок действия кэшированного элемента (или jwt) истекает, мы получаем новый.Таким образом, единственное решение состоит в том, чтобы установить достаточно короткий срок действия для вашего токена-носителя и использовать обновленный, чтобы «актуализировать» канал-носитель.

Лично я не вижу, как может помочь замена ролей на области действия для данной услуги .Это немного другое.Мы можем более или менее постоянно определять, что application1 имеет доступ к service1.write scope и тем самым ограничивает All but application1' users доступ к API.Но что, если приложение универсально?Здесь нет ответа.

Другим предложением было использование эталонных токенов и аннулирование при необходимости.Ну, ты мог бы сделать.Но по умолчанию API кэширует результат проверки эталонного токена, так что ... Мы получаем ту же проблему в новом месте.

Что должно сработать, так это перенести авторизацию на основе ролей в каждый сервис, как предложила @VidmantasBlazevicius, но опять же внутри сервиса у вас, скорее всего, есть какой-то кэш, поэтому вам снова нужно подумать, как сделать его недействительным при необходимости.

0 голосов
/ 10 июня 2019

Я вижу 2 способа сделать это, как показано ниже,

  1. Вы можете ссылаться на поток токенов и аннулировать токен, когда происходят изменения в вашей роли / правах.Проверьте ссылку http://docs.identityserver.io/en/latest/topics/reference_tokens.html

  2. Или, как упоминалось @Vidmantas Blazevicius, переместите задание авторизации на основе ролей в соответствующую службу, а не ретранслируйте на сервере идентификации.

...