We're trying to use the same connected app (using Web Server flow) for two purposes: 1) Allow API calls to Salesforce via an external website and 2) Use Canvas App to embed that external website into Salesforce.

In order to accomplish (1), we used the Enable OAuth Settings checkbox in the API (Enable OAuth Settings) section, and put the appropriate callback URLs, and also allow for Perform requests on your behalf at any time (refresh_token, offline_access) scope to allow the external website to get refresh_tokens as needed).

Yet, as per the help article on Connected Apps - Canvas App Settings, it says the following when using a Signed Request (POST) Canvas App access method:

Signed Request (POST)—OAuth authentication is used, but when Salesforce admins install the canvas app, they implicitly allow access for users. Users aren’t prompted to allow apps to access their user information. When you use this access method, authentication is posted directly to the canvas app URL. If your canvas app uses signed request authentication, don’t select Perform requests on your behalf at any time (refresh_token) for the Selected OAuth Scopes.

Sounds like a contradiction - I want the API to get refresh tokens, but they're telling me to turn off this scope because of the Canvas App aspect.

Also, according to the Edit Connected App Behavior -> OAuth Policies article, it says:

If your connected app is a canvas app that uses signed request authentication, be sure to:

  • Set Permitted Users to Admin-approved users are pre-authorized.
  • Set Expire Refresh Tokens to Immediately expire refresh token.
  • Give users access via profiles and permission sets.

For our API purposes, we'd like to keep the default setting of OAuth Policies -> Refresh Token Policy to Refresh token is valid until revoked, so that we're not constantly having to re-authenticate the API connections.

Does anyone know:

  1. Why Canvas App needs to have the refresh_token permission turned off
  2. If we need the refresh_token permission for our external website to leverage the API via this connected app properly
  3. The implications of having the Immediate expire refresh token with regard to the API connection and also with regard to the Canvas App

Update 7/11/2019 (based on @identigral answer)

We are actually trying to use the connected app in two different functional ways: 1) Allow API calls via the external web platform, which is happening whenever leads/contacts are created in the external website or the like, and then 2) Canvas App layer on top of it to allow that website to be embedded into Salesforce.

According to the OAuth Authentication doc, it looks like we should, in theory, be able to combine both functionalities into one app:

If you have an existing connected app that uses OAuth authentication and you want to expose that app as a canvas app, you have two options. First, you can edit the existing app (create a new version) and add the canvas app information to it. This means your app can continue to use the same client ID and consumer secret. The second option is to create a new canvas app. If you do this, you’ll get a new client ID and consumer secret, and you’ll need to update your app with that information.

Again, if we put both into the same app, then we run into the contradictory instructions as mentioned above on how to setup the configurations.

@identigral suggests that we should just use two connected apps, one for each set of functionality (API use vs. Canvas App embedding). We're trying to publish a package on the AppExchange, and if we can keep it all in one connected app, that would be ideal.

1 Answer 1


First, I am assuming that your scenarios (1) and (2) are really one and the same. The external website calling into Salesforce is wholly represented by your Canvas-based app. That is, all API calls (incl. authentication / authorization) from your external website go through Canvas SDK. If this assumption is NOT true, you should create two connected apps - one for your external website and the other for your Canvas app. The answer below reflects a scenario where the connected app is solely for use by your Canvas app or your (1) and (2) are one and the same.

The docs are confusing because there are two implementations of an authorization use case in play: the standard oAuth option with two different flows - Web Server (aka authorization code grant) and User Agent (aka implicit grant) - and the SF-proprietary option via a signed request. To make this even more interesting for developers both of these options support two authorization flavors: one where you can pre-authorize users via a profile and the other where the users explicitly authorize access. Last but not least, the signed request mechanism is essentially oAuth-lite with JWT-like token.

Under the oAuth umbrella, the User Agent flow does not use a refresh token...but don't use this flow. It's an older flow and it's not recommended. Web Server flow is the way to go, it requires a refresh token.

If you go with the signed request option AND the authorization flavor is where users must explicitly authorize access, THEN the initial, one-time flow to do so is...via oAuth. And again, if you choose the recommended oAuth flow (Web Server/authorization code grant), the refresh token will be issued....but won't be used because you never refresh the access token via the refresh token. The "refresh" equivalent in the signed request mode will be done for you after you issue a repost() or refreshSignedRequest() call. This is why the recommendation is to configure a refresh scope on the connected app but expire the refresh token right away. It's a compromise between correct configuration (protocol requires it, at least in Web Server flow) and security (likely not needing/using it). The docs gloss over the reason for the compromise and that the compromise only makes sense for the signed request/explicit authorization combo.

  1. Do you need a refresh token? With oAuth and Web Server/authorization grant flow, you most certainly do. Your access token is going to expire, you'll need a way to refresh it. With a signed request, you don't need it. This bullet is true for both oAuth and signed request options regardless of authorization flavor.

  2. You mean oAuth scope - see above.

  3. Immediate expiration makes sense for signed requests.

  • Fantastic answer so far, thank you! Please see my updated question above for exactly how what we are trying to accomplish Jul 11, 2019 at 7:10
  • 1
    @BrianMiller The docs do not consider the nuances of the dual-purpose use case, thus the contradictory language. I would still go with two connected apps for a number of reasons having to do with decoupling of two access scenarios - limit on access tokens, being able to revoke access on one client vs the other and reporting come to mind. If you want to combine them in one app, NOT expiring the refresh token should be ok.
    – identigral
    Jul 11, 2019 at 9:34
  • Super helpful and makes a lot of sense. We already have a working version of both when they're separate, so we'll keep them separate. Being able to revoke access & reporting are great reasons to keep them separate Jul 11, 2019 at 14:20

You must log in to answer this question.

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