In which cases do you need to implement these complex token authentication on devise (Rails 3.2) - ruby-on-rails

I'm building a Rails app on Heroku.
I installed devise to manage user authentication on which I wanted to add "token authenticatable".
I basically used this tutorial and it works great
However, I ran across more complex tutorial about token authenticatable like these two ones:
http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/
http://mojoware.com/posts/mobile-rails-api-with-devise
I don't understand why they get much more complex than what I implemented? They seem to mention "mobile" stuff so does that mean it's a more complex way to use "token authenticatable" because it allows to authenticate in more cases of use such as on mobile?
Really in the dark so I appreciate any help.

For the most part, authentication in a (native) mobile app works pretty much the same way as authentication through a browser: the user gives his credentials, these are sent over the wire to the server/app, and the app responds by giving the user a 'token' representing an authenticated session.
The main differences: browser-based clients will generally submit said credentials using HTTP POST of an HTML form, using application/x-www-form-urlencoded. The returned token is usually given as a session cookie, which the browser presents with every subsequent HTTP request.
Native mobile clients, on the other hand, while functioning as the browser aren't restricted to the HTML way of doing things, and most of them don't use cookies.
The typical mobile client uses a Web service API. Most APIs are designed to be as stateless as possible (unlike browser/cookie-based sessions).
Most Web service APIs also need/want to be able to send & receive as much hierarchical, complex data as possible, using as little bandwidth as possible. Hence, they favor more compact representations of structured data such as JSON (or in some cases, BSON).
In most cases, as well, it is undesirable to present the authentication token as a URL query parameter (or, if you're sending over a JSON payload you might as well include the token in there).
For that reason, the stock Devise session controller and token authentication mechanism is inadequate, and hence numerous examples of how to provide alternative, REST-ful or JSON-based authentication that extends Devise.

Related

Token vs Cookie for SPA

I'm using devise_token_auth for a rails application with react on the frontend and rails as the backend acting as the backend.
In the readme the author states that
If you're building SPA or a mobile app, and you want authentication,
you need tokens, not cookies.`
Why? I understand the basic differences between tokens and cookies, but don't understand why you couldn't just use cookies (simply including the headers with any XHR requests)?
There are a few major reasons.
First of all most SPA's are designed as stateless and using cookie based authentication is not stateless. Using cookies also makes every request take a little bit longer because there is a lookup on every request.
Cookies are also tied to a domain. Most SPA's use multiple services across multiple domains which is a no go with cookie based authentication. This also applies to SPA's which have a web app and mobile app, using token based authentication means scaling this is much easier.
Tokens can also be used to store data and only need to be generated once, after that there is no work involved except for the server reading the token. This means you can store user permissions in there etc and the server can get this information with very little work.

Rails: Auth Token in Full, Non-API App?

I'm building a rails app and I want to have token authentication but I don't want to build a separate API, I want it to be all integrated into one rails app.
Is this possible? Every single tutorial about token authentication I can find is about APIs, and every API seems to need to be its own standalone entity running in parallel with the main app.
Is what I'm asking impossible, or stupid? If not, how do I do it?
For "classical" web applications you want to use session based authentication instead of tokens.
Token based authentication is stateless and requires the token to be sent along with every request. This is done via HTTP headers or by placing it in the request body. Which is how you use API's.
For a classical web application there is simply no practical way to send the token along on GET requests.
Session based authentication instead works by using cookies to store the authentication claim (usually a user id). While you could use a token and store it in the session its just an overly convoluted solution since it defeats the whole purpose of token based auth.

API Design - securing user registration API endpoint with multiple clients

I'm currently working on a proof of concept system which involves a backend API which is used by multiple possible client applications, including mobile clients and a isomorphic React client.
I've largely taken care of authentication and authorization, the only remaining problem (that I can see at least) is the route to register users - POST /users/, as it is public with no authorization required. My main concern is protecting that route from malicious spamming beyond implementing CORS and rate limiting.
E.g. curl -X POST -d "{ email: 'hello#gmail.com', password: 'nahnah' }" http://host.com/api/v1/users
What would my options be here?
One solution I've come up with is force the SPA to submit the sign up form to an express route within the server that serves the SPA (it requires SSR) to make the API call on the server, meaning the browser's network tab will have no record of the API call. This would mean I'd also have to implement a CSRF token in the SPA.
Also, is this is just generally a bad idea?
I would recommend including a captcha in your registration.
The spamming problem you describe actually consists of 2 parts:
Someone could endlessly spam your endpoint, draining resources of legitimate users. This is can avoided using rate limiting, Denial of Service detection methods, or hiding behind a CDN.
Someone could register a large amount of invalid users in your application. A captcha will stop any requests that arrive at your API from actually getting registered.

Authenticating Web and Mobile to Rails API

I am reading the Service Oriented Design with Ruby book by Paul Dix and many posts here but am left with many questions surrounding authenticating users and the application.
I want to have api.site.com as a RESTful Rails app serving up JSON. Secure.site.com will be a web app (maybe Rails or maybe PHP) that will consume the service. Also a mobile app such as iPad will also consume it.
So is the first step to build in a level of auth so that only my web app and mobile app can consume the service? Then once the calling app has been authenticated, both these apps will have users who want to CRUD their data so then authenticate them as well?
I've read about Http basic, digest, tokens, oauth and many plugins but am having a difficult time narrowing down the most flexible and reusable way. For now this is simply learning so I would like to stay away from plugins so I can learn the code better.
Can my web app use normal sessions like I'm familiar with and then the mobile use their equivalent to sessions. At that point I still have no authenticated the calling app though. Http basic seemed like I could use it from both, but I didn't see a way for my web app to use a normal login form and logging out seemed like an issue.
I would suggest two solutions for you.
Use a Gem like devise for login system and inherit the devise registration and sessions controller to make it respond to JSON requests.
Create your own simple authentication and use respond to HTML and respond to JSON for separating web and mobile login
Iam not totally sure whether a mobile device maintains a session (please look around) but u can always use a token authentication system if it doesnt.

Looking for suggestions for building a secure REST API within Ruby on Rails

I'm getting started on building a REST API for a project I'm working on, and it led me to do a little research as to the best way to build an API using RoR. I find out pretty quickly that by default, models are open to the world and can be called via URL by simply putting a ".xml" at the end of the URL and passing appropriate parameters.
So then the next question came. How do I secure my app to prevent unauthorized changes? In doing some research I found a couple articles talking about attr_accessible and attr_protected and how they can be used. The particular URL I found talking about these was posted back in May of '07 (here).
As with all things ruby, I'm sure that things have evolved since then. So my question is, is this still the best way to secure a REST API within RoR?
If not what do you suggest in either a "new project" or an "existing project"scenario?
There are several schemes for authenticating API requests, and they're different than normal authentication provided by plugins like restful_authentication or acts_as_authenticated. Most importantly, clients will not be maintaining sessions, so there's no concept of a login.
HTTP Authentication
You can use basic HTTP authentication. For this, API clients will use a regular username and password and just put it in the URL like so:
http://myusername:mypass#www.someapp.com/
I believe that restful_authentication supports this out of the box, so you can ignore whether or not someone is using your app via the API or via a browser.
One downside here is that you're asking users to put their username and password in the clear in every request. By doing it over SSL, you can make this safe.
I don't think I've ever actually seen an API that uses this, though. It seems like a decently good idea to me, especially since it's supported out of the box by the current authentication schemes, so I don't know what the problem is.
API Key
Another easy way to enable API authentication is to use API keys. It's essentially a username for a remote service. When someone signs up to use your API, you give them an API key. This needs to be passed with each request.
One downside here is that if anyone gets someone else's API key, they can make requests as that user. I think that by making all your API requests use HTTPS (SSL), you can offset this risk somewhat.
Another downside is that users use the same authentication credentials (the API key) everywhere they go. If they want to revoke access to an API client their only option is to change their API key, which will disable all other clients as well. This can be mitigated by allowing users to generate multiple API keys.
API Key + Secret Key signing
Deprecated(sort of) - see OAuth below
Significantly more complex is signing the request with a secret key. This is what Amazon Web Services (S3, EC2, and such do). Essentially, you give the user 2 keys: their API key (ie. username) and their secret key (ie. password). The API key is transmitted with each request, but the secret key is not. Instead, it is used to sign each request, usually by adding another parameter.
IIRC, Amazon accomplishes this by taking all the parameters to the request, and ordering them by parameter name. Then, this string is hashed, using the user's secret key as the hash key. This new value is appended as a new parameter to the request prior to being sent. On Amazon's side, they do the same thing. They take all parameters (except the signature), order them, and hash using the secret key. If this matches the signature, they know the request is legitimate.
The downside here is complexity. Getting this scheme to work correctly is a pain, both for the API developer and the clients. Expect lots of support calls and angry emails from client developers who can't get things to work.
OAuth
To combat some of the complexity issues with key + secret signing, a standard has emerged called OAuth. At the core OAuth is a flavor of key + secret signing, but much of it is standardized and has been included into libraries for many languages.
In general, it's much easier on both the API producer and consumer to use OAuth rather than creating your own key/signature system.
OAuth also inherently segments access, providing different access credentials for each API consumer. This allows users to selectively revoke access without affecting their other consuming applications.
Specifically for Ruby, there is an OAuth gem that provides support out of the box for both producers and consumers of OAuth. I have used this gem to build an API and also to consume OAuth APIs and was very impressed. If you think your application needs OAuth (as opposed to the simpler API key scheme), then I can easily recommend using the OAuth gem.
How do I secure my app to prevent
unauthorized changes?
attr_accessible and attr_protected are both useful for controlling the ability to perform mass-assignments on an ActiveRecord model. You definitely want to use attr_protected to prevent form injection attacks; see Use attr_protected or we will hack you.
Also, in order to prevent anyone from being able to access the controllers in your Rails app, you're almost certainly going to need some kind of user authentication system and put a before_filter in your controllers to ensure that you have an authorized user making the request before you allow the requested controller action to execute.
See the Ruby on Rails Security Guide (part of the Rails Documentation Project) for tons more helpful info.
I'm facing similar questions as you at the moment because i'm also building out a REST api for a rails application.
I suggest making sure that only attributes that can be user edited are marked with attr_accessible. This will set up a white list of attributes that can be assigned using update_attributes.
What I do is something like this:
class Model < ActiveRecord::Base
attr_accessible nil
end
All my models inherit from that, so that they are forced to define attr_accessible for any fields they want to make mass assignable. Personally, I wish there was a way to enable this behaviour by default (there might be, and I don't know about it).
Just so you know someone can mass assign a property not only using the REST api but also using a regular form post.
Another approach that saves building a lot of the stuff yourself is to use something like http://www.3scale.net/ which handles keys, tokens, quotas etc. for individual developers. It also does analytics and creates a developer portal.
There's a ruby/rails plugin ruby API plugin which will apply to policies to traffic as it arrives - you can use it in conjunction with the oAuth gem. You can also us it by dropping varnish in front of the app and using the varnish lib mod: Varnish API Module.

Resources