Rails Devise OmniAuth Facebook Login from iOS

2019-03-11 00:11发布

问题:

I've been searching for a solid solution to this problem, and came across this SO question which kind of matches my predicament, but not exactly.

Currently I have my iPhone application authenticating with my Rails API via Basic Auth. It's just your simple, run-of-the-mill devise auth package. I then followed the instructions to set up omniauth-facebook for devise and got that working on the browser side.

The part I can't figure out how to do is how to send the token received on the iPhone side (via the Facebook iOS SDK) to the server. I want the server to check the users table to see if that facebook user has signed up, and create an account for him if he hasn't. Then, I was thinking the server would generate a random password and send it back to the client device so that I could keep my same basic authentication strategy. Is this the proper way to implement single sign on for a web app and iPhone app? How would one go about modifying the server side packages to support authentication via a token sent from the phone?

回答1:

You may want to take a look here:

Open Source: Announcing devise-iOS For Simplified Auth

It looks like a relatively painless way to work with Rails / Devise and iOS. I definitely plan on using it in my next project.



回答2:

Have you looked into making your app an Oauth2 provider?

I haven't done this myself, but after some digging it looks like opro and doorkeeper are two possible solutions to the problem.

https://github.com/opro/opro https://github.com/doorkeeper-gem/doorkeeper

looks like opro works pretty well with devise:

#inside initializers/opro.rb
Opro.setup do |config|
  config.auth_strategy = :devise
end

Definitely interested to see how this turns out for you



回答3:

I think you have the right plan. We've done exactly this in our app and Web service.

The apps use a REST API, basic authentication over HTTPS, a server-generated password, and all of this is implemented without Devise. There's a method in the controller that all the API controllers inherit from, that is a before_action for all the API methods, and it calls 'authenticate_or_request_with_http_basic'

class ApiController < ActionController::Base
  before_action :authenticate_api
  def authenticate_api
    authenticate_or_request_with_http_basic do |username, password|
      # check server-generated password
    end
  end
end

So that handles most requests.

We also have a API controller action to register from the device once to get that server-generated password:

class UsersController < ApiController
  skip_before_action :authenticate_api, only: [:register_fb]

  def register_fb
    graph = Koala::Facebook::API.new(params.require("access_token"))
    profile = graph.get_object("me?fields=email,first_name,last_name")
    # then go on to look up user if already exists, or create
    # ...  return server-generated password
  end
end

The Web app, however, all controllers inherit from WebappController and use devise.

Thus we have two passwords on the User object (one for web, one for mobile) and a facebook ID as well as our own User id which is the one we use for authentication.