📚

既存のRails7プロジェクトにOmniauth::MicrosoftGraphを導入してEntra IDでユーザー認証する

2024/05/06に公開

前提

  • Entra IDのアプリ登録は済んでいる
  • Entra IDで認証だけできればよい(ベーシック認証的使い方)

変更したファイル

Gemfile
gem 'omniauth-oauth2'
gem 'omniauth-microsoft_graph'
gem 'omniauth-rails_csrf_protection'
config/routes.rb
  # omniauth
  get 'auth/:provider/callback', to: 'sessions#create'
  get 'auth/failure', to: redirect('/')
  get 'login', to: 'sessions#new'
  get 'logout', to: 'sessions#destroy', as: 'logout'
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include SessionsHelper
  before_action :check_logged_in

  def check_logged_in
    return if current_user

    redirect_to controller: 'sessions', action: 'new'
  end

新規作成したファイル

config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :microsoft_graph, ENV['ENTRA_APPLICATION_CLIENT_ID'], ENV['ENTRA_APPLICATION_CLIENT_SECRET'], client_options: {
  site:          "https://login.microsoftonline.com/#{ENV['ENTRA_TENANT_ID']}",
  authorize_url: "https://login.microsoftonline.com/#{ENV['ENTRA_TENANT_ID']}/oauth2/v2.0/authorize",
  token_url:     "https://login.microsoftonline.com/#{ENV['ENTRA_TENANT_ID']}/oauth2/v2.0/token"
}
  configure do |config|
    config.full_host = "#{ENV['ENTRA_FULL_HOST']}"
  end
end
config/initializers/session_store.rb
Rails.application.config.session_store :cache_store
rails dev:cache
app/helpers/sessions_helper.rb
module SessionsHelper
  def current_user
    return unless (user_id = session[:user_id])

    @current_user ||= user_id
  end
  
  def log_in(user)
    session[:user_id] = user
  end

  def log_out
    session.delete(:user_id)
    @current_user = nil
  end
end
app/views/sessions/new.html.erb
<%= form_tag('/auth/microsoft_graph?login_hint=email@example.com', method: 'post', data: {turbo: false}) do %>
  <button type='submit'>Login with MS EntraID</button>
<% end %>
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  skip_before_action :check_logged_in, only: [:new, :create]

  def new
    render :new
  end

  def create
    if user = request.env['omniauth.auth']
      log_in user
    end
    redirect_to root_path
  end
   
  def destroy
    log_out
    redirect_to root_path
  end

  private

  def auth_hash
    request.env['omniauth.auth']
  end
end

EntraIDの変数管理

開発環境はdotenv Gemを利用して.envファイルにまとめる。production環境(Docker)は同内容を適当場所にファイル保存してdockerの--env-fileオプションで渡す。

.env
ENTRA_APPLICATION_CLIENT_ID=<EntrIDから入手したClient ID>
ENTRA_APPLICATION_CLIENT_SECRET=<Client IDのシークレット>
ENTRA_TENANT_ID=<テナントID>
ENTRA_FULL_HOST=<稼働サーバーのFQDN>

Discussion