Tenant identification

Highlighted
Occasional Contributor

When creating an app in Hubspot, how do you identity the source and destination tenant when dealing with multi tenant environments? Any best practices?

Reply
0 Upvotes
12 Replies 12
Highlighted
Community Manager

Hi @rasmusfoged ,

 

I myself am not familiar with this topic but I wanted to tag in some top Community contributors here: @Kevin-C and @psdtohubspot , do you have any knowledge that you can share with @rasmusfoged ?

Highlighted
Occasional Contributor
We are really looking for a solution here.
Reply
0 Upvotes
Highlighted
HubSpot Moderator

Hey @rasmusfoged,

 

Just to clarify, by identifying the source of the tenant, do you mean the source of the contact creation? Or source of where that app was installed? 

 

Additionally, could you expand further on what do you mean by multi tenant? Does it mean this?

In a multi-tenant environment, each customer shares the software application along with a single database, so multiple people from the same company can access the database. Still, even in multi-tenant, each tenant is isolated from other tenants.

  

Reply
0 Upvotes
Highlighted
Occasional Contributor
Here is the problem and I don't think there is a solution. A very glaring error if HubSpot missed this.

Let's say my HubSpot Integration company made an AwesomeApp in my developer account. My company gets two customers for AwesomeApp, Customer A and Customer B. Each customer has an Installer (this is where the doc is very weak, the OAuth "user" is not an end user, not a salesperson, the user is acting in the role as an installer).


Installer A uses Awesome App's install url to install the app in Customer A's HubSpot account. The install url is pointed to my AWS Lambda function which gets a code representing the install during the first step and an auth+refresh token, representing creds for the installer for the second step.

Note that the auth token and the refresh token represent Installer A. Installer A has the rights to scopes for Customer A that they approve during install.


Awesome App's Lambda function stores the install code, the refresh token and access_token from Customer A to do work later for Customer A, on behalf of Installer A, since the refresh/access tokens belong to the Installer A

Installer B then installs Awesome App. The Lambda stores a second triad of code/access token/refresh token for Customer B.


Awesome App adds a Make Awesome Deal button to the HubSpot UI. The app is so awesome two users click on the Make Awesome Deal button at the same time, one user from Customer A the other from Customer B. Each from two different installs.


The click on the Make Awesome Deal button is sent to another Lambda function. The two calls from Customer A and Customer B race to this one function. When the function processes the first call, which access token should the function use? (Or if it has expired, which refresh token should the function use?)

The call gets the dealId, user ID, email and portalId. Can any of these be tied back to the install code or refresh token? Using one token gets data, using the other token gets a 404 (the object is in the other customers HubSpot customer account).
Highlighted
Occasional Contributor
Hi Mike

Exactly the case yes. With the current implementation there is no way to identify the hubspot account to split tenancy.
Reply
0 Upvotes
Highlighted
HubSpot Moderator

Hey @MindfulMike,

 

Just to confirm, when you said click on "Make Awesome Deal" button, are you referring to the CRM extension action button

 

If so, the action hook will have the following query parameters:

  • userId: The numeric userId of the customer requesting data.
  • userEmail: The user address, in HubSpot, of the user requesting data.
  • associatedObjectId: The ID for the current object, depending on the associatedObjectType. This will be the companyId, dealId, contact vid, or objectId for tickets..
  • associatedObjectType: The type of object the user is requesting data about (CONTACT, COMPANY, DEAL, or TICKET).
  • portalId: The portal ID (also called Hub ID) of the customer that is requesting data. This will be a customer that has installed your integration.
  • And values for any of the requested associatedObjectProperties. If one of the request properties is not defined for the current object, it will not be listed in the query string. In the above example, the company property domain is included.

In this case, the portalId value would be the parameters that your team can look at when differetiating two different portals. 

Highlighted
Occasional Contributor

Yes, an action button is what I am talking about, thank you.  Yes, I wrote the lamdba to flip on the portalId but that's a total hack.  I have to manually save the mapping from the portalId to the refresh_token.  The only way I know the mapping is because I know exactly when I installed my app in my two HS instances and I dig through the logs (normally you shouldn't log a token).   

This could be solved if HubSpot sends the portalId with the access_token+refresh_token response during install.  OAuth installs an app into a portal, an HS instance, of course HS should send back to the app which portal/instance it just got installed into,access_token+refresh_token+portalId makes sense.  

A domain would be useful as well, but I do not get any fields with "domain" in the name even when I add it to the &properties list.  Nor is there a "domain" returned for the list of properties for a Deal.  Is domain an HS-internal property?  Do you mean use the user's email domain?  There's no guarantee that the installer and the user have the same email.  The installer could be like me -  a contractor who doesn't even share the domain of the install's org.  That's not usable.  Anyway, there's no "domain" in the response of the refresh_token either so there's nothing tie domain to refresh_token just like there's nothing to tie portalId to refresh token.

There's another path ... in the Auth redirect I can send any content I want.  I just send "Installation successful". I could ask the user for their portalId and get the contacts with the most recent refresh tokens and see if it works as validation (in case anyone is thinking of implementing this you must also send a secret with that page that is later verified on the server when the user's submits the form.  Don't send the refresh key as the secret, make a new one.). Someone else has worked this out already, yeah?

Reply
0 Upvotes
Highlighted
Occasional Contributor

Mike, I like these suggestions. Alternatively being able to register multiple urls per HS portal could add the domain/tenant/customer/identifier for multi tenant environments to process. I am really surprised that HS is this early in their readiness of integration.

Reply
0 Upvotes
Highlighted
Occasional Contributor

@#Hubspot - any update on this ?

 

Reply
0 Upvotes
Highlighted
Community Manager

Hey @rasmusfoged , @MindfulMike -- Going to look at this internally and see what I can find

In the meantime, will add a few more community members to the conversation to see if they have explored this before

@himanshurauthan , @quentin_lamamy , @lynton  -- have you dealt with this before?

Thanks,

Dennis


We are excited to announce that the Community will be launching a weekly newsletter on November 2, 2020!
Sign up today!
Reply
0 Upvotes
Highlighted
Regular Contributor

Sorry @dennisedson no experience on this subject

Reply
0 Upvotes
Highlighted
Occasional Contributor

Sorry for the delay, HubSpot resources gave me the answer last week.  
First make the call to Refresh Token Information from the refresh token from the install:   

https://legacydocs.hubspot.com/docs/methods/oauth2/get-refresh-token-information

Then know the secret that "hub_id" in the response is really the portal id the app was installed on.  That should do most tricks.

I'm still confused on the difference between apps like HubSpot Community that every user installs (thus each user has their own refresh token) and apps that are just installed by a system/admin user on whom all the work is done on behalf of.