12

I have been pulling my hair out for a few days now trying to figure out how to add username/password authentication to my rails mobile API.

Here is a brief overview of my current authentication flow:

enter image description here

  1. User selects "login with Facebook" on the mobile client, client redirects to Facebook app and requests access_token

  2. On success, Facebook responds with the access token and the client redirects back to my app.

  3. The client sends the access token to my API

  4. My API uses the koala gem to check if the access token is valid.

  5. If the token is valid, Facebook sends the users data to the API where a new user is created. If the user already exists, my API sends down the users data.

My API handles the access token in step 4 as shown below:

      def self.authenticate_user_from_facebook(fb_access_token)
        user = User.new
        graph = Koala::Facebook::API.new(fb_access_token)
        profile = graph.get_object('me')


        #user['fb_id']    = profile['id']
        #user['fb_token'] = fb_access_token

        # Generate user hash
        uhash = Hash.new
        uhash['provider'] = 'facebook'
        uhash['uid']      = profile['id']

        uhash['info'] = Hash.new
        uhash['info']['nickname']   = profile['username']
        uhash['info']['name']       = profile['name']
        uhash['info']['email']      = profile['email']
        uhash['info']['first_name'] = profile['first_name']
        uhash['info']['last_name']  = profile['last_name']
        uhash['info']['verified']   = profile['verified']

        uhash['info']['urls'] = Hash.new
        uhash['info']['urls']['Facebook'] = profile['link']

        uhash['credentials'] = Hash.new
        uhash['credentials']['token'] = fb_access_token

        uhash['extra'] = Hash.new
        uhash['extra']['raw_info'] = Hash.new



        #Save the new data
        user = User.apply_auth(uhash)
        return user
     end


      def self.apply_auth(uhash)
          User.where(:uid => uhash['uid'], :provider => uhash['provider']).first_or_create do |user|

        user.provider = uhash['provider']
        user.uid      = uhash['uid']
        user.nickname = uhash['info']['nickname']
        user.email    = uhash['info']['email']

        user.name       = uhash['info']['name']
        user.first_name = uhash['info']['first_name']
        user.last_name  = uhash['info']['last_name']
      end
   end

Once the user is created, they can make requests to my API using their access token as shown below:

enter image description here

In step 2 the API is using koala to verify the users access token. This is done by applying the following before_filter to all controllers.

before_filter :current_user

and in my application_helper.rb

def current_user
    @current_user ||= User.authenticate_user_from_facebook(params[:access_token])
end

Every time a user makes a request to my API the koala gem is used to check if the token is valid, then the request is processed.

What I am trying to add now is authentication with only username and password.

Things I have looked into

I have been constantly referring to Railscast 235, 209, 250, 82 and reading up on OAuth2. I have a basic understanding of how authentication works but Im having trouble applying it to my current authentication flow.

Devise Token Authentication Referring to Railscast 235, 209, and this blog post: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/

I can understand how to login and validate a user who logs in with a username and password. However I am confused as to how that will mesh with my Facebook login flow. I do not understand how to create a session with devise for a user who already has an access token generated by Facebook.

OAuth2 Making my API an OAuth2 provider seems like it would be a good way to go, but it seems kind of silly to redirect to a browser, and I don't know if its possible to redirect back from the browser to my app.

Authentication From Scratch This is the option I am thinking of going with but I would be reinventing the wheel.

Any advice is appreciated!

3
  • So how did you solve this eventually? Commented Oct 8, 2013 at 6:58
  • Finally.. what approach you use? Commented Jun 4, 2014 at 14:35
  • Those diagrams are exactly what I've been thinking in the last months. Any updates on your search? Commented Aug 5, 2014 at 17:05

1 Answer 1

1

You may want to look into Warden. Warden makes it easy to setup and use different auth strategies whether you use tokens, password or Facebook. It is Rack-based so it also works outside of Rails which is nice if you ever want to use something like Grape for the API.

Here is the RailsCast on Warden. (Pro subscription required)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.