2
\$\begingroup\$

I have built a Rails app where users can login using Facebook. They have an account on the Rails app but do any authentication in it other than creating a session if they have logged into Facebook successfully.

The first part is using the SDK to get the access_token if they have logged in:

FB.getLoginStatus(function (response) {
    if(response.authResponse) {
        $.post('/auth', {access_token: response.authResponse.access_token}, function(response) {
            window.location.href = '/';
        });
    }
});

And then I pass this to my create method in my controller:

def create
    user = User.from_facebook(params[:access_token])
    session[:user_id] = user.id
end

And the model has the following methods:

def self.from_facebook(access_token)
    # get the user from the FB API
    fb_user = get_user(access_token)
    # either return or create a user from the ID
    where(id: fb_user.id).first_or_create do |user|
        user.id = fb_user.id
        user.name = fb_user.name
    end
end

private

def get_user(access_token)
    response = RestClient get "https://graph.facebook.com/me?access_token=#{access_token}"
end

So I basically either return an existing user or create a new user with the user id that comes from using the access token. This should prevent any unauthorized access and only log in the correct user as it means that the user is logged in using the access token to get the user from Facebook.

Are there any flaws in this method? I know I don't handle if the access_token is invalid, etc. I'm more interested in the security aspect of logging the user in by getting there ID from the token, but as this is all done server side, it seems pretty secure. I also don't want to use anything like Omniauth or other gems.

\$\endgroup\$
1
\$\begingroup\$

I've implemented a few social apps before. What you've done is pretty standard practice when it comes to oauth authentication and is secure.

The one thing you could change:

 where(id: fb_user.id).first_or_create do |user|
   user.name = fb_user.name
 end

When you use first_or_create when it creates it'll set the where query as attributes. So in your case the id will already be set as fb_user.id.

\$\endgroup\$
0
\$\begingroup\$

You should parse the signedRequest from authResponse and get the user_id from there instead. Here's how to parse it:

https://developers.facebook.com/docs/games/gamesonfacebook/login#parsingsr

\$\endgroup\$

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.