Sandbox not authorized V1_ERROR / service.not_authorized

(To preface this post, I have already googled and searched around the forum and found this:

However, I can’t get my head around this error in my application and I’ve spent the better part of the day trying to figure it out.)

I developed a test square integration using the old SquareConnect api about a year ago. I just returned to it this morning and realized I was getting these unauthorized errors.

First thing I did was update to the new API but am still getting the same result.

The code is very straighforward and I’ve triple checked all of my credentials. I’m at a complete loss.

The error is coming when I exchange a code for an access token.

    const client = new Client({
    		timeout:3000,
      		environment: Environment.Sandbox,
      		accessToken: functions.config().square.token
    	})

    	console.log("accessToken: " + functions.config().square.token);
    	console.log("clientId: " + functions.config().square.appid);
    	console.log("clientSecret: " + functions.config().square.secret);
    	console.log("code: " + req.body.code);

    	try {
    	  const response = await client.oAuthApi.obtainToken({
    	    clientId: functions.config().square.appid,
    	    clientSecret: functions.config().square.secret,
    	    code: req.body.code,
    	    grantType: 'authorization_code',
    	    shortLived: false
    	  });

    	  return res.json({'success': true, data: response.httpResponse});

    	} catch(error) {

    		if (error instanceof ApiError) {
          		errorResult = error.errors;
        	} else {
          		errorResult = error;
        	}
        	console.log("error! " + JSON.stringify(errorResult));
        	return res.sendStatus(400);
    	}

Each time I’m getting the following error printed in the js logs:

[{"category":"V1_ERROR","code":"service.not_authorized","detail":"Not Authorized"}]

I’ve checked all of my tokens a bunch. I’ve even plugged the stuff I’ve logged in the method above directly into the API explorer after generating the code and I get a 200 so I know that my credentials are correct, and I know I’m setting my sandbox access token correctly and that it’s the correct token. (again, all this works in the api explorer).

The only thing I’m slightly confused about if I’ve done right is the sandbox test accounts. I have 2 set up and I noticed one of them is maxed out with authorizations. Since I can’t clear those easily from the dashboard I created a new sandbox and have been trying to use that when generating the code.

Any thoughts here? I’m really at a loss. My next step is just going to use an http request with the information above because this seems very simple…

Thanks,
Will

Hi @wcrtr welcome to the forums!

I’m not seeing anything obviously wrong with your code, but typically unauthorized errors are due to incorrect credentials somewhere. I just tested this exact code with my own credentials and it worked successfully (using the latest Node.js SDK). Is the code you’re generating using the same sandbox application id in the URL that you’re using here in your code?

Hey thanks for the reply. Ok, so I’ve definitely checked all the credentials and those I’m confident are correct. I’m having equal trouble just doing straight http calls as well so there must be something I’m doing incorrectly. Just to be clear, the oauth client id == sandbox app id right?

I’m really at a loss for what’s up… there’s no separate keys for each of the sandbox test account right? (e.g I have a couple different test sandbox accounts…)

I’m using

clientId = the sandbox application “application id” (from the oAuth tab)
clientSecret = the sandbox application “application secret” (from the oAuth tab)
code = the code I get back from the authorize redirect
accessToken: the sandbox application “access token” (from the Credentials tab)

This is driving me nuts my brain is turning into mush so I’m a little spacy at the moment.

Thanks!

I’ve verified I’m using the correct sandbox client id in the authorize url - https://connect.squareupsandbox.com/oauth2/authorize.

I’ve verified that the client id, secret and code are all from my sandbox (and prefixed as such).

Once the code has been generated and the call to obtain token has failed, I can pop all those same values into the api explorer on obtainToken and the call succeeds and an access token is returned.

There’s clearly something that I’m missing, but hard to totally see which part that would be. I’ve done OAuth a lot and this is generally the very easy part.

Those all sound correct. Since you mention it works in API Explorer, do you notice any differences in the code it generates? You should be able to choose the dropdown (in API Explorer) and choose “Node.js” and see the SDK code that it’s using exactly. Is there something that is not matching up?

So I ended up copying and pasting the credentials vs using the env vars and now I’m getting more detail in my error logging that the Authorization Code is expired. This is strange because the code is being send to obtainToken immediately. Also strange, again if I take the credentials and code and use the api explorer I get the access token no problem… It seems like if the code was actually expired it would have the same error on the api explorer.

Just in case it helps, I’m using the following flow.

  • iOS app redirects to the square authorize url
  • square redirects back to my server
  • server redirects back to iOS app custom url scheme to open app and pass back code
  • iOS app calls server, which calls obtain code via node api

It’s a slightly roundabout flow, but it has worked in the past. Also fwiw this is also working fine in the production environment. I’ve just been having issues with sandbox.