Error when trying to refresh an access token

(John Laine) #1

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

(John Bergant) #2

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"
(John Laine) #3

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,

(Tom Scott) #4

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.

(John Laine) #5

Perfect, thanks Tom.

(Neil) #6

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