このサイトは、只今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

JavaScriptで、DOMを放り投げる処理

2024.07.27

2022 VIVA JS World Cup 開幕!! 〜 Vue3で作るサッカーゲーム 〜

2022.12.24

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

CATEGORY LIST

LATEST NEWS

Mac VSCodeで、SFML C++開発環境を作る。

C++

2024.09.09

Rust-SDL2 examplesをすべて試す

Rust

2024.09.01

JavaScriptで、DOMを放り投げる処理

JavaScript

2024.07.27

Rustで創る MOS 6502 CPU その2

Rust

2024.07.23

Rustで創る MOS 6502 CPU その1

Rust

2024.07.19

汎用 3D mesh/model viewerを求め。と、簡単に、FBXファイルをglTF(glb)に変換ツールを求め。

C++

2024.06.06

M1 Macで、OpenGL GLUTを使ってコンパイルする

C

2024.04.27

Rust - Actix Web mongo ユーザー登録 JWT認証

Rust

2024.03.24

Rust - Actix Web JWT 認証認可 APIの作成

Rust

2024.02.25

Rust - Actix Web × JSON 静的ファイルをAPIで返却

Rust

2024.01.19

Rust - Actix Web × MongoDB環境をサクッと起動

Rust

2024.01.18

5分で学ぶ RustでWave Function Collapse (波動関数崩壊アルゴリズム)

Rust

2024.01.15

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

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

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

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

FOLLOW US