Ruby on Rails API Authentication
If you are building any kind of API with Ruby on Rails you are going to have to handle authentication if you want to secure your endpoints. If you're using devise with it's pre-built authentication you'll see that when it comes to managing the Authentication of an API endpoint devise falls slightly short. In this post we will show you some of the options you have with securing your Rails API endpoints and how you can integrate them into devise.
1.) Simple Token Authentication
If you have a simple requirement where you just want basic authentication via supplying a token to the client then look no further. This gem is as simple as the name itself. You can check it out here .
The way it works is you run a simple command that pretty much generates the migration file for the user model.
rails g migration add_authentication_token_to_users "authentication_token:string{30}:uniq"
This essentially adds a authentication_token
field yo your user model. You then add a macro to your user model like so.
class User < ApplicationRecord acts_as_token_authenticatable # ... end
Then you add another macro to your ApplicationController
acts_as_token_authentication_handler_for User, fallback: :none
Then any endpoint inheriting from the ApplicationController
will work with token authentication.
On the client to authenticate with the endpoint the user has to pass the X-User-Email
and X-User-Token
in the header. That's pretty much it for the simple token authentication gem. Since the gem already works with devise all your devise utilities should work great.
If you are interested in learning more about this authentication method then you can check out our free video covering this gem.
2.) JWT Authentication with Devise
JSON Web Token is all the rage when it comes to api authentication. This is because it makes life convenient when it comes to securing your API. How? Well If you are building your API for multiple clients, by using JWT you have 1 method of authentication that will work across all platforms whether you are authenticating a client in the browser, a mobile application, or any kind of server side service consuming data from your api.
It supports a ton of features and allows you to generate a token for the client on the fly without having anything stored in the database, because the token itself contains the session information. You can generate a token and embed any kind of information into it. For example
{
"user_id": 1,
"exp": 1516239022
}
Gets turned into
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MTYyMzkwMjJ9.UCTyi_gPUNhfeelaWxMTfnPtRtNByDUMxKTRpkyewQI
This is a cryptographically secure token generated using a secret key on the server. Which means it can only be decrypted by any party with the secret key. Which means if this secret key gets compromised your authentication token method will be compromised.
The client then embeds this token in the header usually called Authorization
. Each request needs to be authenticated on the server using this token. Which means the token sent by the client needs to be decoded on the server and the data can be verified on the server side. You can check out more about the basics of JWT in our free video.
In the video we show you how to generate a basic JWT token using the jwt
gem. We event show you how to fulling develop a authentication solution using JWT.
Once you start working with JWT in your Rails API you'll realize that it doesn't work with your existing devise setup. Which is why we recently released 2 episodes showing you how to integrate your JWT solution with devise by creating a custom devise strategy. You can check them out below. They're member's exclusive so you'll need to become a member for $9 / month, however if you just want the code example it's available for free.
If you are building an API with Ruby on Rails and don't know where to start, I would recommend going for JWT. Since JWT is more future proof and there is a standard that you can follow. Having a standard can be useful because you have 1 authentication system that works in many platforms / languages. So if you are building microservices in multiple languages you can use the libraries for the language of your service and have different services use 1 authentication system that work with one another.
JWT as a solution can grow as your application grows in complexity. You can start off with a database-less JWT solution and later on add the ability to store the token in the database so you can expire tokens at will.
On our site we use JWT for many things, authenticating our users, service-to-service communication, and authenticating video plays. Since we can embed data into the token itself this makes it very flexible for many kinds of things.