Создайте новую заявку от ChallengeResult () в IdentityServer4 - PullRequest
0 голосов
/ 16 мая 2019

В настоящее время у нас есть API, который требует многопользовательской аренды.После успешного входа в систему мы выдаем всех доступных арендаторов пользователю, но когда пользователь решает сменить арендатора, я начинаю сталкиваться с проблемами, в которых контекст клиента пытается получить доступ к ресурсу.

Я думал, что при смене арендатора я могу просто предложить ChallengeResult(), а затем в IdentityServer обработать это, чтобы проверить, к какому арендатору пользователь хочет получить доступ, а затем выдать новый токен с утверждением «ChosenTenant» (или что-то в этом роде).Примерно так:

            var authProps = new AuthenticationProperties();
            authProps.SetString("CurrentTenantId", response.Result.Id.ToString());
            authProps.RedirectUri = "/#home";
            return new ChallengeResult(authProps);

Однако на самом деле это не работает, поскольку ChallengeResult просто попадает в конечную точку IdentityServers " / connect / authorize " и затем возвращается в мое приложение.У меня есть реализация IProfileService в нашем IdentityServer, но я не могу получить доступ к ранее выданным AuthenticationProperties.

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.FindFirst("sub").Value;
        context.IssuedClaims = await _userStore.GetClaimsForUser(sub, context.RequestedClaimTypes, context.Client.ClientId);
        return;
    }

Тогда у меня возникает вопрос: как я могу перехватить или сделать некоторую собственную внутреннюю логику при нажатии /подключить / авторизацию ?Или, может быть, я поступаю неправильно?

Ответы [ 2 ]

2 голосов
/ 17 мая 2019

... но когда пользователь решает сменить владельца, я начинаю сталкиваться с проблемами, в которых контекст клиента пытается получить доступ к ресурсу.

Этона самом деле не проблема.Безопасность - это защита ресурса.Выбор арендатора не меняет авторизацию пользователя.Хотя в настоящее время он не выбран, пользователь остается авторизованным для всех арендаторов, которые настроены для этого пользователя.

Так что вполне нормально добавить tenantid в качестве параметра к вызову API и затем проверить, разрешено ли пользователюдля этого арендатора.Не путайте авторизацию с фильтрацией.

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

Клиент может отслеживать текущийарендатор различными способами: cookie, сеанс, в памяти, маршрут, например /tenant/id/ или tenant.domain.com.

0 голосов
/ 21 мая 2019

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

Я управлял им с помощьюреализация нового пользовательского гранта на Identity Server, который просматривает необработанный контекст и извлекает запрошенный клиент.

 public class ActAsGrantValidator : IExtensionGrantValidator
    {
        private readonly ITokenValidator _tokenValidator;
        private readonly ITenantStore _tenantStore;
        public ActAsGrantValidator(ITokenValidator tokenValidator, ITenantStore tenantStore)
        {
            _tokenValidator = tokenValidator;
            _tenantStore = tenantStore;
        }
        public string GrantType => "act-as";

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            var userToken = context.Request.Raw.Get("accessToken");
            var tenant = context.Request.Raw.Get("chosenTenant");

            if (string.IsNullOrEmpty(userToken))
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
                return;
            }

            var result = await _tokenValidator.ValidateAccessTokenAsync(userToken);
            if (result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
                return;
            }
            // logic to validate the user and tenant
            // ..
            // issue a new claimsprincipal to reflect the new "persona"
            var claims = result.Claims.ToList();
            claims.RemoveAll(p => p.Type == "role");
            claims.RemoveAll(p => p.Type == "chosentenant");
            claims.Add(new Claim("chosentenant", tenant));
            var identity = new ClaimsIdentity(claims);
            var principal = new ClaimsPrincipal(identity);
            context.Result = new GrantValidationResult(principal);
            return;
       }
    }

Затем в контроллере из API я вызываю пользовательский грант:

            // access token from httpcontext, chosenTenant from controller
            var payload = new
            {
                accessToken,
                chosenTenant
            };
            var tokenClient = new TokenClient($"{_identityServerSettings.Authority}/connect/token",
                _identityServerSettings.ClientId, _identityServerSettings.ClientSecret);
            var response = await tokenClient.RequestCustomGrantAsync("act-as", "profile openid", payload);

А затем выполните повторную регистрацию с утверждениями из нового токена доступа и вызовом конечной точки информации пользователя:

            var authProperties = new AuthenticationProperties();
            authProperties.StoreTokens(tokens);
            authProperties.ExpiresUtc = DateTime.Now.AddHours(9);
            var identity = new ClaimsIdentity(claims, "Cookies");
            var principal = new ClaimsPrincipal(identity);
            await _httpContext.HttpContext.SignInAsync("Cookies", principal, authProperties);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...