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

Archives Details

SPAサイトでの認証認可 JWT✗Rails5✗Nuxt.js

JavaScript

2019.03.24

どもです。

SPAでサービスをガンガン作成されているでしょうか?

SPAの認証認可のアクセストークンとして、「JWT(JSON Web Tokens)」を用いる方も多いのではないでしょうか?

前回、「Nuxt.js と auth-module (@nuxtjs/auth)で、JWT(JSON Web Tokens)& OAuth 認証 ログイン」の記事にて、「auth-module@nuxtjs/auth)」を用いた「JWT(JSON Web Tokens)& OAuth 認証 ログイン」について記事を書いたのですが、今回サーバーも作成してみました。

とにかく試したい方はこちらから

Github

・サーバー側(Rails5)

https://github.com/webcyou-org/jwt-server

・フロント側(Nuxt.js)

https://github.com/webcyou-org/jwt-front

JWT(JSON Web Tokens)を用いて認証認可(ログイン周り)の実装となります。

フロント側は、前回同様「auth-module@nuxtjs/auth)」のサンプルを使用する際に、フロント側の実装とサーバー側の実装となります。

Railsのpublicフォルダに、Nuxt.jsのSPAモードでリソースをビルドしたものになります。

Rails側で、ログインしたり、ログイン後ユーザー情報を参照したりすることができます。

前回、フロント側の実装に関してだったので、今回はサーバー側の実装に関して書いていこうかなと。

フロント側のポイントは、process.env.NODE_ENVの「development」(Rails APIサーバーをポート3000で動かしている場合)は、config.proxyを設定し、Nuxt.jsはポート3333で立ち上げ、「/api」は「http://localhost:3000」に向けているところですかね。

あと、SPAの認証認可で、cookieを用いてしまうと脆弱性が出てしまうので、「Local Strage」に変更しているところと、endpointsを「/api/v1/」に変更し、「propertyName」をRailsサーバー側から受け取る(knockデフォルト)「propertyName」に変更したところですかね。

では、サーバー側をRails5 APIモードでサクッと作ったので軽く説明でもと。

SPAを実装しようとしている方の何か参考になればと思います。

(Railsについての説明とかは割愛しております。)

Rails5 APIサーバー (Gem Knockを用いたJWT認証)

それでは、手順を書いて行きます。

まず、以下のコマンドで、Rails APIモードのwebアプリを生成。

$ bundle exec rails new jwt-server --api
$ cd jwt-server

User Modelを Rails ジェネレートコマンドを用いて生成します。

パスワードはBcryptで暗号化したものをセットするため、has_secure_passwordメソッドを用いて生成し、それを保存するカラム「password_digest」を用意しておきます。

$ bin/rails g modeluser password_digest:string name:string email:string--no-test-framework

app/models/user.rbを以下のように修正。

app/models/user.rb

class User < ApplicationRecord
  has_secure_password

  validates :name, presence: true
  validates :email, presence: true
end

seedファイルを修正します。

db/seeds.rb

User.destroy_all

User.create!({
  name: 'daisuke.takayama',
  email: 'test@user.com',
  password: 'test123',
  password_confirmation: 'test123'
})

ダミーデータとして、Userを一人登録します。

emailと、パスワードは上記の様に設定しておきます。

準備ができましたので、データベースの作成とマイグレードを実行。

seedコマンドで、データを挿入しておきます。

$ bin/rails db:create db:migrate
$ bin/rails db:seed

といった作業が、この辺のコミットになります。

Userコントローラもジェネレートコマンドで生成しておきます。

$ bin/rails g controller Api/V1/Users

classで生成されたので、moduleに変更しました。

その辺りのコミットとなります。

Gem Knockを追加

それでは、JWT認証 Gemパッケージである「knock」を追加していきます。

Gemfileに「knock」を追加。

bundle インストール

$ bundle install --path vendor/bundle

knockをインストールします。

$ bin/rails generate knock:install

以下が表示すれば成功。

create  config/initializers/knock.rb

userがアクセストークンを発行できるように「token_controller」をknockコマンドを用いて生成します。

$ bin/rails generate knock:token_controller user

コントローラとルーティングが生成。

create  app/controllers/user_token_controller.rb
route  post 'user_token' => 'user_token#create'

app/controllers/user_token_controller.rb

class UserTokenController < Knock::AuthTokenController
end

このような感じで「user_token_controller.rb」が生成されるのですが、「Api/V1/」にしたかったので、手動で持っていきました。(コマンドで生成したかったのですが、ちょっとやり方わからなかったです)

app/controllers/api/v1/user_token_controller.rb

module Api
  module V1
    class UserTokenController < Knock::AuthTokenController
    end
  end
end

ルーティングも以下の様に修正。

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      post 'user_token' => 'user_token#create'
    end
  end
end

「controllers/application_controller.rb」に、「include Knock::Authenticable」を追記し、application_controllerに、Knock::Authenticableモジュールを追加します。

class ApplicationController < ActionController::API
  include Knock::Authenticable
end

と、この辺りのコミットはここらへんとなります。

Users Controller修正

app/controllers/api/v1/users_controller.rb を修正していきます。

before_action :authenticate_user, except: [:create, :logout]

を追加し、Userリソースを保護します。

createメソッドとlogoutメソッドは、exceptで 対象外としております。

createメソッドは新規ユーザー作成ですが、こちらの説明は割愛させていただきます。

indexメソッドで、ログインしているユーザーを返却します。

def index
  render json: {status: 200, user: response_fields(current_user.to_json) }
end

また、ログアウトに関しては、JWTではサーバー側にログインしている状態などを保持しない設計なので、サクセスだけ返却するようにしております。

このまでのコミットが、この辺りとなります。

Usersコントローラ修正に伴い、routesも修正しておきます。

config/routes.rb

get 'users' => 'users#index'
post 'users' => 'users#create'
delete 'users' => 'users#logout

これまでのコミットが、この辺りとなります。

curlでの検証

と、ここまで実装できれば検証が行える。

はずだったのですが、何度行っても 401エラーとなってしまう。。。

調べたところ、Rails5.2以降で、どうやら「Rails.application.secrets.secret_key_base」は、nilを返すようで、それが影響しているぽい。

回避策として「skip_before_action :verify_authenticity_token」を「UserTokenController」に追加。

module Api
  module V1
    class UserTokenController < Knock::AuthTokenController
      skip_before_action :verify_authenticity_token
    end
  end
end

knockのイシュー

https://github.com/nsarno/knock/issues/208

これまでのコミットが、この辺りとなります。

curl Test

アクセストークンの生成(ユーザーログイン時)

$ curl -X "POST" "http://localhost:3000/api/v1/user_token" -H "Content-Type: application/json" -d $'{"auth": {"email": "test@user.com", "password": "test123"}}'

レスポンスは、jwtが返却されます。

{"jwt":"eyJ0eXAiOiJKV1QiLCJhbG...."}

上記のJWTを用いて、ログインユーザー情報を取得。

$ curl -X "GET" "http://localhost:3000/api/v1/users" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbG...." -H "Content-Type: application/json"

ログインしているユーザー情報が返却されるのが確認できました。

{"status":200,"user":{"id":1,"name":"daisuke.takayama","email":"test@user.com"}}

と、今回のサーバー側のソースはこちらになります。

https://github.com/webcyou-org/jwt-server

Github

・サーバー側(Rails5)

https://github.com/webcyou-org/jwt-server

・フロント側(Nuxt.js)

https://github.com/webcyou-org/jwt-front

フロントエンドのassetsは「frontend」ディレクトリで submodule化しております。

終わりに

といった訳で、今回はJWTのサーバー側の実装でした。

時間ができたら、Rails以外にも、SpringBootとか、Djangoとかでも実装してみようかと思っております。

(最初は、SpringBootでやろうかと思いましたが、環境構築がRailsの方が楽だったので。。)

また、同じく時間ができたら、フロント側のフレームワークも、Nuxt.js以外のSPAフレームワーク用いてやってみようかと。

SPAでのJWT認証認可を作成しようとしている方の何かの参考にでもなればと思っております。

ではではぁ。

またまたぁ。

Comment

Related Article

「二段階認証?」という方も 5分で覚える パスワードレス WebAuthnのまとめ

2019.07.07

上級者向け JavaScript 問題集 「javascript-questions」日本語翻訳担当してます。

2019.06.22

SPAサイトでの認証認可 JWT✗Rails5✗Nuxt.js

2019.03.24

Nuxt.js と auth-module (@nuxtjs/auth)で、JWT(JSON Web Tokens)& OAuth 認証 ログイン

2019.02.21

ブラウザフィンガープリントは、Cookieの代用となるのか? JSライブラリ Fingerprintjs2など。

2019.02.03

Vue.jsでSPA、Vuex使用するなら Nuxt.jsが超絶便利な件。

2018.12.23

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

2018.09.26

Vue.js + SSR (Universal JavaScript)環境を、「NUXT.js」でサクッと構築する方法。

2017.10.09

フロントエンド開発が捗る JSON Serverについて

2017.07.10

技術書、参考書のしおりには【BOOK DARTS】がオススメ!

2017.07.01

CATEGORY LIST

LATEST NEWS

PythonでGUIアプリ開発「PyQt」を使った感想

Python

2019.07.18

「二段階認証?」という方も 5分で覚える パスワードレス WebAuthnのまとめ

JavaScript

2019.07.07

上級者向け JavaScript 問題集 「javascript-questions」日本語翻訳担当してます。

JavaScript

2019.06.22

Wordpress サイトで、長時間 500 Internal Server Error発生。解決した方法とは。

WordPress

2019.06.18

Ubuntu 18.04 LTSで OpenGL開発

ubuntu

2019.05.20

MacOS Mojave (10.14.4)の Xcode に、過去のMacOSのSDKをインストール

C++

2019.05.19

クローンソフトの「EaseUS Disk Copy」を使って、OSのバックアップを取ってみた。

tool

2019.05.06

Rails5 gemでmysql2が インストールできない

Ruby

2019.05.05

平成最後のお買い物!!「Logicool MX Master 2 Wireless Mouse」と「K780 マルチデバイス BLUETOOTH® キーボード」で快適PC生活。

ubuntu

2019.04.27

Amazon 87時間のビックセール タイムセール祭りで購入したもの

イベント

2019.04.23

Androidに Linuxを簡単にインストールするアプリ「UserLAnd」

Linux

2019.04.16

SPAサイトでの認証認可 JWT✗Rails5✗Nuxt.js

JavaScript

2019.03.24

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

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

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

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

FOLLOW US