[SalesForce] How to access “servlet/rtaImage” resources over the API

Does anyone know if it's possible to access the images stored in a rich text area over the API using the username-password flow? I have images in Knowledge Articles that I would like to expose through our app but am unable to figure out a solution. Our app is a standalone webapp which communicates with salesforce through an integration user who is authenticated via OAuth. The only fix we've found so far is to login to login.salesforce.com using a headless browser (zombie.js), grab the value of the sid from the cookies, and use that sid in an HTTP get request to the image hosted at

https://c.<instance-id>.content.force.com/servlet/rtaImage

which works but introduces a lot of unwanted overhead.The answer in How to set public inline images in knowledge base article works great but I don't wish to expose all articles as public. However, when I follow the same steps but make the article non-public I just get an "Image Not Available" error:

enter image description here

So alternatively, if there is a way to fetch these images using an access_token then we could proxy all image requests through our outstanding API connection to solve the problem.

Update

After further investigation, we figured out that this is possible using Daniel's solution as long as you provide the access_token as a valid cookie object. Initially, we were creating the cookie as a String but were only able to get things working once we created it using the jar() function within the request library. When using the username-password flow or the SOAP API, the web scope is not supported but the access_token will still work as a valid sid.

In case anyone else needs this, here is a code snippet which will fetch an rtaImage from Salesforce without making the KB public. Internally, we're using promises but it's not a requirement:

var Q = require('q')
var request = require('request')
var jsforce = require('jsforce')    
var jar = request.jar()
var imageToGet = 'https://c.<instance-id>.content.force.com/servlet/rtaImage?eid=<eid>&feoid=<feoid>&refid=<refid>'

// Initialize a connection to salesforce
var conn = new jsforce.Connection({
  // you can change loginUrl to connect to sandbox or prerelease env.
  loginUrl : 'https://test.salesforce.com'
});

// First, login to Salesforce
Q.npost(conn, 'login', ['foo@example.com', 'p4ssword'])
  // Then generate a cookie containing the access_token from your valid
  // session with Salesforce and issue an HTTP GET request for the image.
  .then(function(userInfo) {
    jar.setCookie('sid=' + conn.accessToken, conn.instanceUrl)
    return Q.nfcall(request.get, imageToGet, {jar: jar, encoding: null})
  })
  // Finally, do something with the fetched image.
  .then(function(args) {
    var res = args[0]
    var body = args[1] // <-- You now have a Buffer object containing the image

    console.log(body.length)
  })
  .fail(console.error)
  .done(console.error) 

Best Answer

You might be able to use the OAuth accessToken in a cookie with the HTTP GET request to servlet/rtaImage depending on the scope you requested when getting it.

I believe you will need to use the full or web scopes to then make web requests or use frontdoor.jsp.

See:

The cookie will have the name sid and the domain ".salesforce.com".

You basically want to use the OAuth accessToken in place of the Session Id.

Note that the accessToken takes the same form as a session Id, but can't always be used to authenticate with the website. Your mileage may vary.