http_basic_authenticate_withがNoMethodErrorになった
前提
やりたいこと
ステージング環境でBasic認証を導入する。
修正前のコードとエラーの内容
class ApplicationController < ActionController::Base before_action :basic_auth_in_staging private def :basic_auth_in_staging http_basic_authenticate_with name: ENV.fetch('BASIC_AUTH_NAME'), password: ENV.fetch('BASIC_AUTH_PASS') if Rails.env.staging? end end
としてステージング環境にアクセスしたら、
NoMethodError (undefined method `http_basic_authenticate_with' 以下略
ほぇ!?
Rails本体のコードを調査
Railsのソースコードを覗いてみると、
module ClassMethods def http_basic_authenticate_with(name:, password:, realm: nil, **options) before_action(options) { http_basic_authenticate_or_request_with name: name, password: password, realm: realm } end end def http_basic_authenticate_or_request_with(name:, password:, realm: nil, message: nil) authenticate_or_request_with_http_basic(realm, message) do |given_name, given_password| ActiveSupport::SecurityUtils.secure_compare(given_name, name) & ActiveSupport::SecurityUtils.secure_compare(given_password, password) end end
は〜ん、before_action
でBasic認証の主要メソッドであるhttp_basic_authenticate_or_request_with
を呼び出しているだけのメソッドなのか。
before_action
にbefore_action
を使ったメソッドを使ってしまったのが良くなかったのでしょうか。
修正後のコード
以下のように修正したら意図したとおりBasic認証が動作しました!
class ApplicationController < ActionController::Base before_action :basic_auth_in_staging private def return unless Rails.env.staging? authenticate_or_request_with_http_basic do |username, password| username == ENV.fetch('BASIC_AUTH_NAME') && password == ENV.fetch('BASIC_AUTH_PASS') end end end