5

We have a visual force page that uses the Apex PageReference method to redirect the VF page to the https://login.salesforce.com for oAuth authentication.

All is working well except in the new Lightning experience where it is throwing the cross origin errors. It works with just the URL but when you add on all the oAuth parameters is where it fails

The code below is what we are using to redirect the page. Since I expect this to be a major issue with a lot of VF pages I am making the question now:

Q: How to do this type of redirect in the new lightning since the vf page is forced inside an iFrame...

public static pagereference oAuth_get_Code(){

    String auth_url = 'https://login.salesforce.com/services/oauth2/authorize';
    String params =  
                        '?response_type=code' +
                        '&client_id=' + encodingUtil.urlencode(client_id(),'UTF-8') +
                        '&redirect_uri=https://' + (isSandbox ? 'cs1' : 'ap1') + '.salesforce.com/apex/ns__pageName' +                             '&prompt=login' + 
                        '&scope=' + encodingUtil.URLEncode('full refresh_token','UTF-8') +
                        '&state=oAUTH_GET_TOKEN';
        pageReference pr = New PageReference(auth_url + params);
        return pr;
}

The error in the console is:

Refused to display {URLDATA} in a frame because it set 'X-Frame-Options' to 'DENY'.

I have added *.salesforce.com and *.force.com to the CORS settings which did not help.....

Exact Error after going to the URL login.salesforce.com/authorize/.......from the code below (This is not the URL I went to so it appears to be the redirect from the authorize:

Refused to display 'https://login.salesforce.com/?startURL=%2Fsetup%2Fsecur%2FRemoteAccessAuthorizationPage.apexp%3Fsource%3DCAAAAU-y0CfJME8wMTMwMX0aCFic4_6fm8ToqqV4SlqhPmh2XbkdZ_-w5uuwmHz_SUT86ve-mdoBjxCw8hcmU3BastbWyCXCohzbqioy6Iz7LWkf-PZWhu3bm7PFdH5xMiDodqSvVdWvsZ60x0je0kSxCTcj9-xydU4OuDeIgSVS4kjN5pFq7FjQLudevAktiKUvgwID1BzIqagzvbvTd7vBaFRV0e3EIbUpKdHf1ss03hilXwEIch-b3BPwmPMST21usKvKed6Z57M8ow5NoHvip5hEU6p67NDJcF8rMaM5fGl5W-HsVD9l0RU5YEH5neiehIzSS3Z-EkUhMW_KFx4UUY36hvRpIM1KbkIgbvhTQpGY0tCGPealN51o74wPkpc6ZOmCa04ZR6VkU2qw5qaftreDZzghXYh2xLqXX1Yawmxjzn5jXk52gSxyBNWH9RO_LgR8FcVM081g8eEYatVK987tfy-2F_EXH67bETUAnWCkkV-pe3mzKOvftdcW_DBp3p070iJj3MavtbENhEdrBUTDxzzO00%253D&sdtd=1' in a frame because it set 'X-Frame-Options' to 'DENY'.

  • Just to clarify, the X-Frame-Options header in the response being served up from login.salesforce.com simply tells the browser that under no circumstances should that page be allowed to exist within an iframe tag. I would not classify that as a "cross origin error" nor would changing CORS settings affect that behavior. It sounds from your question that in a standard page when this VF page is embedded (in an iframe) that this method works perfectly or are you normally using this VF page on its own outside of an iframe and not embedded in a standard page? – Mark Pond Sep 9 '15 at 16:38
  • @MarkPond - VF page on its own normally (And works fine). But inside lightning it forces it into the iframe - hence the problem....I think the answer below to use a popup may be the only workaround unless you have another idea. – Eric Sep 9 '15 at 17:52
  • Ugh, just told by T3 support that you cannot use pagereference in a VF page within the lightning experience. I find this hard to believe since it is the only way to navigate to a new url from apex....Lightning is neat but I do not think it should force the desktop to behave like a mobile device....Going to be a slow adoption at an enterprise level I think... – Eric Sep 11 '15 at 23:07
1
+100

I usually also set

pr.setRedirect(true);

to make the redirect happen clientside (instead of serverside) so that's worth a try. See for more info here.

What I would suggest is creating a public property on the controller to store the authURL

public String redirectURL { get; set; }

then doing the redirect in Javascript. For this, you'll need rendering the redirectURL in a div (you can't rerender javascript, it will become non-functional CDATA), and do the redirect using something like this

<apex:outputPanel id='redirectURLwrapper'>
    <div id='redirectURL'>{!redirectURL}</div>
</apex:outputPanel>

<script>
    function tryRedirect() {
        var redirect = document.getElementById("redirectURL")[0].innerHTML;
        if (redirect) { top.location.href = redirect; }
    }
</script>

<apex:actionFunction action="{! }" reRender="redirectURLwrapper" oncomplete="tryRedirect();" />

We use top.location.href to make the redirect happen at the top (browser-screen) level, so not inside the iFrame. I have not tested this code literally, but you should get the idea.

If you don't want to lose your existing page, you could also open the URL in a new window like so

<script>
    var windowObjectReference;
    function tryRedirect() {
        var redirect = document.getElementById("redirectURL")[0].innerHTML;
        if (redirect) { 
            windowObjectReference = window.open(redirect, 'newWindowName');                    
        }
        // the popup window should close itself in the return window. If that is not possible, then poll the windowObjectReference and after you detect a redirect, call windowObjectReference.close(); to close it
    }
</script>

Does that help?

  • First, I am redirecting to a salesforce domain, second, the issue is that the top is being redirected (by default when the iframe should be the redirect) and not the iframe....If the redirect was happening in the iframe I would not be getting the same origin policy blocking the redirect correct? Not to mention, there are 3 other steps to the oAuth happening in the apex class. Thanks for taking the time to bang out an answer though appreciate it....We can all learns something with every answer – Eric Sep 9 '15 at 13:25
  • Ah yes you are redirecting to salesforce.com domain: removed the text about that. Did the .setRedirect(true) do anything? You are getting the error because you are trying to redirect in an iframe. So redirecting on top should work... Did you actually try my code? – Willem Mulder Sep 9 '15 at 14:03
  • setRedirect(true) is the default value. Just for kicks, I tried it and no change. As for the JS, the top.location DOES work to redirect the whole page but removes the entire lightning experience even on return. I would have to do major reconstruction and it is not worth it as I can tell users to just use classic mode with same effect....Again, appreciate your effort... – Eric Sep 9 '15 at 14:24
  • Sure no problem. All in all then, there's no proper way to do it. The login page explicitly does not want to be framed, and in lightning you need it to be framed. Conflict. Can't you just open the login page in a separate page with window.open()? developer.mozilla.org/en-US/docs/Web/API/Window/open – Willem Mulder Sep 9 '15 at 14:43
  • I am going to try just that (popup window). I think that may be the best solution......We will see....Also may be time to look at redoing the whole thing in lightning components....that will be a learning curve but I have to take the jump sometime.. – Eric Sep 9 '15 at 14:58

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.