このサイトは、只今WEB業界で活躍中のデザイナー、プログラマーの方々の情報を集めたweb統合情報サイトです。

Archives Details

Rails5 + devise token authで作る 認証API

Ruby

2017.05.20

この記事は最終更新日から1年以上が経過しています。

どもです。

ちょっとRailsの認証周りについて少々。

サーバーサイドで認証が必要な場合、大きく2つの実装方法があるかと思います。

Cookieベースの認証

Tokenベースの認証

今回は、Tokenベースの認証について行っていきたいと思います。

Ruby oc Railsを基に構築し、Cookieベースの認証を行う場合、ログイン機能や、ユーザーデータ周りを Gemであるdeviseにお任せすることも多々あるかと思います。

そんな、deviseを使って、トークンベースの認証を行いたい場合「devise token auth 」というGemを使うと、何かと容易に実装が行えますので、行っていきます。

準備

それでは、早速作っていきましょう。

まず、rails new でアプリケーションを生成します。

$ rails new app_name --api -d mysql

続いて、Gemfileを編集しましょう。

新たに、「devise」と「devise_token_auth」を追加し、「jbuilder」と、「rack-cors」のコメントアウトを削除します。

Gemfile

source 'https://rubygems.org'

git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"https://github.com/#{repo_name}.git"
end

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.2'
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.3.18', '< 0.5'
# Use Puma as the app server
gem 'puma', '~> 3.0'

# jsonを扱うためのgem
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# クロスドメイン対策
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'

# トークンベースの認証を行う
gem 'devise'
gem 'devise_token_auth'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platform: :mri
end

group :development do
gem 'listen', '~> 3.0.5'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gemファイルの編集が終わりましたら、bundle installでgemをインストールします。

一応インストール先の pathは、「vendor/bundle」としておきます。

$ bundle install --path vendor/bundle

gemのインストールが完了しましたら、データベースの作成を行います。

$ bundle exec rake db:create

mysqlサーバーを起動していない場合は起動しておきましょう。

$ mysql.server start

ひとまず、準備は完了しましたので、続いては、「deveise token auth」を用いて データを作成していきます。

devise token auth

rails g コマンドで「deveise_token_auth」が使用できるようになっていますので、以下のコマンドで Userデータを生成します。

$ rails g devise_token_auth:install User auth

以下の様に表示すれば成功。

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

完了すると、マイグレーションファイルが生成されますので、そのファイルを編集していきます。

今回は、簡易版という事もあって、ユーザーが新規に登録する際、

・名前

・メールアドレス

・所属チーム

を、登録できるようにカラムの準備を行っておきます。

また、twitterやfacebookなどのソーシャルプラグインによるログインや、登録する際にメール送信して確認。などと言った機能に関して今回は行わないので、コメントアウトしておきます。

ユーザーモデルである、 user.rb を編集します。

app/models/user.rb

class User < ActiveRecord::Base
  # Include default devise modules.
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable
  #:confirmable, :omniauthable
  include DeviseTokenAuth::Concerns::User
end

次に、ユーザーカラム生成のマイグレーションファイルを修正します。

主な修正点として、「Confirmable」のコメントアウトと「confirmation_token」の add_indexのコメントアウト、ユーザーカラム(User Info)に「所属チーム」用のカラム 「team」の追加の記述となります。

db/migrate/xxxxxxx_devise_token_auth_create_users.rb

class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table(:users) do |t|
      ## Required
      t.string :provider, :null => false, :default => "email"
      t.string :uid, :null => false, :default => ""

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

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, :default => 0, :null => false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## 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
      t.string :team

      ## Tokens
      t.text :tokens

      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, [: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
end

ここまで、完了しましたら、マイグレーションコマンドを実行して、ユーザーテーブルの生成を行います。

$ bundle exec rake db:migrate

以下の様に、実行されれば成功。

== 20170520062742 DeviseTokenAuthCreateUsers: migrating =======================
-- create_table(:users)
-> 0.0164s
-- add_index(:users, :email, {:unique=>true})
-> 0.0158s
-- add_index(:users, [:uid, :provider], {:unique=>true})
-> 0.0126s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0140s
== 20170520062742 DeviseTokenAuthCreateUsers: migrated (0.0590s) ==============
Routes

現在のルートの確認を行ってみましょう。

$ rake routes
Prefix Verb   URI Pattern                    Controller#Action
new_user_session GET    /auth/sign_in(.:format)        devise_token_auth/sessions#new
user_session POST   /auth/sign_in(.:format)        devise_token_auth/sessions#create
destroy_user_session DELETE /auth/sign_out(.:format)       devise_token_auth/sessions#destroy
new_user_password GET    /auth/password/new(.:format)   devise_token_auth/passwords#new
edit_user_password GET    /auth/password/edit(.:format)  devise_token_auth/passwords#edit
user_password PATCH  /auth/password(.:format)       devise_token_auth/passwords#update
PUT    /auth/password(.:format)       devise_token_auth/passwords#update
POST   /auth/password(.:format)       devise_token_auth/passwords#create
cancel_user_registration GET    /auth/cancel(.:format)         devise_token_auth/registrations#cancel
new_user_registration GET    /auth/sign_up(.:format)        devise_token_auth/registrations#new
edit_user_registration GET    /auth/edit(.:format)           devise_token_auth/registrations#edit
user_registration PATCH  /auth(.:format)                devise_token_auth/registrations#update
PUT    /auth(.:format)                devise_token_auth/registrations#update
DELETE /auth(.:format)                devise_token_auth/registrations#destroy
POST   /auth(.:format)                devise_token_auth/registrations#create
auth_validate_token GET    /auth/validate_token(.:format) devise_token_auth/token_validations#validate_token

devise_token_authのデフォルトのルート設定がされているのが確認できます。

今回は、userのteamが編集出来るように、コントローラーをオーバライドして「team」を追加していきます。

rails ジェネレータコマンドでコントローラーを生成します。

$ rails g controller auth/registrations

コントローラーが生成されましたら、編集を行っていきます。

app/controllers/auth/registrations_controller.rb

module Auth
  class RegistrationsController < DeviseTokenAuth::RegistrationsController

  private
  def sign_up_params
  params.permit(:name, :email, :team, :password, :password_confirmation)
  end

  def account_update_params
  params.permit(:name, :email, :team)
  end

  end
end

続いて、ルートを変更し、先程のコントローラーが使えるようにしていきます。

config/routes.rb

Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth', controllers: {
    registrations: 'auth/registrations'
  }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

rake routes コマンドで、先程のauth/registrationsにパスが作成されていたら成功です。

$ rake routes
Prefix Verb   URI Pattern                    Controller#Action
new_user_session GET    /auth/sign_in(.:format)        devise_token_auth/sessions#new
user_session POST   /auth/sign_in(.:format)        devise_token_auth/sessions#create
destroy_user_session DELETE /auth/sign_out(.:format)       devise_token_auth/sessions#destroy
new_user_password GET    /auth/password/new(.:format)   devise_token_auth/passwords#new
edit_user_password GET    /auth/password/edit(.:format)  devise_token_auth/passwords#edit
user_password PATCH  /auth/password(.:format)       devise_token_auth/passwords#update
PUT    /auth/password(.:format)       devise_token_auth/passwords#update
POST   /auth/password(.:format)       devise_token_auth/passwords#create
cancel_user_registration GET    /auth/cancel(.:format)         auth/registrations#cancel
new_user_registration GET    /auth/sign_up(.:format)        auth/registrations#new
edit_user_registration GET    /auth/edit(.:format)           auth/registrations#edit
user_registration PATCH  /auth(.:format)                auth/registrations#update
PUT    /auth(.:format)                auth/registrations#update
DELETE /auth(.:format)                auth/registrations#destroy
POST   /auth(.:format)                auth/registrations#create
auth_validate_token GET    /auth/validate_token(.:format) devise_token_auth/token_validations#validate_token

auth/registrations に、「#new」、「#update」などのアクションが付与されているのを確認。

ここまでで一旦、設定は完了です。お疲れ様でした!

initialize

毎回、毎回、トークンが変更されるのはちょっと面倒なので、以下の様に設定しておきます。

config.change_headers_on_each_request を true にしていると、リクエストごとに token を新しくする必要がある。 という設定になるので、コメントアウトを解除し「false」に変更します。

# config.change_headers_on_each_request = true

config.change_headers_on_each_request = false
# config.token_lifespan = 2.weeks

config.token_lifespan = 1.month

その他、config.headers_namesのコメントアウトを解除。

config/initializers/devise_token_auth.rb

DeviseTokenAuth.setup do |config|
# By default the authorization headers will change after each request. The
# client is responsible for keeping track of the changing tokens. Change
# this to false to prevent the Authorization header from changing after
# each request.
config.change_headers_on_each_request = false

# By default, users will need to re-authenticate after 2 weeks. This setting
# determines how long tokens will remain valid after they are issued.
config.token_lifespan = 1.month

# Sets the max number of concurrent devices per user, which is 10 by default.
# After this limit is reached, the oldest tokens will be removed.
# config.max_number_of_devices = 10

# Sometimes it's necessary to make several requests to the API at the same
# time. In this case, each request in the batch will need to share the same
# auth token. This setting determines how far apart the requests can be while
# still using the same auth token.
# config.batch_request_buffer_throttle = 5.seconds

# This route will be the prefix for all oauth2 redirect callbacks. For
# example, using the default '/omniauth', the github oauth2 provider will
# redirect successful authentications to '/omniauth/github/callback'
# config.omniauth_prefix = "/omniauth"

# By default sending current password is not needed for the password update.
# Uncomment to enforce current_password param to be checked before all
# attribute updates. Set it to :password if you want it to be checked only if
# password is updated.
# config.check_current_password_before_update = :attributes

# By default we will use callbacks for single omniauth.
# It depends on fields like email, provider and uid.
# config.default_callbacks = true

# Makes it possible to change the headers names
config.headers_names = {:'access-token' => 'access-token',
                        :'client' => 'client',
                        :'expiry' => 'expiry',
                        :'uid' => 'uid',
                        :'token-type' => 'token-type' }

# By default, only Bearer Token authentication is implemented out of the box.
# If, however, you wish to integrate with legacy Devise authentication, you can
# do so by enabling this flag. NOTE: This feature is highly experimental!
# config.enable_standard_devise_support = false
end

Restlet Client – REST API Testing

REST APIをテストするのに「Restlet Client – REST API Testing」をインストールして試していきます。

chromeの拡張機能として提供されているパッケージとなります。

Restlet Client – REST API Testing

APIテスト

Restlet Client – REST API Testing」をインストールしたら早速試していきましょう。

Rails s コマンドでRailsサーバーを起動します。

$ rails s
ユーザー登録

ユーザー登録は「localhost:3000/auth」のpostで作成されます。

sendデータ 例:

{
  "name": "daisuke.takayama",
  "email": "webcyou@example.com",
  "password": "password",
  "team": "ウェブ帳"
}

レスポンス

{
  "status": "success",
  "data":{
    "id": 1,
    "email": "webcyou@example.com",
    "provider": "email",
    "uid": "webcyou@example.com",
    "name": "daisuke.takayama",
    "nickname": null,
    "image": null,
    "team": "ウェブ帳",
    "created_at": "2017-05-20T07:41:15.000Z",
    "updated_at": "2017-05-20T07:41:16.000Z"
  }
}

成功すると、上記の様にレスポンスが返ってくるかと思います。

DBの方を確認すると、usersテーブルにユーザーデータが作成されているのが確認できます。

続いて、ログインしてみましょう。

ログイン

ログインは「localhost:3000/auth/sign_in」にPOSTでログインとなります。

sendデータ 例:

{
  "email": "webcyou@example.com",
  "password": "password"
}

レスポンス

{
  "data":{
    "id": 1,
    "email": "webcyou@example.com",
    "provider": "email",
    "uid": "webcyou@example.com",
    "name": "daisuke.takayama",
    "nickname": null,
    "image": null,
    "team": "ウェブ帳"
  }
}
パスワードの変更

続いて、パスワードの変更。

パスワードの変更は、 「localhost:3000/auth/password」 に PUT リクエストとなります。

いよいよなんですが、ユーザー情報や、パスワードの変更などを行う際、 認証情報が必要となってきます。

その為に必要なのは、以下の通りとなっております。

REQUEST HEADERSの

・ access-token

・ client

・ uid

の、3つとなります。

先程、ログインした際に、HEADERSに付与されている情報が必要となってきますので、そちらを利用していきます。

Restlet Client – REST API Testing」では、以下の画像の様に、REQUESTの部分で設定できますので、コピペを行って入力しましょう。

入力したら、パスワード変更のデータを PUTしてみましょう。

sendデータ 例:

{
  "password": "password2",
  "password_confirmation": "password2"
}

レスポンス

{
  "success": true,
  "data":{
    "id": 1,
    "provider": "email",
    "email": "webcyou@example.com",
    "uid": "webcyou@example.com",
    "name": "daisuke.takayama",
    "nickname": null,
    "image": null,
    "team": "ウェブ帳",
    "created_at": "2017-05-20T07:41:15.000Z",
    "updated_at": "2017-05-20T08:11:19.000Z"
  },
  "message": "Your password has been successfully updated."
}

パスワード変更が出来ました。

ユーザー情報の変更

最後に、ユーザー情報の変更をおこなっていきます。

ユーザー情報の変更は、 「localhost:3000/auth/」 に PUT リクエストとなります。

先程の

・ access-token

・ client

・ uid

の情報を「REQUEST HEADERS」に付与し、 「localhost:3000/auth/」 に PUT リクエストを送ります。

sendデータ 例:

{
  "team": "webcyou"
}

レスポンス

{
"status": "success",
  "data":{
    "id": 1,
    "team": "webcyou",
    "email": "webcyou@example.com",
    "provider": "email",
    "uid": "webcyou@example.com",
    "name": "daisuke.takayama",
    "nickname": null,
    "image": null,
    "created_at": "2017-05-20T07:41:15.000Z",
    "updated_at": "2017-05-20T08:16:48.000Z"
  }
}

所属する「チーム」の変更を行ってみました。

レスポンスデータで変更に成功したのが確認できました。

と、
今回、ザッとではありましたが、Tokenベースの認証を容易に実装できる Gem 「devise token auth」のご紹介でした。

今回のソースに関しては、githubの方にも追加しております。

github – devise_token_auth_demo

こちらを使って、Tokenベースの認証に切り替え、SPAサイトなど作ってみると良いかもしれませんね。

ではではぁ。

Comment

Related Article

Rails5 + devise token authで作る 認証API

2017.05.20

Rails4 + TypeScript + AngularJS + slimで 快適開発環境構築!最短でSPA環境作成。

2016.02.20

Rubyを始める時のまとめ。

2015.04.10

Ruby 基本まとめ

2013.12.12

CATEGORY LIST

LATEST NEWS

Jenkins 認証情報「Jenkinsマスター上の~/.sshから」が表示しない

tool

2018.11.17

流れで、Raspberry Pi Zero WHを購入。気がつけばもうラズパイ4台。

RaspberryPi

2018.11.06

安く電子工作を始めるなら、電子パーツ購入は「aitendo」がおすすめ!

RaspberryPi

2018.11.06

ASUS Chromebook Flip C101PAに、Visual Studio Codeをインストール

Chromebook

2018.10.15

Chromebookに、Ubuntu (Xubuntu)をインストールしたあとの日本語入力設定

Chromebook

2018.10.14

ASUS Chromebook Flip C101PAに、Ubuntu (Linux)インストール手順

Chromebook

2018.10.10

nodeのない環境にnodeを導入(HTML5ゲームも提供)し続け、1年数ヶ月経過後、かなり開発環境が整ってきたお話。

JavaScript

2018.09.26

安い!軽い!早い! ノートPC(開発環境)。 Chromebookをついに購入いたしました!

Chromebook

2018.07.22

debian & Xserver XDSLで FireFoxが真っ白のページとなる件

Linux

2018.07.08

Kindle Fire HD 8 にLinuxを導入して扱えるようにする。超コスパ Linux タブレット構築方法!!

Linux

2018.07.04

Laravel 4 を PHP 7 環境へ移行したお話。

PHP

2018.06.10

iPhoneXで、ubuntuを動かす。

サーバー

2018.06.09

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

WEBデザイナーの、WEBデザイナーによる、WEBデザイナーの為のサイト。「みんなで書こう!」と仲間を募ってみたが、結局書くのは自分だけとなってしまいました。日々のメモを綴っていきます。

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

MAD CITY 北九州市で生まれ育つ。20代はバンド活動に明け暮れ、ふと「webデザイナーになりたい。」と思い、デジタルハリウッド福岡校入学。卒業後、数々の賞を受賞、web業界をざわつかせる。
現在、主に、ゲーム制作中心に港区六本木界隈で活動中。

FOLLOW US