How to implement client server API and authorization in Ruby (Rails / Sinatra)?

I need a suggestion on how to implement client-server web applications in ruby. Any guides and best practices are much appreciated. I am interested in both ruby ​​paths and necessary gems, since this is the desired platform, and in general the paths and logic for implementing such things.

I am not a great ruby ​​programmer or an experienced system designer with many years of experience, unfortunately, so I really need your help, as I still hope this thing shines in the end.

The current view of the application should look like this:

DB + Auth DB ↔ API App ↔ Other applications:

  • DB - a database or a set of databases with one database for a group of users (regions).
  • Auth DB is another database with personal user data and login information, possibly single, even if the main databases are divided between regions.
  • App API - this thing supports all the logic around data, access control and translations, it is likely to have one translation base for all applications.
  • Other applications - many different applications related to the API, it can be data providers that call the API with some data about some users and different types of user interfaces. All applications could not have their own repository of information related to the user, and work with data only through the API.

API Application: Looks like the best tool for creating Sinatra. Questions:

  • How to organize the API? Rails creates good settings for the path and structure of REST folders for models and controllers. Any tips or gems to improve your API development experience?
  • How to maintain access? Worden doesn't look like a good option, as the API clients will be the web applications themselves. So I need some kind of authentication token. How can I do that? Some kind of custom OAuth provider? The fact is that I don’t like the idea of ​​storing and passing session cookies through the API, some kind of access token transmitted with each request. it's the same

Other applications: mainly web interfaces. The logical choice for this part is Rails. The main question is how to implement client-side authentication. It’s cool to develop, but is it possible to work with a token, or is it a more suitable tool?

+4
source share
1 answer

Ok, this will be a little longer:

If you are already familiar with Rails, you can check out the Rails API gem . The project aims to remove additional crack from Rails, which is not needed for the JSON-based RESTful API.

It may sound smooth, but it has flaws. First of all, you have everything you need for the basic functions of the rails, which you can get used to, for example, respond_to . It may be a little tricky, but pretty simple when you find out which rails module originally provided the functionality typically associated with Rails in ActionController::Base .

Having said that, let me give an example of what I did for a small API project that I did last week out of curiosity:

initial situation

We have the main Rails application. Everything works fine, but mostly monolithic. Everything is served by the Rails Framework. Fortunately for us, all of the model logic comes in a gem called core . the application essentially allows registered customers to create products that are searchable through the end-user view.

The goal was to provide a RESTful API for this, which can handle concurrency and larger data files (e.g. CSV, XLS) somewhat more efficiently.

Introducing the Rails API

The purpose of the design allows me to use the Rails API gem. The main installation works like in Rails, with the exception of a script called rails-api , that is:

 rails-api new jsonapi 

The advantage for me here was that I could use core from another application, but nothing would stop me from simply injecting my own models into the jsonapi application.

This way you can use all the standard Rails attributes such as routing, etc. He follows the same convention. again, standard routes initially only respond to JSON, which can sometimes get a little confusing.

Let me give an example of an API controller that processes products:

 class ProductsController < ApplicationController include ActionController::HttpAuthentication::Token before_filter :find_product, :except => [:create, :index] def index render :json => @products end def create @product = product.new params[:product] if @product.save render :json => @product, :status => :created else render :json => @product.errors, :status => :unprocessable_entity end end def show render :json => @product end def update if @product.update_attributes params[:product] render :json => @product, :status => :ok else render :json => @product.errors end end def destroy if @product.destroy render :json => @product, :status => :ok else render :json => {:note => I18n.t("messages.deletion_impossible")}, :status => :unprocessable_entity end end protected def find_product @product = Product.find params[:id] end end 

This is nothing special. The only thing to note is the second line, in which ActionController::HttpAuthentication::Token is explicitly enabled. This means that your aPI can be protected with an HTTP token. If you want to learn more about providing APIs, I offer Ryan Bates a "Railscasts Guide . "

Basically, you provide a filter before the ApplicationController as follows:

 class ApplicationController < ActionController::API include ActionController::HttpAuthentication::Token::ControllerMethods [...] before_filter :restrict_access [...] def restrict_access authenticate_or_request_with_http_token do |token, options| # see if key is valid. end end end 

Again, pay attention to the second line, you must enable ControllerMethods manually, otherwise the controller will not know about authenticate_or_request_with_http_token .

Extension

You can know how to extend the API based on Rails conventions. It works exactly the same, except that some things are intentionally missing by default. I suggest adding JBuilder ( Railscast ) if you need more flexibility in your JSON templates.

Great, but what about customers?

Personally, there are many choices when it comes to customers. Ultimately, I find that it comes down to what you like best. I personally recommend a small node.js layer on top of the Rails API, which then gets a one-page application based on backbone.js in front of it. You can also try AngularJS if you want. You can also create another Rails application around it and call the API from your controller actions.

It also depends on which platform you want to target - the native iOS / Android application comes to mind.

The choice I made was node.js + basebone. This currently makes sense to me at that time and for the project. The node level essentially contains the token needed to communicate with the API, and the base application has a small library for communicating with the node layer. However, it can be a double-edged sword, depending on how complex your API will be. For a small example, this seems fine, but there can be a lot of code duplication to simply transfer calls from the underlying application to the Rails API.

Authentication

For authentication, you can create client API keys (tokens), and then restrict the controller logic to only accepting operations with data that are allowed with this key. You can manage the session through the node layer. Edit: This is authorization, not authentication. Nothing actually stops you from using Authlogic with the Rails API - I have not tested it, but it should work.

I admit that I have not finished this part yet - I hope that others can answer this architectural question :-)

Hope I could give some ideas.

PS: If you want to test your API, I highly recommend httpie (this is awesome!)

+4
source

All Articles