Base solution for your next web application
Open Closed

set tenant Session #6269


User avatar
0
BobIngham created

I can find no way of passing AbpSession.TenantId to my own AuditingStore implementation. As background I must point out that the call is coming from a copy of TokenAuthController which is used to handle the vagaries of logins from an Ionic app. The app passes tenantId in every call to the system. When a user uses incorrect credentials to sign in I need the audit log to capture tenantId but my efforts so far have been unsuccessful. Let me explain...

The app connects to AppTokenAuthController.AppAuthenticate (my own copy of TokenAuthController.Authenticate) . I wrap my code in the following use block:

using (_unitOfWorkManager.Current.SetTenantId(model.TenantId))

and I call:

var loginResult = await GetLoginResultAsync(
    model.UserNameOrEmailAddress,
    model.Password,
    await GetTenancyNameFromTenantId(model.TenantId)
);

The call is unsuccessful because of incorrect credentials and AuditingStore.SaveAsync() is called. At this stage AbpSession is null. The result is that the audit log gets written to the audit log for the host. Bugger. AuditingStore is in the Core project. My AppTokenAuthController is in the Web.Core project, is there any reason why session is not being persisted? How do I set it in AppTokenAuthController? I have tried the following to no avail:

AbpSession.Use(model.TenantId, null);

Any suggestions gratefully received.


6 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    The simplest solution: The application sets the TenantId at the same time each time the system is called. How it is set up depends on how you determine the current tenant. For example, set the HTTP request header: Abp.TenantId

    https://aspnetboilerplate.com/Pages/Documents/Multi-Tenancy#determining-current-tenant

  • User Avatar
    0
    BobIngham created

    Are you saying that I should set some value in the http header request? Can someone show me some code on how to do that?

  • User Avatar
    0
    ryancyq created
    Support Team

    When a user is not logged in, Abp can use HTTP header to determine the current tenant.

    You will need to pass Abp.TenantId when calling the API from your ionic app

    The document linked above contains the sample.

  • User Avatar
    0
    BobIngham created

    @ryancyq, thanks. here is my authorization interceptor for the angular app:

    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
    
      constructor(private storage: Storage) { }
    
      intercept(req: HttpRequest<any>, next: HttpHandler) {
        // Get the auth token from the service.
        return Observable
          .fromPromise(this.storage.get(TOKEN_KEY))
          .flatMap((token) => {
            // Clone the request and replace the original headers with
            // cloned headers, updated with the authorization.
            const authReq = req.clone({
              headers: req.headers
                .set('Content-Type', 'application/json')
                .set('Authorization', `Bearer ${token}`)
            });
            // send cloned request with header to the next handler.
            return next.handle(authReq);
          })
      }
    

    Everyone keeps telling me to set Abp.TenantId in the HTTP header and then directing me to a section in the documentation which tells me how the system then gets this value. My tenant id is held in app storage, the question is how do I SET it in the above? And, on the server why doesn't this work?

    using (_unitOfWorkManager.Current.SetTenantId(model.TenantId))
    

    And, this?

    AbpSession.Use(model.TenantId, null);
    

    It seems like a lot of work, having to add to the http header, why is not possible to set it on the server?

    Cheers, Bob

  • User Avatar
    0
    BobIngham created

    For anyone interested this was the solution though I still can't see why I can't set the session on the server....

    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
      tenant: Tenant;
    
      constructor(private storage: Storage) { 
        this.storage.get(TENANT_KEY)
        .then((data) => {
          this.tenant = JSON.parse(data);
        });
      }
    
      intercept(req: HttpRequest<any>, next: HttpHandler) {
        //Get the auth token from the service.
        return Observable
          .fromPromise(this.storage.get(TOKEN_KEY))
          .flatMap((token) => {
            // Clone the request and replace the original headers with
            // cloned headers, updated with the authorization.
            const authReq = req.clone({
              headers: req.headers
                .set('Content-Type', 'application/json')
                .set('Authorization', `Bearer ${token}`)
                .set('Abp.TenantId', this.tenant.tenantId.toString())
            });
            // send cloned request with header to the next handler.
            return next.handle(authReq);
          })
      }
    
  • User Avatar
    0
    ryancyq created
    Support Team

    Its by design, see https://github.com/aspnetboilerplate/aspnetboilerplate/blob/50bed1a6645ed2cdf1627f56fd32ebcac91f15d6/src/Abp.ZeroCore/Authorization/AbpLoginManager.cs#L141-L162