Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redirect (callback) outside of canvas #3

Closed
ghost opened this issue Dec 18, 2014 · 28 comments
Closed

redirect (callback) outside of canvas #3

ghost opened this issue Dec 18, 2014 · 28 comments

Comments

@ghost
Copy link

ghost commented Dec 18, 2014

I've specified Secure Canvas URL in app settings as https://localhost:3001/auth/facebook/canvas/
and specified callback url in express app as http://localhost:3000/auth/facebook/callback

However, that throws me out of facebook canvas.

This is all pretty much exactly like in README.

I'd like to stay inside Facebook canvas, is there any way to do that?

@missinglink
Copy link
Owner

hey @dsirijus it's been a while since I modified this lib and I've not had any similar complaints. Setting it all up can be really tricky, which is why I published this in the first place.

In particular, I'd suggest you look at using the auto login route if you're not already, as using server-side redirects blows everything up.

The site I originally wrote this strategy for is still live and stays inside the canvas without issue, maybe you can have a look over the code (which I can't remember any of)
https://apps.facebook.com/openshuffle and hit me up if you need any of the closed-source code (which I think is pretty much copied verbatim to the readme)

@agalazis
Copy link

In my case autologin was configured on failure but it never failed so i added:

Strategy.prototype.authenticate = function(req, options) {

  // Authenticate request via Facebook 'signed_request'.
  if (req.body && req.body.signed_request) {
    return this._authenticate.call( this, req, options );
  }
  if (options.canvasRedirect&&!(req.query&& req.query.code)){
    return this.fail( 'facebook app has not been authorized by this user' );
  }
  // Authenticate request by delegating to Facebook using OAuth 2.0.
  FacebookStrategy.prototype.authenticate.call( this, req, options );
}

to fail manually as well (using the canvasredirect option)

@zalmoxisus
Copy link
Collaborator

hey @missinglink
I got yesterday a "canvas redirect warning" from facebook:

Your app appears to have a Canvas integration that redirects people away from Facebook. This violates Facebook Platform Policy 4.8: "Don’t build an app whose primary purpose is to redirect people off of Facebook." In order for us to consider your appeal, your app will need to stop redirecting users off of Facebook.

I checked https://apps.facebook.com/openshuffle, and see that redirect_uri there is http://apps.facebook.com/openshuffle instead of http://domain/auth/facebook/callback as suggested in the readme. I tried to use my app url for callbackURL, but that doesn't work. Could you please give me a hint how to implement this?

@zalmoxisus
Copy link
Collaborator

So, I solved it by adding in the successRedirect page the following script:

if (window === top)
    top.location.href = MY_APP_URL;

It's not a good solution because of a double redirect (that can be braked by some firewalls), but still cannot get how to add MY_APP_URL directly to the redirect_uri (as in your app). Any suggestions will be appreciated.

@missinglink
Copy link
Owner

Here's a screenshot of my app config if that helps?

screenshot

@agalazis
Copy link

hi @missinglink , tanks letting us know your configuration, the problem is not configuration, it seems that you are using a specific version of passport /passport facebok oAuth2 (not the latest) which acts differently could you post the version of those 3 libraries in your plugin? maybe setting the exact version in the package.json could solve the issue

@zalmoxisus
Copy link
Collaborator

@missinglink, thanks a lot for the info. I have absolutely the same configuration, but after login it is redirected to the callbackURL (domain/auth//facebook/callback), not to the app url as for apps.facebook.com/openshuffle. Could you please check https://github.com/missinglink/passport-facebook-canvas#configure-strategy ?

@missinglink
Copy link
Owner

oh I'm really sorry guys, it turns out that the openshuffle domain was using everyAuth, which was no longer maintained and was the reason I wrote this in the first place. @agalazis you seem to know what the issue is, could you please submit a PR?

@agalazis
Copy link

nuh my solution wouldn't work in any way as expected it's just quick fix /patch that's why I was asking for the library versions you are using, so that I can actually observe what changed and provide a stable solution.Then I would submit a PR.

@falconsapsan
Copy link

has anyone found a solution to this problem?

@agalazis
Copy link

well I guess I will do a pull request but we must do some tests(it seems to
be ok)

On 10 March 2015 at 13:06, falconsapsan notifications@github.com wrote:

has anyone found a solution to this problem?


Reply to this email directly or view it on GitHub
#3 (comment)
.

Andreas Galazis
Junior Web Developer

@zalmoxisus
Copy link
Collaborator

@agalazis, have you got a solution?

@missinglink
Copy link
Owner

right, I finally got some time to have a proper look in to this tonight, you are absolutely correct in saying that it breaks out of the canvas frame and no matter what I tried I could not fix this.

the issue only affects users who log in for the first time, once the app is auth'd then you always stay inside the canvas frame. The obvious culprit here is the frame-busting top.location.href.

This is where I got to, maybe someone else with more time/patience can solve this issue:
https://gist.github.com/missinglink/03809a786b30e714828f

It's been so long now that I can't remember what the original behaviour was in the first place but it does seem that Facebook have become more strict about apps breaking out of their canvas since this lib was originally authored.

I also did a whole bunch of googling around and there are loads of other people with similar problems and no readily available solution, the top.location.href hack seems to be the recommended solution, flawed as it clearly is.

I would welcome a PR to fix this, feel free to use my code above as a base. The login flow is complex and so I'm not counting out simple human error or a misunderstanding although it isn't immediately obvious to me.

@agalazis
Copy link

so do you get new users registered ?(an oneliner i've added was about that
but I might have misinterpreted something as nobody complained about that )

On 13 April 2015 at 23:58, Peter Johnson a.k.a. insertcoffee <
notifications@github.com> wrote:

right, I finally got some time to have a proper look in to this tonight,
you are absolutely correct in saying that it breaks out of the canvas frame
and no matter what I tried I could not fix this.

the issue only affects users who log in for the first time, once the app
is auth'd then you always stay inside the frame. The obvious culprit here
is top.location.href.

This is where I got to, maybe someone else with more time/patience can
solve this issue:
https://gist.github.com/missinglink/03809a786b30e714828f

It's been so long now that I can't remember what the original behaviour
was in the first place but it does seem that Facebook have become more
strict about apps breaking out of their canvas since this lib was
originally authored.

I also did a whole bunch of googling around and there are loads of other
people with similar problems and no readily available solution, the
top.location.href hack seems to be the recommended solution, flawed as it
clearly is.

I would welcome a PR to fix this, feel free to use my code above as a
base. The login flow is complex and so I'm not counting out simple human
error or a misunderstanding although it isn't immediately obvious to me.


Reply to this email directly or view it on GitHub
#3 (comment)
.

Andreas Galazis
Junior Web Developer

@agalazis
Copy link

(not in my server but in the strategy)

On 14 April 2015 at 00:10, Andreas Galazis agalazis@gmail.com wrote:

so do you get new users registered ?(an oneliner i've added was about that
but I might have misinterpreted something as nobody complained about that )

On 13 April 2015 at 23:58, Peter Johnson a.k.a. insertcoffee <
notifications@github.com> wrote:

right, I finally got some time to have a proper look in to this tonight,
you are absolutely correct in saying that it breaks out of the canvas frame
and no matter what I tried I could not fix this.

the issue only affects users who log in for the first time, once the app
is auth'd then you always stay inside the frame. The obvious culprit here
is top.location.href.

This is where I got to, maybe someone else with more time/patience can
solve this issue:
https://gist.github.com/missinglink/03809a786b30e714828f

It's been so long now that I can't remember what the original behaviour
was in the first place but it does seem that Facebook have become more
strict about apps breaking out of their canvas since this lib was
originally authored.

I also did a whole bunch of googling around and there are loads of other
people with similar problems and no readily available solution, the
top.location.href hack seems to be the recommended solution, flawed as
it clearly is.

I would welcome a PR to fix this, feel free to use my code above as a
base. The login flow is complex and so I'm not counting out simple human
error or a misunderstanding although it isn't immediately obvious to me.


Reply to this email directly or view it on GitHub
#3 (comment)
.

Andreas Galazis
Junior Web Developer

Andreas Galazis
Junior Web Developer

@agalazis
Copy link

"top.location.href hack seems to be the recommended solution" yes it is I have also asked if it is acceptable to redirect outside and the back at the official facebook developer group verified that this the expected behaviour for canvas games (In the past I was redirecting to apps.facebook.com/myapp on callback but this has a performance drawback as you still need to redirect top after loading the whole fb page and iframe to get rid of the code so your solution is ok). My problem was actually detecting when facebook app has not been authorized but i didn't see anybody else having the same issue. So I guess my fix is irrelevant.
Other than tha people that don't want to redirect outside facebook for any weird reason can specify the apps.facebook.com/theirappname url but they won't get anywhere as they need to get rid of the code returned as parameter(If they don't care about it then that's fine)

@agalazis
Copy link

David is a facebook support engineer I think his words count:
fb

@agalazis
Copy link

But I think the actual issue I fixed is somehow relevant now that i think about I it people don't get redirected back because of this:

app.post('/auth/facebook/canvas', 
  passport.authenticate('facebook-canvas', { successRedirect: '/',
                                             failureRedirect: '/auth/facebook/canvas/autologin' }));

In the above code failureRedirect never gets called because of some changes in the libraries you use(I think it was oauth2) so you end up getting stack outside facebook please verify if that's the case and i ll do a PR tomorrow (although as I said my solution is not perfect but maybe If I share it other people can contribute to improve it)

@zalmoxisus
Copy link
Collaborator

@agalazis, actually this "weird reason" is Facebook Platform Policy 4.8. As you see from your screenshot even David wrote as the 3rd step that you have to redirect the user back to apps.facebook.com/yourgame.
I'll quote the alert received because of using the library as is:

Canvas Redirect Violation Warning

In working to create a great Platform experience for everyone, we ask developers to ensure the apps they build comply with our Platform Policies. Your app [appname](AppId: [appid]) doesn't comply with the following:

Platform Policy 4.8: "Don’t build an app whose primary purpose is to redirect people off of Facebook."

Your app must not automatically redirect people out of Canvas either before or after Login, and must not be a landing page that serves primarily to redirect to a non-Facebook site. To bring your app into compliance you can make sure your app's core functionality is included within Facebook Canvas. For examples of common redirect violations check out this video: https://developers.facebook.com/docs/apps/review/canvasredirect.

You should also check your app's Login flow to make sure new users aren't redirected out of Canvas after login. When a new user accesses your app's Canvas integration they must remain in Canvas after login and must not be redirected out of Facebook. For help testing your app's Login flow, you can check out this document: https://developers.facebook.com/docs/facebook-login/testing-your-login-flow. If your app is a game, check out this additional document on implementing Login in your game: https://developers.facebook.com/docs/facebook-login/using-login-with-games.

So there are two solutions. One, as David suggested, to redirect back to apps.facebook.com/yourgame. And the second to use app's url as a redirect_uri param, as most applications do (at list the top apps I've just checked), and even @missinglink does for his app. I think the second one is better, because there will not be double redirections, but to implement it (to specify redirect_uri) we have to modify oauth2 library.

@agalazis
Copy link

but as David mentioned redirect uri is yourgame.com period(So that's why I was referring to weird reason xD). Then you redirect back.

@agalazis
Copy link

@zalmoxisus " but to implement it (to specify redirect_uri) we have to modify oauth2 library" This is totally wrong you are already able to specify redirect uri when you initialize the strategy by changing the callbackURL as per my comment (although it might be tricky to land to the right url):

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/facebook/callback"
   //change the above  to https://apps.facebook.com/yourapp/auth/facebook/callback
  },
  function(accessToken, refreshToken, profile, done) {
    User.findOrCreate({ facebookId: profile.id }, function (err, user) {
      return done(err, user);
    });
  }
));

@zalmoxisus
Copy link
Collaborator

@agalazis, you are right, thanks a lot! Just we have to modify the autologin route to:

app.get('/auth/facebook/canvas/autologin', function( req, res ){
if (req.isAuthenticated()) {
  next();
// or the code for the index page
} else {
  res.send( '<!DOCTYPE html>' +
            '<html>' +
              '<body>' +
                '<script type="text/javascript">' +
                  'top.location.href = "/auth/facebook";' +
                '</script>' +
              '</body>' +
            '</html>' );
}
});

@agalazis
Copy link

does autologin get called in your case?

@agalazis
Copy link

@zalmoxisus Now that i see it this is a much simpler and complete approach! kudos! I was messing up with the strategies and whether code parameter was returned (something that was not a complete indication of whether you are authonticated or not and that's why I hesistated to do a PR ) I think you should do a PR to fix the readme ( or missing link can fix this). Thanks a lot for sharing your approach.

@zalmoxisus
Copy link
Collaborator

@agalazis, the solution with not redirecting already authenticated users doesn't work for all cases, also it can generate some security issues when user logs out from facebook, but remains authenticated on the app. Nevertheless I managed to fix it just excluding one redirection as you may see on my pool request. I guess it can be used with req.isAuthenticated clause as I suggested early, but for most the cases that approach is not secured.

@agalazis
Copy link

how do you deal with the code ? doesn't it get resubmited?

@agalazis
Copy link

a ok I understand you still use the autologin route

@missinglink
Copy link
Owner

The solution from @zalmoxisus works great, I tested it today and the user agent always stays inside the canvas frame. Thanks @zalmoxisus!

I've merged the PR which updated the README on how to set it up correctly, for those upgrading the diff is here: https://github.com/missinglink/passport-facebook-canvas/pull/5/files

I've opened a ticket to clean-up and modernize the README file. I'd welcome a PR for this if someone has the time, otherwise I will do it myself at some point.

#6

Thanks again @zalmoxisus I've added you as a collaborator for this repo which means you now have push access, please use it wisely :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants