I'm working on a canvas app which will allow an existing web app to be viewed through canvas.

I have the app working with Signed Request authentication, which works fine when permitted users is set to Admin approved users are pre-authorized. I'm trying to implement the second flow, which occurs when the permitted users setting is set to All users may self-authorize.

The documentation has the following to say:

If the user has previously approved the app and the access hasn’t been revoked or expired, Salesforce performs a POST to the canvas app with a signed request payload.

If the user hasn’t approved the app, or if the access has been revoked or expired, Salesforce performs a GET to the canvas app URL. The canvas app must handle the GET by accepting the call and looking for the URL parameter _sfdc_canvas_authvalue. If the canvas app receives this parameter value, the canvas app should initiate the approve or deny OAuth flow.

_sfdc_canvas_authvalue = user_approval_required

After the OAuth flow is initiated and the user approves the app, the canvas app should call the repost() method with a parameter of true to retrieve the signed request.

The server recieves the GET request with the correct URL parameter, and then redirects to a page which executes the following:

if (!Sfdc.canvas.oauth.loggedin()) {
    var uri = Sfdc.canvas.oauth.loginUrl();
        {uri : uri,
            params: {
                response_type : 'token',
                client_id: 'XXXXXXXXXXXXXXXXX',
                redirect_uri : encodeURIComponent(
else {

The first half of this works as I expected: it detects that we're not logged in, and launches a popup which asks the user to allow access to the Salesforce org, with the connected app name displayed correctly.

Once the user clicks allow, the canvas page refreshes, and we're detected as logged in (and if I inspect Sfdc.canvas.oauth.token there's an OAuth token in there now).

However, when the repost() call is made, the page seems to simply refresh and we're back to our un-logged in state. No signed request is POSTed to the normal URL, which is what I expected to happen. The server just gets another GET request saying that the user needs to allow access again.

If I try to get the signed request straight to the javascript using Sfdc.canvas.client.refreshSignedRequest(), the response comes back with a status of 403.

None of the requests made when I call refreshSignedRequest() or repost() seem to include the OAuth token I see in Sfdc.canvas.oauth.token, which suggests to me that perhaps I'm calling them incorrectly, or perhaps a cookie or header isn't being set somewhere where it should.

Poking into the source code of canvas-all.js has left me none the wiser. There are some attributes called oauthToken in the message body sent to the server which are hard-coded to "null". I've tried hard coding them to match the token in Sfdc.canvas.oauth.token instead, but it didn't seem to make any difference.

3 Answers 3


I had the same problem and just solved it.

You need to initialize a Web Server OAuth Authentication Flow using

response_type : 'code'

and complete fetching the tokens on the server. After you complete the oauth flow you can call the repost() function on the canvas page and you will get the signed request.

A User-Agent OAuth Authentication Flow is not good enough it seems.


Actually, this works fine, with one addition. The clue is in the documentation:

After the OAuth flow is initiated and the user approves the app, the canvas app should call the repost() method with a parameter of true to retrieve the signed request.

So the repost method should be called like this:

  • Can you add a link to that documentation? Any time you reference something, you should link to it if possible. I edited to link to the first result I found, fwiw.
    – Adrian Larson
    Commented Oct 27, 2016 at 22:25

The documentation that was shared does serve as a clue indeed. This should work just right with the OAuth addition, like what was mentioned. You'd need to initialise a web server OAuth flow then go ahead and just complete fetching tokens on the server. After completing the oath flow you can then call the repost() function and then you'll get the signed request. Thanks y'all!

You must log in to answer this question.

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