I'm trying to understand the tenant endpoint and credentials flow for the 'authorization code' grant type used by installed packages that are published on AppExchange.

I have this flow working well independently, that is, I've created an installed package with an API Integration component and a Web App integration type.

With these credentials, I'm then able to follow the documented authorization flow. Specifically:

  1. An end-user initiates the authorization by clicking on a button in my external web application to 'Connect to Marketing Cloud' which makes the authorization code request to the TSSD Authentication Base URI, which includes the Client Id (of the installed package) and Redirect URI defined in the component.

  2. I get the authorization code back from the request which I extract and use to make an access token request to the TSSD Authentication Base URI. Note that this request includes the Client Id and Client Secret.

This flow is suitable for 'manually installed' packages. However, I'm trying to understand how this could work when my installed package is available on AppExchange. Specifically, I don't know the customer's subdomain (TSSD) to make the initial request to.

I note that there's a hint in the documentation for the second authorization part (receiving an access token) which explains:

For AppExchange partners only: The subdomain, or TSSD, that is returned in the /authorize response is different from your own subdomain used as part of the /authorize request. Use the dynamic end-user subdomain returned from /authorize to construct subsequent token requests on your customer’s behalf.

So, here are my assumptions:

  1. My app will actually use two different TSSD values as Authentication Base URIs; the first includes the TSSD of the app that I used to initially create the Installed Package in Development mode on whatever Marketing Cloud account used (which is then approved and published by Salesforce). The second TSSD is returned from the /authorize response in the Authorization Code Return.
  2. I use the same Client Id and Client Secret for every customer (that is, a Marketing Cloud customer who has installed my app from AppExchange on their account).
  3. The access/refresh token is issued by Marketing Cloud in the context of the user (who initiated the authorization from my app and then logged into Marketing Cloud). That is, the API requests are made on behalf of that user and their account permissions. For example, if I make a GET request to the userInfo REST API route using the access token, this will return the name and email of that user.

In summary, my questions are as follows:

  1. Are my three assumptions listed above correct?
  2. If so, why would the initial authorization request be made to the TSSD of the account that I first used to create my installed package? That doesn't sound very sensible to me. That is, if my account is running on a US-based stack, and someone installs my app on S50 (based in Frankfurt, Germany) it doesn't make much sense to me that the initial auth request is routed to a different stack in a different region?! I would expect that I would use a generic auth request like the legacy auth.exacttargetapis.com endpoint for my initial request, but that doesn't appear to be supported.

1 Answer 1

  1. Yes

From the doc:

AppExchange Partners: Request Tokens on Your Customer’s Behalf

Multitenant AppExchange partners that use web app integrations with Marketing Cloud must be prepared to construct their customers’ v2/token endpoint if your application's status is 'Published'. Your application receives the customer’s Marketing Cloud subdomain, or tssd, and an authorization code after the customer has authorized your application by logging in to Marketing Cloud, as part of the authorization code grant type for web app integrations. When you request a token on the customer’s behalf, you must use the customer’s subdomain, or tssd, if your application's status is 'Published'. For applications with 'In Development' status, you can use the authentication base URI available on the API integration component in Marketing Cloud Installed Packages.

AppExchange Partners: Use the Same Client ID and Client Secret

Multi-tenant AppExchange apps use the same client ID and client secret for all of their customers. Marketing Cloud automatically enables this as part of the AppExchange app publishing and installation process.

The token is issued in the context of a user and a business unit (account/MID). Same user and a different MID will require a new access token acquired via a fresh authorization code sequence.

  1. The authorization flow involves two entities - Authorization Server and Resource Server (see diagram). In this case your "home" instance (first TSSD) is the the Authorization Server and the customer instance (second, dynamically constructed TSSD) is the Resource Server. The Authorization Server's job is to issue the authorization code on the basis of client id and then exchange the authorization code (+ client id and optional secret) for the token.

The client-identifying material of client id, client secret and an intermediate authorization code have to reside somewhere and be tied to your developer identity (account you used to publish the app). If this "somewhere" is the same tenant (instance/TSSD/your little fluffy piece of the cloud) where your developer identity lives, it's quick and easy to look that up when receiving an authorization request.

Compare and contrast this with an architecture where a well-known auth endpoint such as auth.exacttargetapis.com would be responsible for fulfilling authorization requests. The implementation choices would vary, from a classic sharding-like locator (find the tenant, route the request there) to a distributed service layer that could serve some identity functions across all tenants. Since the oAuth authorization code grant flow was bolted on when ExactTarget became MC, the deadlines and cost of dev likely played a role. Ergo a quick and easy for MC but not super convenient for ISVs implementation you're witnessing.

  • 2
    Thanks for the comprehensive answer and for taking the time to answer my question, I really appreciate it. I regret not finding that 'integration considerations' page earlier, which is somewhat buried in the documentation forest and would have saved me time in arriving at my assumptions. Commented Aug 27, 2019 at 7:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .