devise_saml_authenticatable + LINE WORKS で SSOログイン を試してみた
株式会社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のデベロッパーコンソールから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