Rails Diary

プログラミングの学習記録です。

認可と認証 authorizeメソッド(Pundit)

経緯

課題のアプリ内で使われていたauthorizeメソッドが何のメソッドか分からなかったため少し調べてみた。Punditというgemに搭載されているメソッドらしい。PunditはRubyのgemであり、認可の仕組みを提供してくれる。

Punditをなるべくやさしく解説する - Qiita

認可と認証

よくわかる認証と認可 | DevelopersIO

認証と認可は密接に絡み合っている一方で全く別の概念です。
それでも多くの場合、認可は認証に依存しています

認証(Authenctication)

パスワードや秘密の質問等の、その人だけが知っていることを提示して貰い、通信の相手が誰(何)であるかを確認すること。

認可(Authorization)

とある特定の条件に対して、リソースアクセスの権限を与えること。

★ 認可における「とある特定の条件」が認証にあたることもある

認証せずに認可する例

電車の切符があれば電車に乗れるし、ある部屋の鍵があればその部屋に入ることができる。その人が誰であるかは関係ない。人から切符や鍵を譲り受けていることもある。誰かどうかの認証をせずに電車に乗ったり、部屋に入ったりという認可が得られる。

認証したのに認可しない例

まずないらしい。何のために認証したんだ。(確かに)

しかし OpenID Connect等、認証の委譲が発生するような分散環境においては複雑な事情がありえます。

マクロな視点では「Aシステムがユーザの認証を行い、その事実をBシステムに通知した」という状態において、Aシステムは認証をしたが、認可はしていないことになります。 一方ミクロな視点では「BシステムはAシステムからユーザを認証したことを通知された。だからBシステムは独自で持つリソースへのアクセスを許すことにした」ということがあるかもしれません。恐らく、あるでしょう。 しかしそれはミクロの話で、マクロレベルでは認証しただけ。認可したかどうかは 知らん のであります。

gem: Pundit

rails g pudit:install

上記コマンドによって、app/policies/配下にapplication_policy.rbという認可のルールを記述するファイルが作成される。

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    false
  end
end
  • このファイルに定義されているクラスApplicationPolicyを継承して、コントローラごとの認可ルールを記述していく
  • userにはデフォルトでcurrent_userが引数に割り当てられている
  • recordには対応するモデルのインスタンスを手動で割り当てる

例)postという名前のモデルに対してpolicyを作成した場合

# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy
  def update?
    user.admin? or not recorc.published?
  end
end
  • モデル名_policy.rbでファイルを作成
  • モデル名Policyでクラス名を定義
  • def アクション名?で認可ルール(policy)を記述
    →このアクションの返り値によって認可するかどうか」を判断する
def update
  authorize @post
  • authorizeメソッドによって、policyファイルに記述されたdef update?が処理される
  • 引数には対応するモデルオブジェクトを入れる