Help us understand the problem. What is going on with this article?

Rack middlewareを使ってRailsアプリケーションにBasic認証を組み込んでみた

この記事はマネーフォワード アドベントカレンダー21日目の記事です。

Railsエンジニアの @kamillle です。

今回はRack middlewareでBasic認証をRailsのアプリケーションに組み込んでみました。

RailsでBasic認証をどうやって実装するか

Googleで rails basic auth とググると api.rubyonrails.orgドキュメントがヒットし、http_basic_authenticate_withにnameやpasswordというkey名を含んだHashを渡すと、そのコントローラーのアクションに対してBasic認証がかけられることがわかりました。

一行でかけるのでRailsぽくていいなーと思ったですが、同時に下記の違和感を覚えました。

  • リクエストがコントローラーに来る前に解決すべきことなのかなと思った
  • コントローラーの継承関係を間違うと一部のControllerにBasic認証がかかってなかったってことが起きそう
    • テスト書いておけばいいんですが、全コントローラーのrequest specにBasic認証のテスト書くのもめんどくさい、忘れそう

Rackがあるじゃないか

Rack middlewareでBasic認証の機構を実装し、 @app.call(env) する前にBasic認証することができればRack側で処理が完結するためコントローラーにリクエストが行くこともないし、全エンドポイントに対してBasic認証をかけることができるので、アプリケーションの開発時に認証のことを気にする必要がなくなるんじゃないかなと考えました。

Basic認証のロジックをオレオレで実装したくなかったので、 Rack basic auth とかでググってると Rack::Auth::Basic というクラスを見つけました。

このクラスはRFCに沿った形でBasic認証を実装してくれているので、オレオレなことをしなくていいし、使うのも簡単にできそうだったので早速やってみました。

このようなRack middlewareを実装し、

# lib/middlewares/basic_auth_middleware.rb 

module Middlewares
  class BasicAuthMiddleware
    def initialize(app)
      @app = app
    end

    def call(env)
      Rack::Auth::Basic.new(@app) do |username, password|
        username == 'username' && password == 'password'
      end.call(env)
    end
  end
end

それをミドルウェアスタックに追加しました

# config/application.rb

...

require_relative '../lib/middlewares/basic_auth_middleware.rb'

...

module RackBasicAuth
  class Application < Rails::Application
    ...
    ...

    config.middleware.use(::Middlewares::BasicAuthMiddleware)
  end
end

ここまで実装してRailsのサーバーを立ち上げてみました

image.png

:tada:

今回Basic認証を実装したアプリケーションは下記のリポジトリで公開しています。
https://github.com/kamillle/rack_basic_auth

おわりに

Rack::Auth::Basicを使うことでも簡単にBasic認証をアプリケーションに組み込むことができました。

今までRack middlewareを実装したことはなかったのですが、Rails側にリクエストを渡す前にリクエストの解析が可能になるので便利だな〜と思いました(弊社のGitHubのOrganization内のコードを見てみると、一部のエンドポイントにのみIP制限をかけるためにRackを使っているプロジェクトがありました)。

kamillle
Rubyist.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした