Sending secure POST data to RESTful API without authentication - ruby-on-rails

I am working with an Arduino that I want to send data to a remote or local Rails RESTful API of mine. When building its front-end, I can login with devise and authenticate. But I am wondering what happens when you want a third party device to POST data to the backend ?
One choice could be to use random generated long hashes as keys, as Twitter does (a client key for example and an API key) which of course is not secure but decreases the chances someone will POST data easily to another account.
However, If I am right, the data will be sent over an http connection so they could be easily sniffed. There is no problem sending temperature data, but If someone decides to send RFID IDs and names etc. it could be a vulnerability.
How could I send data with a POST request to a RESTful Rails backend API:
authenticated?
secured?

authenticaed?
You will need an endpoint that the 3rd party can call (let's call him Zed). Zed sends a request (POST) to that endpoint with his email address. Devise then sends an email to Zed, with a confirmation link that contains a confirm_token. Zed clicks the link, which opens a page where he can enter a password. Once entered, he is logged in and an auth_token is stored against his user id. Subsequently he can use that auth_token to make further requests by passing the token in an Authorization header. The 'confirm_token' is throw away (you can set it to auto-expire after a given time period).
Obviously this requires Zed to manually create his account and login. Even if you setup a 3rd party 'developer program' you still need those developers to sign-up and generate tokens for them that they can pass in requests to your api. All of this should of course be done over https. Devise provides almost all of this capability out of the box.
secured?
HTTPS helps with the 'sniffing' aspect. The method above is secure, since only people who provide an email account they have access to can create accounts and get tokens that they can then user for later requests. However, you could use mobile phone number/sms as a second factor (google 2-factor authentication).
Without authenticaion - well, sort of
The only other option I can think of is that you issue known users a 'signing key'. They sign (encrypt) their request with this key. Since the key should only be known to them and can only be decrypted by the server using the matching public key, the data can be sent over HTTP. If anyone sniffs it, they almost certainly cannot crack the key to see what the real data is. All they can really do is mimic the request and keep sending that same request to the server repeatedly in a DOS attack.
But you still have to solve the problem of how do you verify WHO you are giving keys to - ie you still need to verify who Zed is somehow. Do you plan to do that offline and then email that 'verified' individual their private key? Using RoR, I still recommend sticking with Devise as most of the grunt work is done for you already.

Related

How to identify/authenticate users with socket.io

Trying to wrap my head around some logic.
I'm creating a simple turn-based game with Node.js and Socket.io. The idea is that each user 'logs' in via some framework front-end system (quick RubyOnRails scaffold) and then once they are logged in, they can refresh the page and close the browser and they remain logged in as usual until they log out.
I want this functionality of persisted authentication with a web socket so that while 'in-game' users can close their browser and come back at any point and I can relay to other users when a player is disconnected/connected. A player could also join and leave games but could obviously only be in one at a time.
My guess is that upon each page load the new socket.id that a user connects with is needing to be stored in the database inside the users table perhaps? Or is there a simpler way to tie a current user to a socket.id?
Am I going about this the wrong way? I can't seem to find any good examples/documentation similar to what I want. Some code examples or a starter app to push me in the right direction to achieve the basic idea of what I am trying to accomplish would be amazing.
You can make use of tokens for this purpose. A good option would be using JSON Web Tokens (JWT).
JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA.
- https://jwt.io
One possible way to use JWTs in your case goes like this:
User logs in
A new JWT is issued by server when a successful login happens
This JWT is sent to the client and is stored client side (e.g. cookies, local storage, etc.)
On every socket connection event, client sends this token to the server for validation
Server accepts connection only if the provided token is validated and closes the connection otherwise
The main advantage of using JWTs is that there is no need to store additional data server side because tokens can be validated using cryptographic methods such as digital signatures.
More on JWTs: https://jwt.io

How to only allow my own app to access my API

I am building an API for my rails app. Through that API I will log users in and allow them to interact with their data.
On top of that users authentication, I will also like to make sure only my iOS app has access to the API, and eventually my own web app.
I want to make sure no one else will be using the API, so on top of the user authentication, I will like to protect my API with a token for each of my apps.
How do you usually solve this problem? Would I have to pass that token over on each call in order to authenticate that the call is coming from a valid client and identify which client it is (web vs iOS).
I will very much appreciate any pointers or if you know of an article explaining how to deal with this.
As you are already using jwt's to authenticate your user, why not just use the functionality of jwt to include additional information in the token, in this instance some form of hashed string that you can verify server side if it is a valid "client id".
On each request you could refresh the string.
Kind of dual authentication in each request. the user and the client.

Best way to create an user authentication in Objective-C iOS App

I'm currently developing my own service with its own app. The service has a backend JSON API that the app uses to communicate.
Now, since an iOS app does not have sessions or cookies, I was wondering how I would go about creating a user authentication/login for my app. Should I simply locally encrypt the password/username and then, for every action (such as posting a new entry), send the user/password with the request (which seems unsafe), use a token-based system (app receives a token from the service when authenticating, saves it locally - encrypted - and then sends it with the request), or something else? Should I try to implement OAuth for my service?
I'm using the CodeIgniter Rest API for the backend.
Thanks!
My preference includes both. I normally use oauth2 with a bearer token setup (if I remember correctly). I ask for a username/email + password, encrypt the password client-side and send it to the server via Basic Auth in return for an access token which I can send on all consecutive calls. That way I can always revoke access to the backend by invalidating the access token. Oauth2 is much easier to implement than Oauth 1.0a and by following the specification, it is easy to open up your api for 3rd party apps later.
The Oauth2 access token can be send as a GET parameter, but lately I start to think sending it as a header might be preferable, to distinguish better the meta parameters like an access token and data parameters like it's or a model's actual data.

OAuth: OAuth implementation use case

I have a webapp which does a lot of ajax requests with the php server and database server. I have also created an iPhone app and an Android app, which have been working as offline apps till now.
Now I want to create an API which will be used to sync data between web server and smartphone apps. Should I be using OAuth for this? What I have read about OAuth - it seems like it is used if I want to open my API to be used by third party apps. But here I just want to ensure secure transfer of data between API and my own apps.
Can somebody shed some light on this?
The main usage of OAuth is to make third-party apps authorized to access private resources of a user on a website without giving user credentials to the third-party app. For example, suppose that Twitter wants to get the list of contacts from your Yahoo account. The traditional way is to give your username and password to Twitter. But with OAuth, you give them a temporary token (called Access Token) which authorizes Twitter to access your contacts on Yahoo for a limited amount of time (until either this token expires or you, as the owner of private resource, explicitly revoke it).
That said, OAuth is not about securely transmitting data on the web. That's another story which is usually achieved using SSL. Even when you use OAuth, you have to use SSL alongside to make sure data is sent and received securely.
So in your case, you have to see what the API is used for. If it's public API which doesn't give any private data to the callers, there is no need to use OAuth. If the API is for accessing private resources of individual users however, You may consider using OAuth. If you opt to implement OAuth, you may allow other third-party apps to access your API in future without any concern.
Well a lot depends on how you are securing your API. Is your API open to public specially the post urls? If your data is not something which every user should see, then how are you checking the authentication of the user credentials?
Most the important thing is that we should avoid sharing the username and password over the wire to check for authentication all the time. This means, your API should not require username and password to validate if the user is valid. Which you can do by sending the username and password from mobile or device id or some other thing.
In such situation, the OAuth server comes to the rescue. Basically, on one URL a user will send his username and password to get his access token. Once that is acquired, we can use the access token to validate each request and take necessary actions.
You can refer the videos where I have implemented OAuth server in Laravel 5 using bshaffer which is one of the best OAuth library for any PHP framework to user. https://www.youtube.com/watch?v=0vGXbWdtjls

Design for Facebook authentication in an iOS app that also accesses a secured web service

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

Resources