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?
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.
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
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.