簡體   English   中英

在IdentityServer4中從ChallengeResult()發出新聲明

[英]Issue a new claim from ChallengeResult() in IdentityServer4

我們目前有一個需要多租戶的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 ”端點,然后返回到我的應用程序。 我的IdentityServer中有IProfileService的實現,但無法訪問以前發布的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;
    }

然后我的問題是:在打/ connect / authorize時如何截獲或做一些內部邏輯? 也許我正在以錯誤的方式進行操作?

...但是當用戶選擇更改租戶時,我開始遇到有關用戶試圖訪問資源的租戶上下文的問題。

這真的不是問題。 安全是關於保護資源。 選擇租戶不會更改用戶的授權。 盡管當前未選擇,但該用戶仍然有權使用為此用戶配置的所有租戶。

因此,將tenantid作為參數添加到api調用中,然后驗證是否允許用戶使用此租戶是完全可以的。 不要將授權與過濾混淆。

從Api的角度來看,唯一的上下文是客戶端提供和維護的上下文。

客戶端可以通過多種方式跟蹤當前租戶:cookie,會話,內存中的路由,例如/tenant/id/tenant.domain.com

由於我在Identity Server中托管了一些API函數來進行一些內部用戶修改,因此我需要將租戶反映在令牌中,以便可以驗證對此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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM