Open Closed

Impersonation with TokenAuth #7470


0
mightyit created

I am writing a utility that allows a host user to do batch loading of data on behalf of a tenant, via our API. For this, I have generated a .Net Core 2.2 client with NSwag, based on the generated swagger docs. This of course means that we use TokenAuth for authentication.

I am getting stuck with impersonation though. I am able to get an impersonation token, but get stuck when I want to authenticate as the impersonated user & tenant.

Here is my code through which I invoke the generated TokenAuth client:

// Get the impersonation token...
var accountClient = new AccountClient(_baseUri, _httpClient);
var impersonationToken = (await accountClient.ImpersonateAsync(new ImpersonateInput
{
    TenantId = selectedTenantId,
    UserId = selectedUserId,
})).ImpersonationToken;
            
var tokenAuthClient = new TokenAuthClient(_baseUri, _httpClient);            
var impersonatedAccessToken =
    (await tokenAuthClient.ImpersonatedAuthenticateAsync(impersonationToken)).AccessToken; // <== This call is generating Http Error 500

In my Web.Core project, the ImpersonatedAuthenticate method is being called on TokenAuthController as follows:

[HttpPost]
public async Task<ImpersonatedAuthenticateResultModel> ImpersonatedAuthenticate(string impersonationToken)
{
    var result = await _impersonationManager.GetImpersonatedUserAndIdentity(impersonationToken); <== This line is generating the exception
    var accessToken = CreateAccessToken(await CreateJwtClaims(result.Identity, result.User));

    return new ImpersonatedAuthenticateResultModel
    {
        AccessToken = accessToken,
        EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
        ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds
    };
}

Here is the exception I am getting: image.png image.png

Further details:

  • I'm using the AspNetCore + JQuery version of the framework
  • Abp.AspNetZeroCore 1.2.2
  • Abp.ZeroCore 4.4.0

6 Answer(s)
  • 0
    ismcagdas created

    Hi,

    Have you tried adding "Abp.TenantId" Header with the value of "selectedTenantId" to the tokenAuthClient's request headers ?

  • 0
    mightyit created

    Yes, but I'm not sure whether I am doing it right. Here is the code I am using for this just before calling tokenAuthClient.ImpersonatedAuthenticateAsync (and still getting the same error as mentioned above):

    _httpClient.DefaultRequestHeaders.Remove("Abp.TenantId");
    _httpClient.DefaultRequestHeaders.Add("Abp.TenantId",selectedTenantId.ToString());
    

    I have also tried to modify the header for the HttpRequestMessage inside the generated client as follows,with the same outcome:

    request_.Headers.Remove("Abp.TenantId");
    request_.Headers.Add("Abp.TenantId", selectedTenantId?.ToString());
    
  • 0
    mightyit created

    @ismcagdas @ryancyq

    See below screenshot which confirms that the Abp.TenantId header is set correctly.

    image.png

    Also, confirming that setting the Abp.TenantId header does not updateAbpSession.TenantId, and thus causes the CheckCurrentTenant check to fail and throw the mentioned exception.

    image.png

    So what would cause the AbpSession.TenantId update to fail?

  • 0
    ryancyq created

    Hi, can you share the details of session and request?

    Also, confirming that setting the Abp.TenantId header does not update AbpSession.TenantId

    do you mean "even if Abp.TenantId header is present in the http request, AbpSession.TenantId does not have the given tenant id"?

    can you share the request header payload when you call ImpersonatedAuthenticate()

  • 0
    mightyit created

    Yes, AbpSession.TenantId remains null, even though the Abp.TenantId request header was set to 2.

    Here is the session object, serialized as JSON:

    {
      "UserId": 1,
      "TenantId": null,
      "ImpersonatorUserId": null,
      "ImpersonatorTenantId": null,
      "MultiTenancy": {
        "IsEnabled": true,
        "IgnoreFeatureCheckForHostUsers": false,
        "Resolvers": [
          "Abp.AspNetCore.MultiTenancy.DomainTenantResolveContributor, Abp.AspNetCore, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null",
          "Abp.AspNetCore.MultiTenancy.HttpHeaderTenantResolveContributor, Abp.AspNetCore, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null",
          "Abp.AspNetCore.MultiTenancy.HttpCookieTenantResolveContributor, Abp.AspNetCore, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null"
        ],
        "TenantIdResolveKey": "Abp.TenantId"
      },
      "MultiTenancySide": 2
    }
    

    Here is the request.Headers object, serialized as JSON:

    {
      "Connection": [
        "Keep-Alive"
      ],
      "Content-Type": [
        "application/json; charset=utf-8"
      ],
      "Accept": [
        "application/json"
      ],
      "Authorization": [
        "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwibmFtZSI6ImFkbWluIiwiQXNwTmV0LklkZW50aXR5LlNlY3VyaXR5U3RhbXAiOiJRNUpOWlg2NEg0QlZEV1pFVTVCV0hST1QyVzc3UEg1MyIsInJvbGUiOiJBZG1pbiIsImp0aSI6IjJkNmE1YWRmLTVlYjYtNGU3Yy05OTA3LTExZDk3NzFkNjgwZCIsImlhdCI6MTU2NTc2OTY3MywidG9rZW5fdmFsaWRpdHlfa2V5IjoiOGQyNDVhYzctZGM1MC00ZmU1LWEwMzgtNWJjMWIwN2Q1NjM4IiwidXNlcl9pZGVudGlmaWVyIjoiMSIsIm5iZiI6MTU2NTc2OTY3MywiZXhwIjoxNTY1ODU2MDczLCJpc3MiOiJaZW5EZXRlY3QiLCJhdWQiOiJaZW5EZXRlY3QifQ.LG1lcqgRpjmG_Gmh13zwbj-nqejDNAtij5b9HKeU_60"
      ],
      "Host": [
        "localhost:62114"
      ],
      "Content-Length": [
        "0"
      ],
      "Abp.TenantId": [
        "2"
      ],
      "MS-ASPNETCORE-TOKEN": [
        "359ecd4d-4df5-46bd-95b3-630aae1dddbb"
      ],
      "X-Original-Proto": [
        "http"
      ],
      "X-Original-For": [
        "127.0.0.1:58003"
      ]
    }
    
  • 0
    mightyit created

    I was able to figure out what the issue was.

    I was calling ImpersonatedAuthenticate with an HttpClient for which the bearer token was already set (by calling _httpClient.SetBearerToken(bearerToken);) during authentication. It seems that, if the bearertoken is set for your call, it will resolve the AbpSession.TenantId to the tenantid to which the bearer token applied.

    The fix was to new up the HttpClient, so that there is no bearer token set on the subsequent call to ``ImpersonatedAuthenticate`.