I need to provide a way to update, via API, some user informations in the mobile app like email, name and also the password(is optional; solution for that).
My problem is that because I'm using the API to change those data, how do I keep this secure ? what is the solution for updating the information only if my user is logged on the app. And how my API would know that it really is the user trying to change his informations and not someone trying to hack or something.
I'm using Rails 4 and Devise for authentication.
While signup and login generate a authentication token and send in the response.
Once the token is received by the app it can store it in local storage and will send this authentication token every time it sends a request to the server. This is how you will get to know that the user authentic and when the user logs out of the app delete that token from the app's local storage.
Related
I have a Single Page Application in AngularJS with API in Ruby on Rails (Grape framework).
My authentication system looks like this:
User create an account. Sends information to server.
Server save user in database and generate token with Devise. Token and user information is send to Angular.
Angular save token and user info in storage (angular-storage) and token is added to every request (Authorization header).
When user click log out button, storage is cleared and token is deleted in database.
My question is: it this secure, or do I need to use something like JWT? Can I send a role name (for example 'moderator') to Angular without any encoding this? (of course server will always check, if this user with this token can do something)
I also will implement doorkeeper to my app in near future.
I have an iOS app that is using the Facebook SDK to authenticate. I am then able to use omniauth, devise, and omniauth-facebook-access-token (via AFNetworking) to create a user on the server for that facebook account.
Now I need my iOS app's user to be able to "have a session" on the RoR server - I could do that by passing some information in the headers or URL for each request to be authenticated or I could use a cookie. When the app makes API requests (JSON usually), I need those requests to be in the context of the user who has been authenticated.
What is the best practice for having an authenticated RoR user on an iOS app in this situation?
Some options that come to mind:
Maintain a cookie on the client
Send a piece of information for each API request in a header or somewhere else (access_token? user_id?)
My concern is that I want to be able to add additional oauth2 authentication providers without redoing this code.
You need a token to authenticate the user, you should also keep sending the csrf-token in order to keep your app secure. Take a look at this question, and see how the csrf is handeled in its answer.
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.
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.
Goal:
Allow a user to authentication with Facebook into an iOS application which requires access to a protected web service that I'm running.
Assumptions:
There is a native authentication (and registration) system in place for those users that opt not to use Facebook for sign in.
Details:
Assume we want to offer the option for a user to sign in with Facebook without creating a separate account/credential for our system.
Because we support our own native auth mechanism (username and password) we have our own user IDs and issue an authentication token that is used for subsequent interactions after the initial credential validation.
I'm surprised that Facebook doesn't have best practices for this in their developer documentation. All the existing documentation is either assuming you are building FB auth into a website, or a standalone mobile app with no service that requires authentication.
Here's my initial thoughts on how this would be designed but want validation on whether it's correct.
Client pops the Facebook iOS Login
UI User signs in with Facebook credentials and gets access token
iOS App passes access token to our server
Our server talks to FB graph API using access token to (a) validate the token and (b) get the FB user ID for that access token.
e.g. Our server would call https://graph.facebook.com/me/?access_token=XYZ which would return profile info in a JSON object
Assuming it's valid, our server extracts the User ID from the JSON object and checks whether the user already has an account. If so, we issue our own auth ticket to client to use for that session. If user doesn't have an account, we create a new one with the Facebook User ID, assign our own unique UserID and issue our auth ticket.
Client then passes auth ticket back on subsequent interactions that need authentication.
This seems like the right approach to me but not sure if I'm missing something insanely basic and going down the wrong (complicated) path.
I just dealt with this myself, and here's the part that bit me:
In your step 5... It's possible for a user to register for an account with you entirely separate from their Facebook ID, right? Then some other time they log in with Facebook.... And you just created them a second account and lost their first one.
There needs to be a way to be logged in to your web service, then log in to facebook, and capture the association between the facebook ID and the local account.
Apart from that, your plan sounds solid.
Update: Facebook has added a doc outlining such a scenario HERE
Use https to transmit the auth token to your server, as stated by Facebook
Sharing of Access Tokens
Our Data Policies explicitly prohibit any sharing of an Access Token
for your app with any other app. However, we do allow developers to
share Tokens between a native implementation and a server
implementation of the same App (ie. using the same App ID) as long as
the transfer takes place using HTTPS.
One problem I can see with this strategy, is that somebody can give you an access token obtained for a different facebook app. As far as I know, there's no way to verify that the access token is for your application, so you'll just go on and use it.
It doesn't sound very harmful, though. Generally people/apps try to protect the access tokens, rather than sharing them.
One possible exploit of this would be, for somebody to create their own site or mobile app, obtain access tokens for their users and try to authenticate them, using your API. If this succeeds (the user is has a facebook account in your site), the malicious site will be able to use your API impersonating the user.
It's a bit of a long shot, but I think it could work.
Edit: It looks like there is a way to validate the access token after all. See the answer by #Daaniel on question Get application id from user access token (or verify the source application for a token).
your solution totally works.
Maybe an alternative: why not just get the email on the client from the initial social service request and send to your web service? The web service could just store the email, and maybe a social_provider as well. I understand that your web service will not be able to validate where the email came from, but isn't there a high-trust relationship between your web service and your client? If there is, seems like you can depend on the email coming from the right place. Someone please let me know what obvious thing I'm missing that makes the email-based approach silly...