HTTP Error 403 CORS origin denied getting access token

I’m trying to work through the first few “Getting Started with the REST API” steps using Postman. I got through the Authorization step, but when I try to get an access code I get a “403 CORS origin denied” error.

What am I missing?

What “getting started” pages are you using, for reference? Which step? (Links would be helpful.)

Are you using a Postman standalone, native application? Or through your browser?

The tutorial here: Keap REST API

I’m on step 2 “Requesst an Access Token” under “Authentification.”

I’m using the Postman Google App.

Follow the Form Code example I put in this reply.

Thanks for the additional detail. I bet you’re doing everything correctly; it’s probably Google Chrome getting in the way by trying to enforce CORS.

Please try everything exactly the same as you’re doing now but with the standalone, native Postman application.

There are some important differences between Postman’s Chrome and native apps including Origin headers.

1 Like

I switched to the Postman native app for Windows. Now I get a different error:

HTTP 401 Unauthorized

{
“error”: “invalid_client”
}

Hi @Andy_Lipscomb, I just tried going through the process using Postman and I got the same error when I had selected “form-data” instead of “x-www-form-urlencoded” under the body tab in Postman. Can you verify that you’re using the correct content type?

I was using form-data as well, but I made the change you suggested and tried again. Same result.

Can you take a screenshot of your Postman window and blur/block out the private information (client_id, client_secret, code)?

I may have found the problem while collecting this information. See the response headers and remarks following them.

The screenshot is below. Here’s the actual POST message:

POST /token?client_id=xxxxxxxxxxxxxxxxxxxxxxxx&client_secret=xxxxxxxxxx&code= xxxxxxxxxxxxxxxxxxxxxxxx&grant_type=authorization_code&redirect_uri=https://www.getpostman.com/oauth2/callback HTTP/1.1
Host: api.infusionsoft.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: 2c9e07cd-05da-1a34-2faf-e91be87bed3b

You can see the response in the screenshot. Here are the response headers:

Cache-Control →no-store
Connection →keep-alive
Content-Length →26
Content-Type →application/json;charset=UTF-8
Date →Wed, 19 Jul 2017 18:05:53 GMT
Pragma →no-cache
Server →Mashery Proxy
WWW-Authenticate →Basic realm=“api.infusionsoft.com
X-Error-Detail-Header →Account Inactive
X-Mashery-Error-Code →ERR_403_DEVELOPER_INACTIVE
X-Mashery-Responder →prod-j-worker-us-west-1b-58.mashery.com

Check out the two headers in bold above. Why would it say my account is inactive? Is that the problem?

This video is just a first run through but it covers the details of the oauth2 workflow:

What is you client_id (that is public info so it is safe to share here if you want). If not PM it to me. I will check the status of the key. You could also look at keys.developer.infusionsoft.com and see what the status of the client_id (key) is. It should be active. Also I can’t see the entire query params you are sending but by spec you should not be sending client_id and client_secret in the url. It should a Basic Authorization header. The post body should also have the grant_type and redirect_uri (the one used to obtain the authorization code. I provided a sample POST from the OAuth 2.0 spec (RFC 6749: The OAuth 2.0 Authorization Framework)

     Host: server.example.com
     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
     Content-Type: application/x-www-form-urlencoded

     grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
     &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

The client_id is epmdrdhqeutwnqbayzj3zj6u. keys.developer.infusionsoft.com shows it as active.

The Post message has the grant_type and redirect_uri parameters. I included the full text of the request in my earlier post. You can see them there.

When I send the initial authorization request, I get a page that asks me to select the Infusionsoft app to access. I have two choices, one of which references a defunct sandbox account. I choose the other, which is the full-up, paid app I need to access now. Could the fact that there are two instances of IS associated with my login credentials be part of the problem?

The multiple accounts is by design and should be fine. Sorry I missed the full post earlier. I just added a pinned post with a link to the possible error codes you can get from /token Common Error Codes/Causes to `/token` and the API

try the post without the query params, put the params as x-www-form-urlencoded params in the body, and the credentials as a properly formatted Basic Auth header. Let me know how that goes.

Same result: 401 Unauthorized, Invalid_client. Heres the POST:

POST /token HTTP/1.1
Host: api.infusionsoft.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic xxxx
Cache-Control: no-cache
Postman-Token: f042703e-3b41-3e20-8539-b272707f959d

client_id=epmdrdhqeutwnqbayzj3zj6u&client_secret=xxxxxx&code=q33fwk724vgb92wcwqhzuube&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fwww.getpostman.com%2Foauth2%2Fcallback

So the issue is the authorization header. The username needs to be your client_id not your mashery username. I base64 decoded your header to see that you are using andy.lipscomb as the username when it should be epmdrdhqeutwnqbayzj3zj6u. You might might to delete that post since it has your client_secret in it even though it is base 64 encoded :slight_smile:

Now I get Error 400 Unauthorized, and the message is:

{
“error”: “invalid_grant”,
“error_description”: “Authorization code is invalid”
}

I generated a new auth code, and tried that with the same result.

OK, I just got yet another auth code and tried again. I also removed the Basic Auth header. For some reason, it worked this time. I finally got an access code. I also used the refresh token to get a second access code. I honestly don’t know why this worked, but to summarize:

  • I used a Content-Type: application/x-www-form-urlencoded header and put the parameters in the body rather than the URL.
  • I did not use a Basic Authorization header.

The Refresh Access Token does require a Basic Authorization header (as the documentation states) with the client_id and client_secret in the base-64 encoded value.

UPDATE: Based on replies to my earlier post and further experimentation, the request works equally well with client_id/client_secret in the body or in an Authorization header. The Authorization header is considered the standard method and preferred.

You should not put the client_id and client_secret in the post body. The Authorization header should still be there. Refer to the sample post request I mentioned above. Putting the client_id and client_secret in the body works but is not to spec and can go away anytime. Mashery currently supports it, but that is not guaranteed by any means.

The Infusionsoft API Reference clearly lists these values as parameters of the Get Access Token call and as a base64-encoded Authorization header value for the Refresh Access Token call. If the parameter method is out of spec, the documentation should be updated.

The OAuth spec you referenced in your earlier post states that either method is acceptable. See Section 2.3

Be that as it may, I confirmed that either method works as of today. If you are sure that the header method is preferred, I’ll use that exclusively in the future.

Thanks for your help.