How do we use the OAuth refresh token flow after the first OAuth access token (and refresh token) has been received?

  • 1
  • Question
  • Updated 2 years ago
We have configured our OAuth (Salesforce) authentication provider with a default scope = full,refresh_token and we can connect to Salesforce sucessfully but every time we run the app it always prompts for OAuth consent, how do we get Skuid to remember the refresh token and use it to automatically request a new access token so the user doesn't have to keep approving access?

The same issue happens when using a Google auth provider, we have set the default scope accordingly and can see Skuid setting the access_type=offline parameter in the OAuth request but according to this post we need to add the approval_prompt=force parameter as well?
http://stackoverflow.com/questions/8942340/get-refresh-token-google-api
And even if we did this, how do we get Skuid to use the Google refresh token as above?
Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb

Posted 2 years ago

  • 1
Photo of Zach McElrath

Zach McElrath, Employee

  • 48,984 Points 20k badge 2x thumb
Skuid should be using the Refresh Token flow by default if the Auth Provider supports it. 

1. Which version of Skuid are you running? The Brooklyn release adds some improvements to perform automatic reauthentication if authentication initially failed, such as do to an invalid access token or Refresh Token. 

(a) Salesforce --- are you using the "Authorization Code" OAuth Grant type, or "Implicit"? 

(b) Google Calendar --- Even with Refresh Tokens, I think that Google still requires you to re-authorize every 60 minutes. So you shouldn't be seeing a popup again every time you visit a page with Google Calendar, but you may see one every 60 minutes. Also, I've noticed that Google only returns a Refresh Token the very first time a user accesses a Google API with a particular OAuth Client. As a Google User, you may need to revoke the particular Client's access through Google's Connected Apps area, and then go back into Skuid and try again, which will force a reauthentication.

Hope some of this helps.
Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
Thanks Zach for the help. I've double-checked everything, I tried using both Implicit and Auth Code settings with no luck, I still get prompts or pop-ups (with no grant prompt) occurring for Salesforce and Google OAuth. This occurs in both Skuid Salesforce Brooklyn 9.3.1 and Skuid Native. I've attached my OAuth settings and test page XML. They work fine when you grant access the first time but what I'm expecting is that the next time I use the app (hours later) they should connect (using refresh flow) and retrieve a new access token without any intervention or pop-ups for the user. The end goal is to build an always connected (mobile web) app.

For Google OAuth refresh flow, although I've not actually had to code it yet, the Google documentation I've read below describe an OAuth scenario for offline apps that can access Google APIs anytime (after user grants). It does point out that you need access_type=offline&prompt=consent or maybe approval_prompt=force. Do you know if Skuid is using these settings? It's hard to tell what Skuid is doing and whether there is a refresh token in place.
https://developers.google.com/identity/protocols/OAuth2WebServer#offline
http://stackoverflow.com/questions/8942340/get-refresh-token-google-api
http://googlecode.blogspot.co.nz/2011/10/upcoming-changes-to-oauth-20-endpoint.html
http://stackoverflow.com/questions/31853881/google-oauth-refresh-token
<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="false" useviewportmeta="true" showheader="false">
    <models>
        <model id="GoogleCalendar" query="true" createrowifnonefound="false" datasource="Google Calendar" processonclient="true" x-entityname="Calendar">
            <fields>
                <field id="id"/>
                <field id="summary"/>
            </fields>
            <conditions/>
            <actions/>
        </model>
    </models>
    <components>
        <skootable showconditions="true" showsavecancel="true" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="true" model="GoogleCalendar" buttonposition="" mode="read" allowcolumnreordering="true" uniqueid="sk-3J4xmS-119">
            <fields>
                <field id="summary" hideable="true" uniqueid="fi-3J4z9V-132" valuehalign="" type=""/>
            </fields>
            <rowactions>
                <action type="edit"/>
                <action type="delete"/>
            </rowactions>
            <massactions usefirstitemasdefault="true">
                <action type="massupdate"/>
                <action type="massdelete"/>
            </massactions>
            <views>
                <view type="standard"/>
            </views>
        </skootable>
    </components>
    <resources>
        <labels/>
        <javascript/>
        <css/>
    </resources>
    <styles>
        <styleitem type="background" bgtype="none"/>
    </styles>
</skuidpage>
<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="false" useviewportmeta="true" showheader="false">
    <models>
        <model id="SFDev" query="true" createrowifnonefound="false" datasource="SF Dev" processonclient="true" type="" sobject="Account">
            <fields>
                <field id="Name"/>
            </fields>
            <conditions/>
            <actions/>
        </model>
    </models>
    <components>
        <skootable showconditions="true" showsavecancel="true" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="true" model="SFDev" buttonposition="" mode="read" allowcolumnreordering="true" uniqueid="sk-3I-WVf-110">
            <fields>
                <field id="Name" hideable="true" uniqueid="fi-3I-Zka-142" valuehalign="" type=""/>
            </fields>
            <rowactions>
                <action type="edit"/>
                <action type="delete"/>
            </rowactions>
            <massactions usefirstitemasdefault="true">
                <action type="massupdate"/>
                <action type="massdelete"/>
            </massactions>
            <views>
                <view type="standard"/>
            </views>
        </skootable>
    </components>
    <resources>
        <labels/>
        <javascript/>
        <css/>
    </resources>
    <styles>
        <styleitem type="background" bgtype="none"/>
    </styles>
</skuidpage>


Thanks