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

Archives Details

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

JavaScript

2019.03.24

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

どもです。

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

OAuthのフローを可視化できるツールを作ってみました。

2020.05.17

令和の時代に、JavaScriptで Shift-JISファイル作成 全銀データフォーマットに対応する。

2020.03.03

インターネットにて世論調査を行う「世論Web」サービスを始めてみました。

2020.01.31

年末のレトロゲーム熱の際、ファミコンソフト一覧パッケージ作ってました。

2020.01.24

あと10日で「jsdo.it」のサービスが終わってしまう!! ソースダウンロードまだの方は急げぇ〜!

2019.10.21

正規表現 先読み後読み 論理積

2019.07.28

「二段階認証?」という方も 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

CATEGORY LIST

LATEST NEWS

M1 Macで始める「ゼロからのOS自作入門」- 第1章

自作OS

2021.07.24

2021年6月 Amazonプライムデーで購入したもの。(今更)

イベント

2021.06.30

Go言語開発者、Unity開発者必見!! 【Golang】「クソコードをシンプルにする」,【Unity】「Singletonを使わないUnityを用いたApplication開発」

イベント

2021.05.23

TypeScriptでStateMachine

AI・Bot・algorithm

2021.05.16

iPad Air で、Web開発環境構築(iSH Alpine使用)

mac

2021.04.11

【Qt】Mac開発 ソートダイアログ (拡張するダイアログ)を作成

C++

2021.04.01

M1 (Appleシリコン)Macで Widowsアプリを起動

mac

2021.03.27

M1(Appleシリコン)Macで、ファミコンソフトプログラミング。 サクッと開発環境準備編

Game

2021.03.21

iPad Air 2020を購入しちゃった件。

mac

2021.03.14

眠っているラズベリーパイをネットワークオーディオ化 Volumio2 インストール手順

RaspberryPi

2021.03.12

ラズベリーパイ 5インチDSIタッチスクリーン ディスプレイを使う。

RaspberryPi

2021.01.11

今年読んで良かった書籍は、「Go言語でつくるインタプリタ」でした。

イベント

2020.12.31

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

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

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

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

FOLLOW US