Having problem with accessing different Square applications through their application IDs/secrets

Hey there, I am very confused by this issue I am having and would appreciate any help.

I have a Google AppScript application that I am trying to connect the Square API to. I have been testing it with a couple different Square accounts.

I have an account “a” that has application “a1” and I have an account “b” that has two applications, “b1” and “b2” where “b1” was the first application created. Account “b” does not have access to application “a1.” Each application has their own application ID and secret. Here is the behavior I’m experiencing:

  • When I set the app id/secret to that of “a1” and login with account “a” I successfully retrieve the data from application “a1”

  • When I set the app id/secret to that of “a1” and login with account “b”, the authorization is mistakenly approved but then the data retrieved is from application “b1”

  • When I set the app id/secret to that of “b2” and login with account “b” the data retrieved is from “b1”

I am very confused about what is going on here. It seems like it is ignoring the app ID/secret and just going through the auth flow for the first application that was created under the account that logs in. I see the correct app ID in the authorization URL too but then I am not connected to the corresponding application unless it is a coincidence in being the first app that the user signing in created.

Thank you so much for your help.

For reference, here are the app IDs I am working with:

  • a1: sq0idp-Gvoeqs_Qi41M6LzEoVfzWA
  • b1: sq0idp-a5yRfQrkYD_rxOcf-K6Waw
  • b2: sq0idp-jpYgUfGxulMwvlKVAY_BQQ

And here is the authorization code I am using where I am changing the value of CLIENT_SECRET and CLIENT_ID appropriately:

function getSquareService()
{
  var SQUARE_CLIENT_SECRET = CLIENT_SECRET;
  var SQUARE_CLIENT_ID = CLIENT_ID;

  return OAuth2.createService('Square')
    .setAuthorizationBaseUrl(BASE_URL + '/oauth2/authorize')
    .setTokenUrl(BASE_URL + '/oauth2/token')
    .setClientId(SQUARE_CLIENT_ID)
    .setClientSecret(SQUARE_CLIENT_SECRET)
    .setCallbackFunction('authCallbackSquare')
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope(
      [
        'ORDERS_READ',
        'MERCHANT_PROFILE_READ'
      ]
        .join(" ")
    )
    .setGrantType('authorization_code')

}

function authCallbackSquare(request)
{
  var service = getSquareService();
  var authorized = service.handleCallback(request);
  console.log("Authorized ", authorized);
  if (authorized)
  {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else
  {
    return HtmlService.createHtmlOutput('Denied. You can close this tab.');
  }
}

function authorizeSquareUser()
{
  var service = getSquareService();
  var authorizationUrl = service.getAuthorizationUrl();
  var template = HtmlService.createTemplateFromFile('AuthSidebar.html');
  template.authorizationUrl = authorizationUrl;
  template.service = "Square"
  var page = template.evaluate().setTitle('Authorize Square').setSandboxMode(HtmlService.SandboxMode.IFRAME).setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
  SpreadsheetApp.getUi().showSidebar(page);
}

With OAuth you only need one account that has the application in the Developer Dashboard. You’ll then Authorize the second account with the call to Authorize. When Authorize is called the seller will be prompted to login to there Square account. Once they log in and approve your application they’ll be redirected to your configured redirect URL. In the URL will be the code that you then need to pass in the ObtainToken call.

The ObtainToken call response will have the access_token that you’ll use to make API calls with. :slight_smile:

Sorry, that doesn’t really solve the issue I’m having. In the app I’m building, there are multiple accounts accessing one Square application. Some accounts also have other unrelated Square applications attached to their accounts. In order to connect the Square application to my app, I’m calling Authorize with the application’s ID and secret (which I can see are reflected in the Authorization URL). However, when receiving the data from the Square application, I can see that it isn’t pulling data from that Square application and is for some reason pulling data from the first random Square application that was created by whichever account logs in.

After calling Authorize are you calling ObtainToken with the code from the Authorize call? Thats how you get the access token to get the information for the sellers account. :slight_smile:

I’m not, but I was under the impression that wasn’t needed if I use the client secret going the code flow route instead of PKCE. https://developer.squareup.com/docs/oauth-api/overview

It is required if you use the code flow. The OAuth code flow is designed for confidential client applications that run on a server and can store client information securely. The code flow uses the following OAuth terms:

  • client_id - The ID that is associated with an application using the OAuth process. This is a public variable and is called the Application ID in the Developer Dashboard on the OAuth page.
  • client_secret - The secret that is associated with an application. It is used to redeem refresh tokens and should never be shared by a public client. Leaking this information is equivalent to leaking a password. This variable is called the Application secret in the Developer Dashboard on the OAuth page.

The code flow process is as follows:

  1. Your client application creates an authorization URL that you provide to the seller who approves the permissions you requested. The authorization URL contacts the Authorize endpoint.
  2. The Authorize endpoint returns an authorization code.
  3. The client calls the ObtainToken endpoint and provides the client ID, client secret, and the authorization code.
  4. The ObtainToken endpoint returns an access token and a refresh token.
    :slight_smile:

Hey Brian, so the code I am using is actually calling ObtainToken through the service that is created behind the scene in .setTokenUrl(BASE_URL + '/oauth2/token'. I am still getting this weird behavior where the data returned is from whichever user I login with and not from the application ID/secret that I provide. Any insight you could provide? Thank you for your help

Right, you won’t get data from the application that’s configured as a seller. You’ll only get data for the account that the access token was created from. :slight_smile:

What if user1 has their own application and access to user2’s application and I want user1 to access user2’s application? Even if I put the app ID and secret of user2’s application, when I log in with user1 it returns data from user1’s application

Only one user will have an application with OAuth. That will be your account. You will OAuth to each sellers account. Once your Authorized you’ll get an access token that you’ll use to get information from that sellers Square account. You will not be configuring an app ID for every connected seller. :slight_smile:

So if a user has multiple applications there is no way to access data from just one of their applications? And there is no way for a different user to access data from another user’s application?

And why do we pass in an application ID/secret to receive the authorization URL if it isn’t specific to the application?

When you call Authorize you don’t pass in a secret. You only configure the URL: [Preformatted text](https://connect.squareup.com/oauth2/authorize?client_id={YOUR_APP_ID}&scope=CUSTOMERS_WRITE+CUSTOMERS_READ&session=False&state=82201dd8d83d23cc8a48caf52b)

When the seller clicks on the link and approves the application you’ll get a code in the redirect URL. With that code you’ll make an API call to ObtainToken with the retuned code to get the access token for the sellers account.

The returned access token is what you’ll use to get information from the sellers account. :slight_smile:

Okay yes I’m doing all of that. That doesn’t answer my previous questions. Is there no way for a user to access an application that belongs to a different user? And if a user has multiple applications, how can I access the data of only one of those applications instead of all the data that is attached to the account? And again, I don’t understand the significance of using the application ID in the authorization URL if it isn’t application specific and is instead specific to whichever user logs in.

A seller can have multiple authorized application on there Square account. The only data you’ll be able to access with OAuth is the data from the sellers Square account. This data includes anything that was created by your app or any other 3rd party application. You won’t be able to access data from any other 3rd party application directly that sellers are connected to. :slight_smile:

Gotcha okay. Is there another method to access data from a third party Square application or is there no way?

If you want to access information in a 3rd party application you’ll have to build an integration with that 3rd party application with there developer tools. :slight_smile:

Sorry, I’m not sure what you mean by this. This seems to be a limitation of the Square API not a 3rd party’s dev tools? Are these automated responses? I would appreciate talking to a human about this if so. I want to access data from a Square application with a user who does not own the Square application themself, but rather has been given access.

Okay, I’m happy to setup a meeting to further discuss. Also with OAuth its your application that is given access to take action on behalf of a sellers account. You won’t be accessing any applications. Just the Square seller account. :slight_smile:

Hey that would be great. Can you tell me the protocol to access data from an application instead of a sellers account through the API if it isn’t through OAuth?