When I authenticated using oAuth, I received an access token and a refresh token, with which I am able to query data from Salesforce.

The access token is working correctly, but once it expires, I cannot seem to refresh the access token. It says invalid_grant: expired access/refresh token.

Even if I try to refresh the access token immediately after receiving the access token and refresh token from Salesforce, it says it is expired.

How do I refresh the refresh token? Or why is it expired?

I do have selected

  • Refresh token is valid until revoked
  • Relax IP Restrictions
  • All scopes are enabled

This is the code I am using

const conn = new jsforce.Connection({
    oauth2 : {
        clientId : sf_client_id,
        clientSecret : sf_client_secret,
        redirectUri : sf_redirect_uri
    instanceUrl : sf_url,
    accessToken : sf_access_token,
    refreshToken : sf_refresh_token,
    logLevel: 'ERROR'

conn.on( 'refresh', function( accessToken, res )
    console.log( 'Refreshing access token..' );

    console.log('accessToken:', accessToken)

    // Refresh event will be fired when renewed access token
    // to store it in your storage for next request

    setEnvValue( 'SF_ACCESS_TOKEN', accessToken );

    await new Promise( ( resolve, reject ) =>
        conn.oauth2.refreshToken( sf_refresh_token, ( err, results ) =>
            console.log( 'refreshToken', err );

            if( err ) return reject();

            console.log( 'refreshToken entrance', results );

            setEnvValue( 'SF_ACCESS_TOKEN', results.access_token );
            setEnvValue( 'SF_REFRESH_TOKEN', results.refresh_token );

            console.log( 'refreshToken saved' );

            resolve( 1 );
catch( e ) {}

console.log( 'Done' );
  • 1
    Are you certain that you are getting a refresh token? Which flow are you using to get the initial access token? Does your connected app have the appropriate scopes selected?
    – Derek F
    Commented Feb 5 at 14:11
  • @DerekF Thank you for asking. I'm getting the refresh token returned from the same call as the access token. It is formatted like this: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXXXX. All scopes are enabled
    – Z0q
    Commented Feb 5 at 14:18
  • 1
    Not this issue perhaps? salesforce.stackexchange.com/questions/65590/… Commented Feb 7 at 14:35
  • 1
    @BritishBoyinDC Thank you for asking. Revoking all, resetting 'Use Count' to 0 did not solve the issue. But it did lead me to switch to JWT Bearer Token flow, which seems more suitable for my purpose.
    – Z0q
    Commented Feb 7 at 15:44

1 Answer 1


It's not really an answer to my own question, but rather a workaround.

I switched to using JWT Bearer Token flow, which seems more suitable for Server to Server Integration - as suggested in the final sentence of this answer, thanks to @BritishBoyinDC for pointing to this question. It solved the issue as no Refresh Token is used by this Flow.

If anyone has an explanation for the original answer, I'd accept it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .