[RUBY] Introduced # 10 devise_token_auth to build a bulletin board API with authentication authorization in Rails 6

Introduction of # 9 serializer to build bulletin board API with authentication authorization in Rails 6

Constitution

Currently, anyone can post by hitting the API, but I would like to change this to a configuration that links this to the logged-in user.

Introduction of devise, devise_token_auth

devise is the de facto standard around authentication in Rails. You can use a wide range of functions such as user creation, login / logout, password reissue, login count recording, login failure block, etc. just by entering and setting this. On the contrary, it is difficult to customize because of its multi-functionality, but ...

The token-authenticated version of devise is devise_token_auth. Since devise is derived, devise_token_auth requires devise.

Gemfile



...
+ #Authentication
+ gem "devise"
+ gem "devise_token_auth"

Install both devise and devist_token_auth.

$ rails g devise:install
$ rails g devise_token_auth:install User auth

Reference: Use [Rails] devise token auth

Change of various files

Config / routes.rb is rewritten at runtime, but this time I want to put it in the v1 namespace, so fix it.

config/routes.rb


 # frozen_string_literal: true

 Rails.application.routes.draw do
-  mount_devise_token_auth_for 'User', at: 'auth'
   namespace "v1" do
     resources :posts
+    mount_devise_token_auth_for 'User', at: 'auth'
   end
 end

Also, the automatically generated file is stuck in rubocop, so fix it. It's a little rough, but I'll set exclusions for migrate and config. Other than that, we will handle it manually.

diff:.rubocop.yml



...
+ #Method length
+ Metrics/MethodLength:
+   Exclude:
+     - "db/migrate/**/*"
+
+ # AbcSize
+ Metrics/AbcSize:
+   Exclude:
+     - "db/migrate/**/*"
+
+ #Line length
+ Layout/LineLength:
+   Exclude:
+     - "config/initializers/**/*"

Change model and migration

This time, we will use only the minimum necessary functions, so delete unnecessary initial values.

app/models/user.rb


   devise :database_authenticatable, :registerable,
-         :recoverable, :rememberable, :trackable, :validatable
+         :rememberable, :validatable
   include DeviseTokenAuth::Concerns::User

db/migrate/xxxxxxxxxxxxxx_devise_token_auth_create_users.rb


       ## Database authenticatable
       t.string :encrypted_password, null: false, default: ""

 
-      ## Recoverable
-      t.string   :reset_password_token
-      t.datetime :reset_password_sent_at
-      t.boolean  :allow_password_change, default: false
-
       ## Rememberable
       t.datetime :remember_created_at
 

-      ## Confirmable
-      t.string   :confirmation_token
-      t.datetime :confirmed_at
-      t.datetime :confirmation_sent_at
-      t.string   :unconfirmed_email # Only if using reconfirmable
-
-      ## Lockable
-      # t.integer  :failed_attempts, :default => 0, :null => false # Only if 
lock strategy is :failed_attempts
-      # t.string   :unlock_token # Only if unlock strategy is :email or :both
-      # t.datetime :locked_at
-
       ## User Info
       t.string :name
-      t.string :nickname
-      t.string :image
       t.string :email
 
...
     add_index :users, :email, unique: true
     add_index :users, %i[uid provider], unique: true
-    add_index :users, :reset_password_token, unique: true
-    add_index :users, :confirmation_token,   unique: true
-    # add_index :users, :unlock_token,       unique: true
   end

After making the changes so far, migrate.

$ rails db:migrate

Allow columns other than email and password

Try it with curl.

$ curl localhost:8080/v1/auth -X POST -H 'Content-Type: application/json' -d '{"email": "[email protected]", "password": "password", "name": "hoge"}'
{"status":"success","data":{"uid":"[email protected]","id":1,"email":"[email protected]","provider":"email","name":null,"created_at":"2020-09-08T04:40:44.659Z","updated_at":"2020-09-08T04:40:44.827Z"}}

You have successfully registered. However, if you look closely, it is null even though the name is specified by hoge.

Being able to guess the cause of this is proof that you're used to Rails.

This is because, like other controllers, the columns that can be registered with strong parameters are limited. Therefore, we will take the following measures.

app/controllers/application_controller.rb


 class ApplicationController < ActionController::API
   include DeviseTokenAuth::Concerns::SetUserByToken
   rescue_from ActiveRecord::RecordNotFound, with: :render_404
+  before_action :configure_permitted_parameters, if: :devise_controller?
 
   def render_404
     render status: 404, json: { message: "record not found." }
   end
+
+  def configure_permitted_parameters
+    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
+  end
 end

This makes it possible to register including the name column.

$ rails db:reset
$ curl localhost:8080/v1/auth -X POST -H 'Content-Type: application/json' -d '{"email": "[email protected]", "password": "password", "name": "hoge"}'                                                  
{"status":"success","data":{"uid":"[email protected]","id":1,"email":"[email protected]","provider":"email","name":"hoge","created_at":"2020-09-08T04:51:42.527Z","updated_at":"2020-09-08T04:51:42.698Z"}}

Reference: How to use super basic devise

Confirm sign_in

Now that you have registered, we will confirm your login.

$ curl localhost:8080/v1/auth/sign_in -X POST -H 'Content-Type: application/json' -d '{"email": "[email protected]", "password": "password"}' -i
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
access-token: T4ZeomARybw3_o5nIHQAfw
token-type: Bearer
client: Fj772-EYBPnvJdETYhObyQ
expiry: 1600751367
uid: [email protected]
ETag: W/"8c41022d2e42ca28df0cb958a84ab2f4"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: d4ff732c-f6b5-4213-8984-5d9457b39cbd
X-Runtime: 0.510436
Transfer-Encoding: chunked

{"data":{"id":1,"email":"[email protected]","provider":"email","uid":"[email protected]","name":"hoge"}}

By adding the -i option, the header information is also returned. And at the end, the information of the user registered earlier is listed, and the header also returns with 200 OK, so you can see that you can log in normally.

Notable headers access-token: T4ZeomARybw3_o5nIHQAfw client: Fj772-EYBPnvJdETYhObyQ uid: [email protected] These are the three. By including these three in the header at the time of request, it is determined that the access is for an authenticated account.

As an aside, what happens if the authentication information is incorrect? Try logging in with the wrong email or password.

$ curl localhost:8OST -H 'Content-Type: application/json' -d '{"email": "[email protected]", "password": "PASSWORD"}' -i                                                       
HTTP/1.1 401 Unauthorized
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
X-Request-Id: 12832212-9797-465b-a5b1-ecaa7e88a977
X-Runtime: 0.308726
Transfer-Encoding: chunked

{"success":false,"errors":["Invalid login credentials. Please try again."]}

It will be returned at 401.

Continued

Building a bulletin board API with certification authorization in Rails 6 # 11 User model test and validation added [To the serial table of contents]

Recommended Posts

Introduced # 10 devise_token_auth to build a bulletin board API with authentication authorization in Rails 6
Introduced # 9 serializer to build bulletin board API with authentication authorization in Rails 6
Introducing # 15 pundit to build a bulletin board API with authentication authorization in Rails 6
# 16 policy setting to build bulletin board API with authentication authorization in Rails 6
# 8 seed implementation to build bulletin board API with authentication authorization in Rails 6
Build a bulletin board API with authentication authorization in Rails # 13 Add authentication header
# 6 show, create implementation to build bulletin board API with authentication authorization in Rails 6
Build a bulletin board API with authentication authorization in Rails # 17 Add administrator privileges
# 7 update, destroy implementation to build bulletin board API with authentication authorization in Rails 6
Build a bulletin board API with authentication authorization in Rails 6 # 14 seed Execution time display
Build a bulletin board API with authentication and authorization with Rails 6 # 1 Environment construction
Build a bulletin board API with authentication authorization with Rails 6 # 3 RSpec, FactoryBot introduced and post model
Build a bulletin board API with authentication authorization in Rails # 12 Association of user and post
Build a bulletin board API with authentication authorization with Rails 6 # 2 Introducing git and rubocop
Build a bulletin board API with authentication authorization in Rails 6 # 11 User model test and validation added
I tried to make a group function (bulletin board) with Rails
Create a SPA with authentication function with Rails API mode + devise_token_auth + Vue.js 3 (Rails edition)
Try to create a bulletin board in Java
How to build API with GraphQL and Rails
[How to insert a video in haml with Rails]
How to set up a proxy with authentication in Feign
How to rename a model with foreign key constraints in Rails
Steps to build a Ruby on Rails development environment with Vagrant
[Rails] How to log in with a name by adding a devise name column
How to insert a video in Rails
I tried to build a Firebase application development environment with Docker in 2020
How to build a Ruby on Rails development environment with Docker (Rails 6.x)
Steps to set a favicon in Rails
How to build a Ruby on Rails development environment with Docker (Rails 5.x)
How to use credentials.yml.enc introduced in Rails 5.2
How to build Rails 6 environment with Docker
How to store data simultaneously in a model associated with a nested form (Rails 6.0.0)
Convert to a tag to URL string in Rails
Create a simple bulletin board with Java + MySQL
[Rails] rails new to create a database with PostgreSQL
One way to redirect_to with parameters in rails
How to implement a like feature in Rails
How to easily create a pull-down in Rails
[Rails] How to build an environment with Docker
How to make a follow function in Rails
[Rails] [Docker] Copy and paste is OK! How to build a Rails development environment with Docker
Docker command to create Rails project with a single blow in environment without Ruby
I made a function to register images with API in Spring Framework. Part 1 (API edition)
How to deal with errors in Rails s could not find a JavaScript runtime.
How to implement a like feature in Ajax in Rails
How to delete a new_record object built with Rails
I want to use a little icon in Rails
How to manually generate a JWT with Rails Knock
Throw raw SQL to a read replica in Rails
[Note] Build a Python3 environment with Docker in EC2
How to write a date comparison search in Rails
I want to define a function in Rails Console
How to store Rakuten API data in a table
How to query Array in jsonb with Rails + postgres
[Rails 6] How to set a background image in Rails [CSS]
Build Rails (API) x MySQL x Nuxt.js environment with Docker
[Rails] How to load JavaScript in a specific view
How to get started with creating a Rails app
A new employee tried to create an authentication / authorization function from scratch with Spring Security
I made a function to register images with API in Spring Framework. Part 2 (Client Edition)
Tutorial to create a blog with Rails for beginners Part 1