I’m having trouble authenticating my canvas app using oauth2. This is despite being able to authenticate and connect via other means. The following is my problem in detail…
I’ve configured a connected app with the following settings…
OAuth Scope: full, refresh_token, offline_access Canvas App URL: https://app.d.com/ (this is a locally-running server) Canvas Access Method: OAuth Webflow (GET) SAML Initiation Method: None Locations: Chatter Tab, Visualforce Page, Layouts and Mobile Cards Options: Enabled as a Canvas Personal App Lifecycle Class: None
Using OAuth and the jsForce library on the backend, I’m able to authenticate with Salesforce and push events from our web app to a chatter stream. During the authentication process, I save the user’s auth token and refresh token (so that I am able to continue to make calls via the backend).
However, when plugging the Sfdc library into the front end and attempting to access my web app via canvas, I am unable to get the context object. Here is some debugging code (in coffeescript) that I trigger when the web app is loaded via canvas…
initCanvas: (session) =>
if !Sfdc.canvas.oauth.loggedin()
debugger
uri = Sfdc.canvas.oauth.loginUrl()
Sfdc.canvas.oauth.login({
uri: uri
params: {
response_type: "token"
client_id: SALESFORCE_API_KEY
redirect_uri: SALESFORCE_REDIRECT_URI
}
})
else
debugger
Sfdc.canvas.oauth.logout()
Ideally, since I already have the user’s auth token (when they enable chatter integration), I shouldn’t need to trigger the Sfdc.canvas.oauth.login() function. I should be able to get the context by creating my own client object. But since I am trying to follow the examples as closely as possible, let’s proceed with the assumption that I’m using the code above…
When the canvas app loads within salesforce, my first “debugger” breakpoint gets hit. After playing through this breakpoint, I receive a salesforce popup window which asks me to authenticate. After authenticating, the canvas app appears to refresh (because it hit the example callback.html endpoint provided) and now my second breakpoint gets hit (after the else statement). At this point, my client object looks like the following…
{
instanceId: undefined,
oauthToken: "00Do0000000...Ce7F2kJx”, // shortened for this example
targetOrigin: undefined
}
Unfortunately, it appears that I need the instanceId and targetOrigin, because when I try to request the context…
Sfdc.canvas.client.ctx(function (msg) { console.log(msg); }, client);
I get back the following error…
{status: 400, statusText: "Bad Request", parentVersion: undefined, payload: "client.instanceId or client.targetOrigin not supplied”}
This response comes from the Sfdc library, not any salesforce server. Any attempts to modify the instanceId and targetOrigin fields directly on the client object do not appear to work either…
client = {oauthToken: "00Do0000000…Ce7F2kJx”, instanceId: “06Po0000000LRQb”, targetOrigin: “https://na17.salesforce.com”};
Sfdc.canvas.client.ctx(function (msg) { console.log(msg); }, client);
Response...
undefined
(no callback msg received in the console)
Looking at the documentation, the instanceId and targetOrigin are defined as…
instanceId: The ID of a canvas app exposed on a Visualforce page. Used internally for canvas app instance management. targetOrigin: The URL of the canvas app. Used internally for cross-domain communication between the page and the iFrame that contains the canvas app.
Questions…
1.) If the user has already authenticated and given permission to the app, why do we need to request permission a second time? 2.) It appears as though the instanceId and targetOrigin fields are required portions of the client object before being able to request the context via the Sfdc library. How can I obtain these fields?