Base solution for your next web application
Open Closed

Impersonation with TokenAuth #7470


User avatar
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:

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)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

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

  • User Avatar
    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());
    
  • User Avatar
    0
    mightyit created

    @ismcagdas @ryancyq

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

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

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

  • User Avatar
    0
    ryancyq created
    Support Team

    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()

  • User Avatar
    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"
      ]
    }
    
  • User Avatar
    1
    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`.