Looking for suggestions for building a secure REST API within Ruby on Rails - 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.

Related

How to secure basic methods like user creation in an API

I'm learning about developing APIs with rails, but I can't find how to secure the base methods like user creation. Let's say I have a rails backend API and a frontend mobile app. I want the app to be able to make API calls to create a new user. Off course, not everyone should be able to create a new user, so it should have some kind of authentication. I could use basic or digest authentication (doesn't really matter, because I'll definitely use SSL), but then I would have to hardcode the credentials into my app. If the credentials are discovered somehow, I would have to change them, but that would mean that all instances of the app are no longer authenticated and they can't create users anymore.
The things I would like to have:
Only my apps should be able to use the user creation calls.
It should be easy to change the credentials, or the credentials should change automatically over time. If they would involve the date and time for example, it would be harder to crack.
It should be impossible (or VERY hard) to beat the system behind it, while having knowledge of a couple of the credentials over time.
Would it be possible for example to let my apps generate public and private key pairs at random and use them? What's the standard way of securing these calls?
Thanks in advance,
Rugen Heidbuchel
I could share my own experience:
https protocol communication with API. That is your last sentence about private/public keys, all is built in into https.
Doorkeeper (we combine it with Devise) gem for Oauth (github accounts in my case) as authentication, while you can use pairs of user/passwords instead.
CanCanCan gem as authorization (User creation restriction is about authorization and not authentication)
Set of that three tools should provide essential security level for your API. I believe cancancan could be under discussion, while devise is mostly industry standard.

Using OAuth2 to permit users to authorize as a global user

Apologies for the oddly worded title, however I could not come up with a better one.
My application should be able to perform a limited set of actions on an Enterprise Google Apps system. Users submit requests to the application, the application interprets these requests and then makes requests to Google resources as necessary.The point is that users, who normally do not have permissions to access/modify the google apps resources, will be able to use this application to do so in the limited ways that it allows.
My problem lies in the apparent fact that the OAuth2.0 authorization flow seems designed to allow third party client applications to authorize themselves as the user and access/modify the user's google resources, rather than a global administrator's. In other words, a normal API key type deal. Unfortunately it seems that Google's AdminSDK will only work with OAuth2 authorization.
Is there a way to use Google's AdminSDK API with OAuth2 (permanent access token, maybe? API key?) to do what I want? Or is there a different API I should be trying? The now-deprecated Provisioning API seemed to be able to do this.
I feel like there should be a way for the application to just pull something out of a secrets.json or secrets.yml, include that in the API authorization request and have Google servers recognize and grant access to the application without the user ever needing to see what's going on.
For the record I'm using Ruby on Rails, though I don't think that affects the question very much.

Will using a master login username and password when implementing web services considered secure

I am working on an asp.net mvc-4 web application and I have started implementing some web services which provides statistical information about my site. But to make sure that only authorized and authenticated consumers can call and consume the web services I am thinking of defining a master login username and password for each consumer, and when a consumer sends a web service request he should include these master login username and password (stored as a hash value ) in the web service calls.
For example the web service link to call specific web service from my web site will look as follow:-
/web/json/statistic/getsummaryinfo/areacode?j_username=masterusername&hash=D012B772672A55A0B561EAA53CA7734E
So my question is whether the approach I am following will provide a secure solution to my web services and to the consumers? OR my approach have security holes I am unaware of ?
:::EDITED::
I am using the WebAPI controllers to implement the web services inside my asp.net mvc-4.**
Best Regards
There are a few ways to make sure things are secure.
http://techcrunch.com/2012/11/08/soa-softwares-api-management-platform-and-how-it-compares-to-its-sexy-counterparts/ This article just came out today highlighting some API tools. I'm not sure how big you are or are planning to be, but if you're looking for scale, these tools seem to be pretty popular (note: I haven't had a large scale API project myself, so I haven't used these).
You can use something like ServiceStack to build your API layer. It has authorization and authentication built in with a boatload of authentication providers. It scales well and, after a call to authenticate, is session-based so you don't have to authenticate each call.
You can use "signed" requests. Signed requests often look something like: "take all the parameters for the request as a querystring, append a 'secret consumer key' to the end of the request', and then sign the request by appending the md5 hash of the results (without the secret key!!) to the request." This is a safe way of doing things because even if the request is made client-side (AJAX) it is generated server-side using a secret key. So you can ensure that things weren't tampered with.
You can go the oauth/token route (which often still uses method #3 above).
You can go with a simple API key that can be revoked (again, fotne used with method #3). bit.ly uses this method I think.
Option #2 is my favorite. I like ServiceStack. But to be honest the learning curve for your first project can be a little steep.
A master username and hashed password feels weak to me, so I'd strongly consider at least looking around at how others are doing it.
HTH
I do not consider your way to be safe. If I could listen on the wire and cache the request I will have the login an the password to the service. There even does not matter if the password is hashed or not. I like the point 3. in Eli Gassert's answer. It sounds very useful and light weight and you are not exposing the password because it is hashed "somewhere" in the request.

allow secure form data to posted to my rails api

I am creating a rails app which will help out businesses. These businesses have thousands of employees who will need a user account on this app.
I would like the business to be able to implement a form on their local intranet which can be submitted by users when they want to sign up to my app. This form posts some semi-sensitive fields to my rails API about their currently logged in user, such as their name and email address which would be populated by their server side code.
I can use this information to aid in the process of signing the user up to my site, and in identifying which business they actually do belong to. However, the form information along with an API key will need encrypting to avoid any data being stolen or a business being spoofed.
What methods of encryption are there out there that can be implemented on a variety of different languages and frameworks, and that involve the least amount of fuss to implement for the business?
OPEN SSL with Public and Private key encryption does seem like a good choice, but this does require some exchanging and creating of keys and can get complicated. Are there easier options?
Why not just have them post to your site over TLS/SSL? They can include their API key. SSL is about as cross-platform and cross-language as you can get. Any decent server-side language can make an HTTP request, so if you want them to send the request from their backend instead of directly from the form, that is easy enough.
You should use SSL to secure the transport layer as well as built-in Rails form protection (assuming you might do your own forms). Assuming this is intranet, you can generate an SSL certificate and run your Rails app through https://
Edit1:
You can also roll out a full API with OAuth/OpenID to authenticate users and authorize other applications. It all depends on if you own the data, users and ecosystem overall.

Building A RESTFul API, How To Do Authentication

I am building a RESTFul API and wondering what's the best way to do auth? Users will need to authenticate. I know of three ways:
1.) Pass API key in every RESTFul requests:
http://api.mydomain.com/api-key-here/get-users
This is nice because developers can immediately start using the API by simply copying URL string into the browser. Are there any potential security risks though?
2.) Every request passes the API key in the header of the request.
This seems to be more secure, but developers can't make requests via their browser. CURL is required.
3.) oAuth
I must admit I don't know much about it, but seems very popular. My concern is that its a barrier for developers to start using the API. They first must be familiar with oAuth, and have it setup.
Thoughts? Thanks greatly.
If your concern is burdening developers with a high cost to entry, I suggest basic auth, but running your API over https.
I do this with Diligent Street and it works really well. I use an API Key and couple it with a Secret as the username/password combination for basic auth.
I have employed the technique found here: Build a RESTful API. This solution uses an MD5 hash of your API ID, API secret and the UNIX Time stamp and passed in the HTTP header. This authentication method is the same used by Mashery’s Authentication.
This link references and contains a full blown starter kit for creating an API that has Auth, Membership and*API Usage Metering* along with a supporting EF database.
As for testing the service you can use RESTClient to execute HTTP calls with custom headers instead of using Curl.

Resources