OAuth flow, iPhone -> Rails -> Facebook - ruby-on-rails

I'm building an app with both a web client and a iPhone client.
On the web client I authenticate users through Facebook with Omniauth, the user can then post actions on the app to Facebook. That works good.
I'm having some problem implementing the Auth flow from the iPhone application.
I've set up Doorkeeper in the rails app as an OAuth provider. Although I'm not sure how the authentication flow should be implemented.
I've come up with this:
The user can log in to Facebook in the iPhone and get a token. The idea is then to send the token, along with the Facebook uid to the rails app, store it, and authenticate the user with Omniauth. Once the user is authenticated generate a token with Doorkeeper and send it back to the iPhone app.
If it's the first time the user authenticates against the rails app, a new user will be created.
The user can then do actions against a JSON-api and the rails app will take care of the Facebook integration since the Facebook token is stored on the user record.
The application will also span over several domains so I'll need to have multiple Doorkeeper applications registered to provide different callback uri's.
Does this seem like a viable solution?
Is it secure?
Is there alternative flows / approaches?
Thanks.

The solution I went with is summarized as followed:
Client starts oath flow w/ Facebook (using login button etc)
Client gets auth token and posts back to server
Server looks up user via FB API call w/ token
Server does lookup/create of user based on FB id
User is logged in if a user with FB id association lookup is successful
I have a diagram and more detail here: http://www.eggie5.com/57-ios-rails-oauth-flow

Related

Prevent Okta from authenticating user during OAuth 2.0 authorization redirect

I'm building an app that requires users to authenticate with Salesforce. However, the problem I'm encountering occurs when Okta (SSO) steps in to authenticate the user automatically. The user is authenticated and redirected to the Salesforce home page, rather than the OAuth callback redirect as configured in the connected app (and passed as query param).
This is happening between steps 3 and 4 on this diagram:
Question: Is there a way I can prevent Okta from automatically authenticating a user on a page?
Just wanted to circle back and post my answer. It was simply the authorization server url. Instead of directing a user to a specific Salesforce instance (i.e., "na17.salesforce.com"), use the Salesforce auth server (i.e., "login.salesforce.com"). This keeps Okta from identifying the specific subdomain and trying to authenticate.

What are the different methods that i can use to authenticate user from rails server which is a backend of iOS?

I use rails as backend for ios applications. So far i have been using devise as it looks flexible and comfortable to use with less effort . And i have read about omniauth and that too looks easy to integrate with devise. My question is, consider my ios app requires authentication and the following are the different methods that i should be able to allow user to do
Login using email and password
Login using Facebook account
Login using Twitter account
Login using email can be handled by the devise itself but how about login using Facebook and twitter? Actually in one of my project i came up with the following approach which has all three of these login process. The ios app authenticates the user from the device(not devise) itself and sends the user information like username, email etc whatever required along with auth type so i save this a separate user with username that is sent and one of the field as password. And the next time he sends me these details i allow him to login to the app. But now i realised this is not the best way to do. I read about FBgraph which can be used to verify the access token validity, so should i get the token from user and then verify it and get the profile information and save it in user model and give them the token.
Also i have another doubt which is, For login using email and password i allow user to login through email and password and then for the each requests the user sends me the username and password. Is this is alright or do i have to create a token in login request and send the token as response and then the user can send the token for all the other request he makes.
Sorry if it is confusing but to tell you shortly i need to know what should i do if i have all these three login process. Any help is greatly appreciated. Thankyou
There are couple things to consider when dealing with external applications like on other devices:
You should use an API to communicate with your Rails server
Your server should send an authentication token after the first user authentication using his email and password. It is not a good idea to send user's email and password for each requests.
Devise
Devise is great for authentication both in-app and for remote applications using the token_authenticatable hook. This will allow any registered user to have a unique secret token to use in order to be authenticated on your server.
More information here
OAuth2
OAuth2 is becoming the standard way to authenticate on remote services giving the user the possibility to use his Facebook account to login for example.
This would be the easier way to allow your users to authenticate using their Facebook or Twitter account (note that twitter will not give you the user's email address).
Devise can handle OAuth2 clients.
Finally, you could also create your own OAuth consumer to authenticate users using your service. Doorkeeper is a great gem to protect your API endpoints and to allow users to use OAuth2.
Conclusion
Devise is great for authentication. Using their token module coupled with OAuth2 integration could do the trick in your case.
Here is the OmniAuth wiki page from Devise
Here is the Simple Token Authentication wiki page from Devise

can an OAuth consumer app expose an API to an iOS app?

I'm creating an app for iOS that consumes an API I've created, which requires authentication and authorization of users. I'm thinking of using OAuth to let the mobile users do this with Facebook. This is an internal API that isn't meant to be exposed to third parties.
Anyway, I'm a little confused about the abilities and limitations of OAuth consumers versus OAuth providers. Basically, I want to implement "Login with Facebook" functionality from the iOS app. It seems to me that this implies that my API should be an OAuth consumer, but the problem with this is that the login flow for a web app assumes a browser -- an NSURLConnection instance isn't going to know what to do with an HTML login page, and even if the redirect to the login page was made to work by prefixing the redirect URI with the fb:// schema, surely the login form is going to pass the authorization token back to the iOS app and not my API?
So my question is: is there a way to implement my API as an OAuth consumer? If not, and I should implement it as an OAuth provider, what does logging in with credentials from another provider like Facebook even mean?
I think things are a bit mixed up:
OAuth is to Authenticate your app against facebook. A user grants
access to his FB account to your app on behalf of him
"Login with FB" is the other way round and is not OAuth: A User
with an FB account is using this data to register AND login to your
app.
The entire flow of the # 2 can be read here.

use facebook iOS client authorization on own to server

I am using facebook SSO in my iOS app and that works alright.
Now I would like to use that information - the user being verified against facebook with his uid - on my server backend. But how can I - securely - pass this information to the server?
My guess is that I'd need to send the uid and probably the authToken I got from facebook to my server? Could someone outline a general approach to that?
Even though it shouldn't really matter for my question, my server is running rails and devise for authentication. I also have facebook login working there separately, but I want to use the already done authentication from the client on the server. Confusing...
I came across this post which helped me understand the problem and solution.
Correct me if you see any issues.
The idea is to pass the auth token to the rails app. The auth token only works if both apps use the same app secret.
So the flow is like this:
iOS authenticate. Take the user's Facebook auth token and send to rails app.
Rails app takes auth token, posts it to graph.facebook.com/?auth_token=XXX. Response should be a json object of the user.
Take the user object response to find the UID and match it with a user in your database. If UID doesn't exist, create a new user and set the new UID.

For a hybrid SSO scenario using the Facebook iOS SDK, what's the best way generating a password/key for our own custom user records?

So my intention is to have a login in my iOS app that allows for either our standard email/pwd registration, or login with Facebook. We are also creating rest services to get application info for a given user, e.g. https://url/getPosts/[userId]?userPwd=foo
I've implemented SSO with fb in a web application before but I have some concerns about the security of authentication in a iOS client scenario. The key difference from what I've done before is that in a web app, I was making a server to server call to Facebook to get the access token so I was reasonably assured that the user was authenticated and the web server made privileged calls to the database. In the iOS case, I have the mobile client app making the Facebook iOS authentication request itself and the server has to somehow trust that this user from the client app is indeed authenticated against the matching user record in our database.
My question is how do I generate a durable and secret unique key from the iOS SDK so that I can create and associate a matching user record in our database for users that authenticate only with Facebook. I want this to be seamless so the user would not have to manually fill out another form, and we would just automatically create this matching user record in our db.
I could insert a record into my own users table when they fbDidLogin with Facebook, using the Facebook Id as the unique identifier, and the fb access token as the pseudo password/key for my own user record. I would have to validate the access token with Facebook to make sure it's valid before saving it as a password for the user (the user would never see this password, it would just be passed by the client app during api calls). That way when the user makes a call to our own rest api via the iPhone app we can authenticate and authorize using this secret/pwd/key.
An alternative that would make this whole question moot is to just handle the authorization logic on the client app, and check that there is a valid fb session before making calls to our own apis which I secure with just a single application-wide secret, but that doesn't seem as secure since getting that one secret gives authorization to data on all users. I'd rather authorize at an individual user level. Is that the right choice? Am I being paranoid about iOS security?
The fb access token expires so that might not seem durable, however if I enable offline access that token won't expire but creates a scarier looking oauth dialog window. An alternative to the access token is to hash the fb Id with an application secret key on the iOS client, and use that as the Facebook user's password in our db. However, that again is a single secret key that could perhaps be reverse compiled from the iOS client app?
Design for Facebook authentication in an iOS app that also accesses a secured web service
This post helped me undesrtand it more. If I am not mistaken, the flow goes like this:
User authenticates in iOS app
iOS app takes auth token, sends it to the rails app
Rails app takes auth token and sends it to graph.facebook.com/?auth_token=XXX to get back the user if authentication was successful.
Rails app takes the user info and matches/creates user in own database table. Sends some kind of authentication key back to iOS app.
iOS app saves the authentication key so it can use it to communicate with the rails app.
Let me know if I am missing anything.
Have you looked at the iOS docs for Single Sign On (SSO)? https://developers.facebook.com/docs/guides/mobile/#ios
You can share an app ID across mobile, canvas and web site and the same user auth works for each environment.
Check out: https://developers.facebook.com/docs/authentication/
Facebook Platform provides a number of ways to use the above OAuth flows in different app types, including Websites, Apps on Facebook.com, Mobile and Desktop Apps.
You just need to insert users Facebook key to your database to know if its authenticated with Facebook. Use OAuth at ios side authenticate user take users secret key send it to your rest web-service and save it with users other info.

Resources