【初心者向け】RailsでAPI開発 Part.2


これは何?

【初心者向け】RailsでAPI開発 Part.1

の続きです。

今回は認証編となります。


概要


▼ 仕組み

認証については、下記のように判定するものとする。


  1. emailとpasswordが入力される。

  2. 登録が完了したらトークンを発行してクライアントに返す。

  3. クライアントは毎リクエスト、トークンをヘッダーに入れてリクエストを送る。


▼ 使用するもの


  • has_secure_password


    • bcrypt(事前に追加しておいてください。)



  • has_secure_token


    • ActionController::HttpAuthentication::Token


      • authenticate_with_http_token






手順


① UserModelを整える

- name:string

- email:string
- password_digest:string
- token:token


addp/models/user.rb

before_save { self.email = self.email.downcase }

has_many :books
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
has_secure_token

上記のように設定することで、

バリデーションはもとより、Userが作成されると自動的に、

- セキュアなパスワードがDBに保存

- セキュアなトークンがDBに保存

されていく。


② UserControllerを整える


app/controllers/v1/users_controller.rb

before_action :set_user, only: [:show]

def show
render json: @user, adapter: :json
end

def create
user = User.new(user_params)
if user.save
render json: user, adapter: :json, status: 201
else
render json: { error: user.errors }, status: 422
end
end

private
def set_user
@user = User.find(params[:id])
end

def user_params
params.require(:user).permit(:name, :email, :password, :token)
end



③ トークン認証


app/controllers/application_controller.rb

include ActionController::HttpAuthentication::Token::ControllerMethods

rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

def authenticate
authenticate_with_http_token do |token, options|
@current_user = User.find_by(token: token)
@current_user != nil ? true : render_unauthorized_request
end
end

def render_unauthorized_request
self.headers['WWW-Authenticate'] = 'Token realm="Application"'
render json: { error: 'No Authentication' }, status: 401
end

def record_not_found
render json: { error: 'Record not Found' }, status: 404
end



④ 認証が必要なページに設定


app/controllers/v1/users_controller.rb

..

before_action :authenticate, except: [:create]
..


まとめ

難易度の高いと思われていた認証も、

Railsの標準の機能でかなり簡単に実装できることがわかりました。

まずはサービスに登録させ、そのタイミングでトークンを発行してクライアントに送ってあげれば、

あとはヘッダーのトークン情報に合わせて認証しているかを判断しているだけです。

それをリクエスト毎に判断してあげるというシンプルな構造です。

次はPunditを使って認可周りを整えていきます。

ここまではサービスに登録しているかどうかだけの判断でしたが、

認可を作り込むことで、自分の情報だけは編集できるようにするなどのことができるようになります。