1

I have built several Hybrid Remote mobile apps for Customer Community users using the Salesforce Mobile SDK, versions 3.1.2 through 3.3.0. I'm using a custom community login screen, based on the SiteLogin Visualforce page provided by Salesforce when you first create a community. I'm also using social login with Auth Providers, but in my testing, the issue seems to be the same if using Salesforce username/password for login.

In each case, the app works fine, and re-launching the app before the current login session expires will successfully start the app without requiring another login. But if the current session expires (or if you remove the current session via Setup->Security Controls->Session Management), the app requires you to log in again. It does not appear to use the OAuth Refresh Token to obtain a new Auth token. How can I prevent users from having to login after each session expires?

1

After using an http proxy to watch the traffic from my app, it is clear that the app does receive a Refresh token upon successful login, and that after the original session (Auth Token) expires, the app does use the refresh token to obtain a new session. The problem is that when it asks for the new Auth Token, it passes a retUrl that includes the old Auth Token, which is used after the refresh.

I built a test app with just minimal functionality to test the login behavior; if you are interested in the details of my findings I posted them to the Mobile SDK Google+ Group. Note that the test app did not use a custom login screen, which led to some different observed behavior.

The solution is to inspect the startURL and retURL params during the community login process and modify them to avoid the loop. The rest of this answer details my process.

First, your community should be configured to use the CommunitiesLogin VF page provided by Salesforce as its login page (or a custom page based on it). This page, as provided by Salesforce, is a simple redirector that redirects the user to the standard login page for the community. Because I want a custom login page, I have previously just customized SiteLogin and made that my login page, however, now we need the redirect behavior in order to fix up the params.

CommunitiesLogin redirects by using the action param of the apex:page page tag to call CommunitiesLoginController.forwardToAuthPage(). The provided method looks like this:

global PageReference forwardToAuthPage() {
    String startUrl = System.currentPageReference().getParameters().get('startURL');
    String displayType = System.currentPageReference().getParameters().get('display');
    return Network.forwardToAuthPage(startUrl, displayType);
}

Note the passing of the startURL param. When the hybrid remote app tries to login using an existing Auth token, it will call frontdoor.jsp and pass the app's start page (from bootconfig.json) as the retURL, but when the app tries to get a new Auth token via the refresh token, this page will see the request with the original frontdoor url (including the invalid session token) as the startURL param instead of the app's start page. Interestingly, the retURL param from inside that startURL is also extracted and passed to the VF page, so we can use that.

We need to redirect to our custom login page (in my case, SiteLogin) instead of the standard auth page, so I added a new method to CommunitiesLoginController and updated the VF page's action param to call the new method:

global PageReference forwardToCustomAuthPage() {
    map<string, string> params = System.currentPageReference().getParameters();
    String startUrl = params.get('startURL');
    string extraParams = '';
    if (startUrl.contains('frontdoor.jsp') && params.containsKey('retURL')) {
        startUrl = params.get('retURL');
        extraParams = '&ec=301';  //expected by SDK
    }
    String displayType = params.get('display');
    // update SiteLogin to your custom login page name
    string url = Site.getPathPrefix() + '/SiteLogin?startURL='  
               + EncodingUtil.urlEncode(startURL, 'UTF-8') 
               + '&display=' + displayType 
               + extraParams ;
    return new PageReference(url);
}

I'm passing startURL along unchanged, unless it contains frontdoor.jsp and the page params contain retURL, which I take to mean that we are in an OAuth Refresh request, in which case we replace startURL with retURL. Also note extraparams. While investigating with my test app, I found that the iOS SDK looks for this param when detecting a session refresh redirect, but I wasn't getting it in my page params, so I'm adding it manually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.