#352 Securing an API
There are many approaches to locking down an API. Here I start off with HTTP Basic authentication then move on to generating a unique token which can be passed through a URL parameter or HTTP header.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
How do you autocomple the "restrict_access". It looked like it cycled through a few options...
Hi Ryan, lately I've seen a lots of development railscasts for rails API's. What are the best practices to test API's and versions? Because you don't want to break anything down if you implement new features, change the json format later on. What i would like to know is how you guys test your json api's input and output and even with versioning. Maybe this would be a good idea for a railscast.
Thanks
Hi Anket, I have a same problem over here.
Hey Zolzaya,
I did some research myself. I think i will try to split my controller and response tests with Capibara gem. What I test in my controllers are the controller logic. I still need to get started with testing on my json responses. Ill give you a update...
One thing i have to use :format => "json" to get json responses, it would be great if it went automatically.
One more thing check RABL git how to test your RABL responses.
https://github.com/nesquena/rabl/wiki/Testing-with-rspec
Here you go mate ;)
In my previous post, forget about Capibara.
I got a sample how you could test some controllers..
In my setup I use; factorygirl and RSpec.
I hope this helps you..
It would be great to make a screencast about rate limiting.
that would be awesome
If every API users has a API_KEY or Token, you can have a column like 'requests_count' and increment it with each request. When you reach lets say 500, you can return a 500 or something and have rake tasks reset the count after 24 hours or so.
Very useful screencast Ryan.
I'm using a
generate_access_token
in myUser
model to create anaccess_token
for each user so that my app can do "Remember Me" using a cookie (so they don't need to login again) as per screencast #274.Would I use this same
access_token
field for the user to be able to call my API?Can you see any issue in doing that?
Or should they be different?
Try rack api throttling with a rack middleware. I forked it to limit throttling to a certain path: https://github.com/christoph-buente/api-throttling
...but would I use the
access_token
field to identify the user calling the API?authenticate_or_request_with_http_token did not work for me, use authenticate_with_http_token (http://apidock.com/rails/v3.2.3/ActionController/HttpAuthentication/Token/ControllerMethods/authenticate_with_http_token)
Great cast, really helped me secure my API. One question, how can I pass a token and userid with a request for authenticate_or_request_with_http_token so I can always match a token to a user?
I initial had some trouble implementing this together with Mongoid. It turned out that the problem was in the
mongoid.yml
configuration file. When I changedto
Everything worked properly. I guess this is because having a proxy server messes with the meaning of
localhost
.@Matthew Ford(Im sure you found this by now)
For anyone who followed the rails api gem cast you might have problems adding in the:
"authenticate_or_request_with_http_token"
To use this you will need to add this line:
include ActionController::HttpAuthentication::Token::ControllerMethods
Please could you give an example of an activeresource model, which calls a protected RESTapi? With curl all is fine, but how can I deliver the token with a activeresource model?
Put this at the top of your model which inherits from
ActiveResource
In Rails 4 beta1, I'm getting a "HTTP/1.1 422 Unprocessable Entity" error when attempting a post request to an API. The controller is raising an ActionController::InvalidAuthenticityToken error.
Do I need to somehow disable request forgery protection for APIs?
Found the answer in the Edge Docs here: http://edgeapi.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html#method-i-protect_against_forgery-3F
...others might benefit if this is included in the show notes.
Hi, How do I test this using rspec?
This part>
Here is a nice answer if your are doing controller or acceptance tests.
If you're like me and went with Rack::Test::Methods (see this post section 'Testing your API', some examples here as well), here's the solution (which was a pain to figure out ...) :
And here is a little helper to keep things DRY :
I have a readonly api hosted on heroku. I also built an android client for this api.
What I want is that only my android app should be able to consume this api.
What is the best possible solution I can apply. Do I need ssl certificate?
Thanks in advance!!
I don't know much about android, but I would assume you can get the device Id somehow. couldn't you use that as your token and then have your client just send the device id along with the request?
I know this is a little late but I recently released a gem for this exactly this purpose. Do check out Cadinsor.
Note that
authenticate_or_request_with_http_token
will return 401 messages as text/html- not what you want for a JSON API.I handled this by overriding
request_http_token_authentication
in the controller: