devise_saml_authenticatable + LINE WORKS で SSOログイン を試してみた | Dev Driven 開発・デザインチーム devise_saml_authenticatable + LINE WORKS で SSOログイン を試してみた | 働くひとと組織の健康を創る iCARE

BLOG

devise_saml_authenticatable + LINE WORKS で SSOログイン を試してみた

2022/12/21

株式会社iCAREでサーバーサイドエンジニアをしている越川と申します!

この記事は iCARE Dev Advent Calendar 2022 の21日目の記事です。

今年は devise_saml_authenticatable + LINE WORKS で SSOログイン を試してみたので、備忘録としてブログに残してみたいと思います。

devise_saml_authenticatable のレポジトリ

環境

Ruby 2.7系
Rails 6.0系

Railsアプリの新規作成

rails newでサンプルアプリを作ります。

$ bundle exec rails new devise_saml_sp -d postgresql -T

$ cd devise_saml_sp

$ bundle exec rails db:create

Gemの導入

deviseとdevise_saml_authenticatableを導入します。

# Gemfile

gem 'devise'
gem 'devise_saml_authenticatable'

その後bundle installを実行します。

$ bundle instal

DeviseのインストールとUserモデルの作成・編集

$ bundle exec rails g devise:install

$ bundle exec rails g devise user

作成されたUserモデルに修正を加えます。

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :saml_authenticatable # saml_authenticatableを追加
end

ビューにフラッシュメッセージを表示するための記述を追記します。

  <body>
    # ここから追加
    <% if flash[:notice] %>
      <div>
        <%= flash[:notice] %>
      </div>
    <% end %>
    <% if flash[:alert] %>
      <div>
        <%= flash[:alert] %>
      </div>
    <% end %>
    # ここまで

    <%= yield %>
  </body>

config/devise.rbにsamlの設定を追加

    config.saml_configure do |settings|
      # assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
      settings.assertion_consumer_service_url     = "http://localhost:3000/users/saml/auth"
      settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      settings.protocol_binding                   = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      settings.name_identifier_format             = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
      settings.issuer                             = "http://localhost:3000/users/saml/metadata"
      settings.authn_context                      = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
      settings.idp_entity_id                      = "https://auth.worksmobile.com/saml2/your_group_name"
      settings.idp_slo_service_url                = "https://auth.worksmobile.com/saml2/idp/your_group_name/logout"
      settings.idp_sso_service_url                = "https://auth.worksmobile.com/saml2/idp/your_group_name"
      settings.idp_cert_fingerprint               = "後ほど設定します"
      settings.idp_cert_fingerprint_algorithm     = XMLSecurity::Document::SHA256
    end

仮のトップページの作成

$ rails g controller home index
# app/views/home/index.html.erb

<% if current_user.present? %>
  <p>ID: <%= current_user.email %></p>
  <p><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></p>
<% else %>
  <p>ログインしてね☆</p>
  <p><%= link_to "メアドとパスワードでログイン", new_user_session_path %></p>
  <p><%= link_to "SAMLでログイン", new_user_sso_session_path %></p>
<% end %>
# config/routes.rb

Rails.application.routes.draw do
  root 'home#index' # 追加

  # 省略
end

config/attribute-map.ymlの作成

SAMLの値とUserモデルの値をマッピングするためのconfigファイルを作成します。

# config/attribute-map.yml

"urn:mace:dir:attribute-def:email": "email"

LINE WORKSにSAML Appsを新規登録

LINE WORKSでSAML2.0によるSSO機能を使うには、有料アカウントで登録する必要があります。(2022年12月時点。スタンダード・ユーザー一人当たり月額450円)

450円は自己投資だと思うようにしましょう(技術書よりは全然安いし、、、)

LINE WORKSの製品プラン

まずは無料でアカウントを作成し、その後にスタンダードプランにアップグレードする必要があります。

無事課金し終えてスタンダードプランにアップグレードできましたら、LINE WORKSのデベロッパーコンソールからSSO機能を利用するアプリの登録を行う必要があります。

・Application Nameにはsaml-sp
・ACS URLには http://localhost:3000/users/saml/auth
・SP Issuer(Entity ID)には http://localhost:3000/users/saml/metadata

を入力してください。

「次へ」をクリックし、以下の表示が出れば設定成功です。

登録後、以下URLにアクセスすると、

https://developers.worksmobile.com/jp/console/idp/saml/view

先ほど追加したサービスが表示されていると思いますので、まずは使用状態を「無効」から「有効」に切り替えます。

「変更」をクリックすると、以下のモーダルが表示されますので、ラジオボタンの「有効」をクリックし、「保存」をクリックすると、使用状態を切り替えられます。

次に、「LINE WORKS Identity Provider情報」をクリックすると、SSO URL と Response Issuer の確認と Certificate のダウンロードが行えますので、

SSO URL と Response Issuer は一旦どこかにコピペしておき、 Certificateのダウンロードを行ってください。

ダウンロードしたCertificateを使って、以下コマンドを叩いてフィンガープリントを取得してください。

$ openssl x509 -text -noout -in ~/Downloads/<your file name> -fingerprint -sha256

出力された値はおそらく以下のような感じになるはず。

SHA256 Fingerprint=59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM

この出力された値を settings.idp_cert_fingerprint に設定してください。

    config.saml_configure do |settings|
      # assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
      settings.assertion_consumer_service_url     = "http://localhost:3000/users/saml/auth"
      settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      settings.protocol_binding                   = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      settings.name_identifier_format             = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
      settings.issuer                             = "http://localhost:3000/users/saml/metadata"
      settings.authn_context                      = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
      settings.idp_entity_id                      = "https://auth.worksmobile.com/saml2/your_group_name"
      settings.idp_slo_service_url                = "https://auth.worksmobile.com/saml2/idp/your_group_name/logout"
      settings.idp_sso_service_url                = "https://auth.worksmobile.com/saml2/idp/your_group_name"
      settings.idp_cert_fingerprint               = "59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM:59:10:LO:D0:9L:31:PO:AM"
      settings.idp_cert_fingerprint_algorithm     = XMLSecurity::Document::SHA256
    end

これで準備完了です。

動作確認

まず、Userモデルにレコードを追加します。この時、LINE WORKSのIDと同じ値をemailに設定する必要があります。

$ rails c

$ User.create!(email: "your_line_works_id@your_group_name", password: "1234test")

その後、トップページの「SAMLでログイン」のリンクを踏んでください。諸々の設定が正しければLINE WORKSのログイン画面に遷移します。

IDとPASSWORDを入力してログインを押すと、自分のアプリにリダイレクトされます。

ログアウトボタンを押すと正常にログアウトできます。

メールアドレスとパスワードでのログインも試してみましょう。

正しいメールアドレスとパスワードであればフラッシュメッセージと共にトップページにリダイレクトされるはずです。

ログインした状態で /users/saml/sign_in にアクセスすると以下の表示になります。

既にログイン済みである旨のフラッシュメッセージが表示されました。

まとめ

メールアドレス + パスワードでのログインとSAMLによるSSOを共存させることを比較的簡単に行えました。

本来はUserモデルに紐づく形でSAMLの設定を保存するモデルを追加するのが筋だと思いますが、今回は「まずは動かす」ところに重点を置いてみました。

また、devise_saml_authenticatable内でruby-samlというGemが使われているんですが、SAML認証の根幹の処理を書いてたりするので、コードを読んでみると面白いと思います。

大いに参考にさせていただいたサイト

素晴らしいコンテンツの提供、誠にありがとうございます。

https://github.com/apokalipto/devise_saml_authenticatable/blob/master/README.md
https://qiita.com/tokotan/items/9340b70df064b8edc90c