Create a Ruby on Rails 5.2 API with Auth0 Authentication
Storyblok is the first headless CMS that works for developers & marketers alike.
In this tutorial, we will walk you through the setup of a Ruby on Rails 5.2 API Application combined with Auth0. After this, you will have an API with private and public routes than you can use for our tutorial on "How to add Auth0 to Vue.js in 7 Steps" which allows you to make authenticated calls on this API. During this tutorial, you will learn how to set up a custom Concern, a JSON Web Token verification, a Private and a Public route that returns JSON.
Requirements
- Ruby installed -> 2.5.0p0
- Rails installed -> 5.2.0
- Auth0 Account
What is Rails
Rails is a web application development framework written in the Ruby programming language. It is designed to make programming web applications easier by making assumptions about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks. Experienced Rails developers also report that it makes web application development more fun. You can read more on their website.
What is Auth0
Auth0 provides authentication and authorization as a service. They are here to give developers and companies the building blocks they need in order to secure their applications, without having to become security experts. You can connect any application (written in any language or on any stack) to Auth0 and define the identity providers you want to use (how you want your users to log in). Based on your app's technology, choose one of our SDKs (or call our API) and hook it up to your app. Now each time a user tries to authenticate, Auth0 will verify their identity and send the required information back to your app. If you want to learn more about what Auth0 check out their getting started overview.
Auth0 Setup
Before we start our dig into Rails 5.2 and the setup, we will access the Auth0 application to add an API so we can configure our application accordingly. To do so access the API Menu in the Management App (manage.auth0.com/#/apis).
Press the orange + Create API button on the top right corner to open the creation modal.
Enter your information as I did in the screenshot below. In audience you do ** not** have to add http://localhost:4000
- note: this identifier (which do not need to be an URL) cannot be modified, but you can, of course, create a new API if needed.
Well done! You're ready to start your authentication journey. Sadly the Quickstart of Auth0s API section does not include a Rails Copy&Past example right away but you can find all you need later in this tutorial. The big benefit of the already available Quickstarts is that you have all the information you need to configure in one place (the node.js example). All those information can also be found in the Settings Tab.
Environment Setup
This tutorial will use a freshly created Rails project. You can also add Auth0 to an existing project using the same/similar approach as presented here.
If you already have your own project have a look at their guide on how to change an existing application.
Install dependencies
We will use the jwt
gem for validation within our own JsonWebToken
class and a custom Concern to mark endpoints which should require authentication through an incoming AccessToken from your client application. You can check our tutorial for a Vue.js Client that already handles the authentication process.
Creating our JsonWebToken Class
The code we're going to use from the official Auth0 Ruby on Rails getting started which I highly recommend you to open as well since it ships with your project configuration out of the box.
Before we will create a JsonWebToken
class, which we will use to verify the incoming AccessToken of the Request Authorization
Header, we have to make some adjustments: Rails 5.2 has some changes that will require you to either change your understanding of the /app
and /lib
folder or to add one line to allow the "old" behavior. Since with 5.2, you will not be able to directly use the /lib
directory for non-domain specific classes. There are two ways to approach this:
I will go ahead and follow the /app/lib
approach, for now, feel free to also use the other. Thanks to an awesome group of contributors we can use a pure ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT) standard as shown below.
Adding your Auth0 API Audience
With Rails 5.2 is out with a brand new credentials API that will replace the current config/secrets.yml
. The idea behind the change is mainly to remove some of the confusion introduced by the combinations of config/secrets.yml
, config/secrets.yml.enc
and SECRET_BASE_KEY
used in earlier versions of Rails, and attempt to unify everything using a more straightforward approach. You can read more about this Change in their Pull Request on Github.
Your Rails application should already have those two files available instead:
config/credentials.yml.enc
config/master.key
As it’s extension .enc
suggests, this file is going to be encrypted using the master.key
- nobody is able to read what’s inside - unless they have the proper master key to decrypt it. So you can add the config/credentials.yml.enc
to your version control. On the other hand the config/master.key
should not be in your version control eg. git repository. New Rails 5.2 apps already have it in the .gitignore
to make sure you won't commit it. Everybody that has that config/master.key
will be able to decrypt your credentials.yml.enc
file and therefore has access to your credentials.
Editing your encrypted Rails credentials file
Rails 5.2 comes with a way to edit the config/credentials.yml.enc
so you won't have to decrypt and encrypt your file each time on your own. For this to work with your favorite editor you will have to have $EDITOR
defined, to do so in one command you can use the list below, let me know in the comments or on Twitter which editor you use and how you edited it.
You should now be able to see a demo .yml
structure where we can now add our own configuration/credentials. We will go ahead and add the namespace auth0
and attribute api_audience
with your audience as shown below, you can also introduce staging namespaces as you would in a normal .yml
file. It is a good idea to have the credentials for environments protected by different master keys so that all of your development machines don’t have access to the production credentials, however, if you want to use one key to encrypt them and use namespaces you can find an example right here as well:
The audience you're using here must be the same as you added in your clients' setup. You can read more about the audience and what an audience actually is in the Auth0 docs. If you have an issue with audiences check the auth0 logs and if you have an API with that audience in place.
Updating the JsonWebToken file
You may notice the line Rails.application.secrets.auth0_api_audience
which still uses the old secrets
and that would actually still work but since we don't even have it (if you have created a new project as we did and not upgraded) we exchange that with our credentials: Rails.application.credentials[:auth0][:api_audience]
.
Define your Secured concern
Next we will create a custom Concern
called Secured
which checks for the AccessToken
in the Authorization
request header. If the token is present, it should be passed to JsonWebToken.verify
. If you experience an issue at this point that JsonWebToken
is not defined or can not be loaded, make sure to have the /lib
folder moved to app/lib
or add Dir[Rails.root.join('lib/**/*.rb')].each { |f| require f }
to your config/environment.rb
Public and Private route
To test our application we will add two new controllers (a public and private) to our application.
The public controller should now already be accessible via /public/hello
after you've started your server rails s -p {your_port}
.
The private controller should now also be accessible via /private/hello
, to tell Rails that this controller should use our Secured
Concern all we have to add is one line:
If you now access the /private/hello
route you will receive an error that should look like:
Nice! We now have a check for the Authorization
Header and not let our request through! Well done!
Test/Accessing your Authenticated endpoint
To test your authenticated endpoints you can navigate to the Auth0 Test Panel of your API in the Auth0 app, where you can find, not only a CURL that is preconfigured and looks like the one below, but also many more code examples in various technologies. You can also use our Vue.js example by exchanging the audience with the one of your newly created API in Auth0. The Test suite can be found at the last Tab in the API Configuration in the Auth0 Dashboard.
1. Get your JWT from Auth0
The basic request your client can perform by posting to the Auth0 /oauth/token
endpoint should look like:
The response you expect from that endpoint should have the following body:
2. Use that token against your API
In your client application, we now send that token as Authorization
header to our API
and expect the following result:
Wrapping it up
Adding Auth0 to a Rails application is unbelievable easy by following the official guide. However, since it currently does not cover the differences in Rails 5.2 I felt the need to update and document that part for you so you won't fall into the above changes. The benefits from not writing your own Authentication in every application and instead use an Identify Service like Auth0 is such a boost for your productivity and increase in security that I would highly recommend you to check it out yourself.
With the change in Rails 5.2 that enables you to actually use encrypted credentials out of the box is great, even tho some will miss the old, now deprecated, secrets.yml. Even tho you can still use it, it is now no longer the recommended way so keep that in mind while upgrading. The issue with the lib folder was interesting to read on Github and took me longer to find the "best" way as I wished for. As many of you requested this is now the first API part of the Auth0 tutorials we created at Storyblok since we do use Ruby and Auth0 ourselves. Feel free to leave your comments down below or write your tweet your feedback on Twitter.
Resource | Link |
---|---|
Auth0 | https://auth0.com/ |
Rails | https://rubyonrails.org/ |
Vue.js + Auth0 client tutorial | https://www.storyblok.com/tp/how-to-auth0-vuejs-authentication |
Source on Github | https://github.com/storyblok/rails-52-auth0 |