Angular 2+ and Ruby on Rails user authentication

How to setup an Angular 2+ frontend with User Register/Login capabilities using Ruby on Rails backend and Devise Token Auth gem

Intro

TD;DR: We’ll create a simple Rails & Angular (2+) web application that allows a user to create an account, login with it and view his profile using Devise and token authentication.

Final result

Prerequisites

This tutorial assumes you’re comfortable with Ruby on Rails (RoR), more precisely with the version 5 and Rails API Mode, and somewhat familiar with Angular 2+. This is not exactly a “Getting Started with Rails and Angular” kind of tutorial for absolute beginners, but I’ll go into as much details as I can.

I’ll also assume you have NodeJS 6.9+, NPM and Postgres installed on your system, if not, there are great tutorials online if you Google around.

Frontend and backend will be running on separate servers, communicating with each other via a REST API.

Before we begin, English is not my first language, so if you see something weird, please, calmly point it out in the comment section, there’s no need for violence :)

Angular features we’ll use

  • Components
  • Services
  • Dependency injection
  • Forms and form validations
  • Component inputs
  • Component outputs
  • View Children
  • Router and Router Guards

Part 1: Backend

Rough plan

  1. Bootstrap and configure a RoR app in API mode
  2. Link to Postgres database
  3. Install, configure devise-token-auth gem
  4. Create and Configure our Devise User model
  5. Seed the DB with a default test user
  6. Create, Migrate and Seed our database
  7. Run the server and test the API

If you don’t want/need to go through this process, you can just download the final code from this repo: https://github.com/avatsaev/rails-devise-token-seed and jump straight to Part 2: Bootstrapping and configuring the frontend.

Let’s get started.

Setup

First let’s bootstrap a new Rails project in API mode and Postgres database (DB) config:

$ rails new rails_devise_token_auth --api --database=postgresql

This will create a barebones Rails 5 app in API mode (without views and without the asset pipeline, JSON will be the default response format)

Next, we’ll add a few useful gems to our Gemfile:

gem 'devise_token_auth'
gem 'omniauth'
gem 'rack-cors', :require => 'rack/cors'

Devise Token Auth leverages Devise and will allow us to do user management via a REST API, omniauth is a devise_token_auth dependency.

We need rack-cors, which allows us to do cross domain AJAX requests (because we are running in API mode, so the backend will most certainly run on a separate server and domain when in production).

Install the gems:

$ bundle install 

Let’s configure cors, edit the file ./config/initializers/cors.rb (create if doesn’t exist), replace its contents with the following:

Rails.application.config.middleware.use Rack::Cors do
  allow do
    origins '*'
    resource '*',
    :headers => :any,
    :expose  => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
    :methods => [:get, :post, :options, :delete, :put]
  end
end

For this tutorial we’ll allow all domains to contact our server, expose some custom headers retuned by Devise Token Auth, and allow the most commonly used http request methods, although we won’t need all of them.

Database configuration

Assuming you already have a Postgres server installed and running on your system, we do not have to change anything, because Postgres is already initialised with a public postgres user and database, and initial Rails DB config uses postgres as default user and localhost as default host, but if your Postgres server has a custom password protected user, don’t forget to edit the ./config/database.yml file:

default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: rails_devise_token_seed_development
username: YOUR_CUSTOM_USERNAME
password: YOUR_PASSWORD
test:
<<: *default
database: rails_devise_token_seed_test
username: YOUR_CUSTOM_USERNAME
password: YOUR_PASSWORD

Create the database

$ rails db:create

This command will create our development and test databases.

Initialise Devise User Model

If you read the DeviseTokenAuth README you’ll see how to initialise our user model:

$ rails generate devise_token_auth:install User auth

User will be our model name, and auth will be the endpoint of our user management rest api (ex: /auth/sign_in, /auth/sign_out)

Generated output of this command should look something like this:

create  config/initializers/devise_token_auth.rb
create  db/migrate/20170131161242_devise_token_auth_create_users.rb
create  app/models/user.rb
insert  app/controllers/application_controller.rb
gsub  config/routes.rb

The most interesting files for us are highlighted in bold.

The first one is a database migration file that will initialise the users table for us with all required fields.

We also have User model initialised, as well as the auth endpoint mounted in routes.rb

Configure User Model

For this tutorial, we’ll disable account email validation by opening the User model (./app/models/user.rb) file and removing confirmable module from the devise configuration, so the User model should look something like this:

class User < ActiveRecord::Base


devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:omniauthable
  include DeviseTokenAuth::Concerns::User
end

Create a default User seed

We’ll initialise the users table with a default user that will allow us to test our API as we go. In ./db/seeds.rb add the following line:

User.create(email: 'user@example.com', nickname: 'UOne', name: 'User One', password: "monkey67")

Our login will be user@example.com with password monkey67

Migrate and Seed the DB

rails db:migrate && rails db:seed

This one liner will migrate the users table, and create our default user in it:

Test the API

Now we can finally start our backend server and test the API, start the Rails server by issuing the following command:

$ rails s

And we’ll try to login with our default user credentials, to test REST APIs I use the Paw App for macOS (which is a great tool btw, you if you work with REST APIs, I can’t recommend it enough) but you can use whatever tool you like or just curl in your terminal.

By reading the Devise Token Auth documentation we can see that we need to make a POST request to /auth/sign_in endpoint with email and password parameters in order to login and get our auth token, so we’ll do just that:

Response body
Response headers

It’s alive! (Paw Print of the request and response: https://paw.pt/b4LiggBt)

The server will return the user data in response body, and the auth token in response headers (acess-token key)

Alternatively you can use this curl command to test it in the terminal:

curl -v -X "POST" "http://localhost:3000/auth/sign_in" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"email": "user@example.com",
"password": "monkey67"
}'

So now that our backend have the minimal functionality, let’s attack the frontend.

Click here for the Part 2: Setting up Angular frontend
Show your support

Clapping shows how much you appreciated A. Vatsaev’s story.