[Rails-API] sorceryによるAPIでの認証の実装②

学習記録

はじめに

クライアントからリクエスト時にaccess_tokenを付与して、認証の実装を完成させましょう。
すなわち、Rails-APIでもcurrent_userを使えるようにするということです。

baseコントローラーに追記

baseコントローラーに、authenticateメソッド、current_userメソッド、set_access_token!メソッドを追記します。

module V1
  class BaseController < ApplicationController
    include Api::ExceptionHandler
    include ActionController::HttpAuthentication::Token::ControllerMethods

      before_action :authenticate

      protected # サブクラスでも呼び出せる

      def authenticate
        authenticate_or_request_with_http_token do |token, _options|
          @_current_user ||= ApiKey.active.find_by(access_token: token)&.user
        end
      end

      def current_user
        @_current_user
      end

      def set_access_token!(user)
        api_key = user.activate_api_key!
        response.headers['AccessToken'] = api_key.access_token
      end

      private

      # https://github.com/NoamB/sorcery/issues/724
      def form_authenticity_token; end
    end
  end
end
  • protected
    protectedとすることで、クラス外から呼び出せなくなります。pribateとの違いは、サブクラス(継承先の子クラス)でも呼び出せます。
  • authenticateメソッド
    中で使われているauthenticate_or_request_with_http_tokenメソッドが重要になります。 こちらを実行することで、クライアントからリクエストする際のAuthorization: Bearerヘッダーに含まれているトークンを渡して、トークンに紐ついたユーザーを探し出します。 そしてそのユーザーデータをcurrent_userとして保持します。
def authenticate
  authenticate_or_request_with_http_token do |token, _options|
    @_current_user ||= ApiKey.active.find_by(access_token: token)&.user
  end
end
  • @_current_user
    @_はローカルキャッシュとして扱う場合の命名規則。
    つまり@_current_userを直接使わないでほしいということ。

authenticationsコントローラーに追記

ログイン処理を行う際はauthenticateメソッドをスキップさせます。

module Api
  module V1
    class AuthenticationsController < BaseController
      skip_before_action :authenticate

      def create
        @user = login(params[:email], params[:password])

        raise ActiveRecord::RecordNotFound unless @user

        json_string = UserSerializer.new(@user).serialized_json
        set_access_token!(@user) # レスポンスヘッダーにAccessTokenを付与

        render json: json_string
      end
    end

registrationsコントローラーに追記

module Api
  module V1
    class RegistrationsController < BaseController
      skip_before_action :authenticate

      def create
        @user = User.new(user_params)

        if @user.save
          json_string = UserSerializer.new(@user).serialized_json
          set_access_token!(@user) # レスポンスヘッダーにAccessTokenを付与

          render json: json_string
        else
          render_400(nil, @user.errors.full_messages)

終わりに

これでRails-APIでもログイン認証機能ができました。

参考

ActionController::HttpAuthentication::Token
HTTP Token authentication Simple Token example class PostsController < ApplicationController TOKEN = "secret" before_action :authenticate, except: de...
【Ruby入門】private と protected の使い方まとめ【メソッドのアクセス制御】
クラスの中で定義できるメソッドは、外から直接 呼び出せないようにアクセス制御を設定することができます。 以下か ...
Bearer認証について - Qiita
HTTP上で認証を行う場合, セッションによる認証 リクエストボディにトークンを含める認証 独自ヘッダにトークンを含める認証 Authorizationヘッダを用いた認証(Basic, Digest, Bearer) JWT認証 ...
Rubyの@_って何?? - Qiita
@_って何だろう... gem等を読んでると、 @_ を時々見るけど、@とは違うのかな? と思い、調べてみました。 def config @_config ||= Config.new end ...

コメント

タイトルとURLをコピーしました