Error when trying to refresh an access token

I am getting this error:
{"error":"invalid_request","error_description":"response_type or grant_type is required"}

I am using both postman and node, getting the same error from both.

Here is my code:

const fetchAccessToken = () => {
    const baseURL = 'https://api.infusionsoft.com/token';
    const grantType = 'refresh_token';
    const refreshToken = 'tq7mptg7kdtgj5g7yy899s2u' // TODO: Get this from the database
    const URL = `${baseURL}?grant_type=${grantType}&refresh_token=${refreshToken}`;
    console.log(URL);
    const authorization = () => {
        baseString = `${config.infusionsoft.clientID}:${config.infusionsoft.clientSecret}`;
        encodedString = new Buffer(baseString).toString('base64');
        console.log(encodedString);
        return `Basic ${encodedString}`;
    }
    console.log('authorization', authorization());
    const options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': authorization()
        }
    }


    fetch(URL, options)
        .then(res => res.text())
        .then(body => console.log(body)) // We need to save the token and refresh token to the database.
        .catch(err => console.log('err: ', err));
}

I hard coded the refreshToken for now. Got this from the developer console.

The console.log of the URL looks like this:
https://api.infusionsoft.com/token?grant_type=refresh_token&refresh_token=tq7mptg7kdtgj5g7yy899s2u
I’ve read through another similar post on this forum, but it did not solve my problem.

Any help is greatly appreciated.

John

Hi John,

Can you try removing the parameters from the URL and adding them to the options object in the body encoded?

For example:

var encodedParameters = encodeURIComponent("grant_type") + '=' + 
encodeURIComponent("refresh_token") + '&' encodeURIComponent("refresh_token") +
 '=' + encodeURIComponent("token_value");

const options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': authorization()
        },
        body: encodedParameters
    }

I was able to generate a refresh token with node by doing this and I was also able to generate a refresh token with postman, I have pasted the postman log below:

* * Request Headers:
    * authorization:"Basic <urlencoded_client_id_client_secret>"
    * cache-control:"no-cache"
    * postman-token:"<token>"
    * user-agent:"PostmanRuntime/7.2.0"
    * accept:"*/*"
    * host:"api.infusionsoft.com"
    * content-type:"application/x-www-form-urlencoded"
    * accept-encoding:"gzip, deflate"
    * content-length:63

* * Request Body:
    * grant_type:"refresh_token"
    * refresh_token:"<refresh_token_old>"

* * Response Headers:
    * cache-control:"no-store"
    * content-type:"application/json;charset=UTF-8"
    * date:"Fri, 31 Aug 2018 03:57:25 GMT"
    * pragma:"no-cache"
    * server:"Mashery Proxy"
    * x-mashery-responder:""
    * transfer-encoding:"chunked"
    * connection:"keep-alive"

* * Response Body:
    * access_token:"<access_token>"
    * token_type:"bearer"
    * expires_in:86400
    * refresh_token:"<refresh_token>"
    * scope:"full|<appname>.infusionsoft.com"

You are awesome, thanks John! This did the trick.

A follow up question:

I am building a machine to machine app, that has no user interaction. I will need to store the refresh and access tokens somewhere. Do you think it is safe/best practice to save them to the database?

This is what the IS docs reccomend and it seems ok for the refresh token but the access token is kinda like a password, right?

Thanks again,

The access token is the password, yes. Most systems will store AT/RTs in the database simply due to the number that are often dealt with, but if you are only responsible for a single one, you might want to simply provide them via a configuration file on the server’s local storage, and update the file as required by refreshes.

Perfect, thanks Tom.

Hi,

I am trying to figure out how to programmatically refresh access tokens and this is the only discussion of Node and refresh tokens that I could find. Reviewing your discussion, I have this:

const fetchAccessToken = () => {
    const baseURL = 'https://api.infusionsoft.com/token';
    const grantType = 'refresh_token';
    const refreshToken = refreshTokenVariable; 
    const URL = `${baseURL}?grant_type=${grantType}&refresh_token=${refreshToken}`;
    console.log("URL: " + URL);
    const authorization = () => {
        baseString = `${config.infusionsoft.clientID}:${config.infusionsoft.clientSecret}`;
        encodedString = new Buffer(baseString).toString('base64');
        console.log(encodedString);
        return `Basic ${encodedString}`;
    };
    console.log('authorization', authorization());
  var encodedParameters = encodeURIComponent("grant_type") + '=' + encodeURIComponent("refresh_token") + '&' + encodeURIComponent("refresh_token") + '=' + encodeURIComponent("token_value");
  console.log(encodedParameters);
    const options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': authorization()
        },
      body: encodedParameters
    };

    fetch(URL, options)
        .then(res => res.text())
        .then(body => console.log(body)) // We need to save the token and refresh token to the database.
        .catch(err => console.log('err: ', err));
};

Do you know if there are any other code examples or ones that could be shared? I’m assuming you’re doing a try/catch and then executing this if there is an error.

Thanks