saml認証をruby-samlライブラリを利用して自前のサーバをSPサーバとして構築
基本、前回の続きみたいなもの
前回は以下のような感じで一部の処理をcognitoが一部代行
IDP側の処理はIDP側で制御するがSP側の処理でどんなデータを送信していたかなどが全く不明のため、 作成することにした
1から作成するにしてもデータ形式とかの仕様がわからない
のでライブラリを元に追いかけることにする 今回は「ruby-saml」の情報を元にexampleを探して作成
流れ
手順
1. SP側のエンティティIDとACS URLを決める
No | 項目 | 設定値 |
---|---|---|
1 | エンティティID | http://localhost:3000/saml/metadata |
2 | ASC | http://localhost:3000/saml/acs |
2. IDPにエンティティIDとACS URLを設定し、IDPのメタデータを取得
3. 環境変数に設定情報のデータを定義
.env.dev
SP_ISSUER = SP用のエンティティID(例:http://localhost:3000/saml/metadata) SP_ACS_URL = SP用のIDPの認証結果を受け取るコールバック(例:http://localhost:3000/saml/acs) SP_LOGOUT = SP用のログアウト用のエンドポイント(例:http://localhost:3000/saml/logout) SP_CERT_KEY= SP用の証明書に利用したキー(例:saml/sp/private.pem) SP_CERT = SP用の証明書(例:saml/sp/sp.cert) IDP_ISSUER = IDPのエンティティID(メタデータに記載) IDP_SSO_URL= IDPのシングルサインオンURL(メタデータに記載) IDP_SLO_URL= IDPのシングルサインアウトURL(メタデータに記載) IDP_CERT = IDPの証明書(例:saml/idp/idp.cert) IDP_ID_FORMT = IDPのIDフォーマット(例:urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress)
4. コード改修
app/models/account.rb
class Account < ActiveRecord::Base def self.get_saml_settings(url_base) # this is just for testing purposes. # should retrieve SAML-settings based on subdomain, IP-address, NameID or similar settings = OneLogin::RubySaml::Settings.new # When disabled, saml validation errors will raise an exception. settings.soft = true #SP section settings.issuer = ENV["SP_ISSUER"] settings.assertion_consumer_service_url = ENV["SP_ACS_URL"] settings.assertion_consumer_logout_service_url = ENV["SP_LOGOUT"] settings.certificate = File.read(Rails.root.join('config', ENV["SP_CERT"])) settings.private_key = File.read(Rails.root.join('config', ENV["SP_CERT_KEY"])) # IdP section settings.idp_entity_id = ENV["IDP_ISSUER"] settings.idp_sso_target_url = ENV["IDP_SSO_URL"] settings.idp_slo_target_url = ENV["IDP_SLO_URL"] settings.idp_cert = File.read(Rails.root.join('config', ENV["IDP_CERT"])) settings.name_identifier_format = ENV["IDP_ID_FORMT"] # Security section settings.security[:authn_requests_signed] = true settings.security[:logout_requests_signed] = true settings.security[:logout_responses_signed] = true settings.security[:metadata_signed] = true settings.security[:digest_method] = XMLSecurity::Document::SHA256 settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256 settings end end
※証明書は任意の場所へ配置しておくこと
↓
結果
SAMLリクエストとSAMLレスポンスについて
SAMLリクエスト
まずはXML形式で作成するみたい
<samlp:AuthnRequest AssertionConsumerServiceURL='http://localhost:3000/saml/acs' Destination='IDP側のリクエストURL' ID='任意のリクエスト文字列' IssueInstant='リクスト日時(UTC)' Version='2.0' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'> <saml:Issuer>http://localhost:3000/saml/metadata</saml:Issuer> <samlp:NameIDPolicy AllowCreate='true' Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'/> </samlp:AuthnRequest>
↓
でbase64で暗号化しているみたいです
[IDPのログインURL]?SAMLRequest=fZLLTsMwEEV%2FJTuvUttJA9RqKkVESJUA...
SAMLレスポンスも同じようにXML形式の物が暗号化されてくるので デコードしてから検証する感じ
成果物
※環境変数とかは自前の環境のものを利用すること ※元々のサンプルとはバージョンが違うためところところ設定を追記しています
参考
GitHub - onelogin/ruby-saml: SAML SSO for Ruby
GitHub - onelogin/ruby-saml-example: Ruby example of how to use the ruby-saml gem
ruby-saml を使ったOneLogin での SAML 認証の処理シーケンスを追う - Qiita
Rails+AzureADでSAML認証のSSOを実装する