こんにちは!kossyです!
今回はSSOを実現するGem「ruby-saml」で「Invalid settings, idp_sso_service_url is not set!」が発生した場合の対処法について、
備忘録としてブログに残してみたいと思います。
環境
Ruby 2.6.8
Rails 6.0.4
MacOS BigSur
ruby-saml 1.13.0
エラーの発生箇所のコードリーディング
まずはどこで例外が投げられているのか、binding.pryで処理を止めて、
pry-byebug Gemを入れると使用できるstepコマンドを使いながら確認してみます。
class SamlController < ApplicationController skip_before_action :verify_authenticity_token, :only => [:acs, :logout] # 省略 def sso settings = Account.get_saml_settings(get_url_base) if settings.nil? render :action => :no_settings return end request = OneLogin::RubySaml::Authrequest.new binding.pry redirect_to(request.create(settings)) end # 省略 end
localhost:3000/saml/sso にアクセスすると、処理が止まります。
From: /app/app/controllers/saml_controller.rb:18 SamlController#sso: 8: def sso 9: settings = Account.get_saml_settings(get_url_base) 10: if settings.nil? 11: render :action => :no_settings 12: return 13: end 14: 15: request = OneLogin::RubySaml::Authrequest.new 16: 17: binding.pry => 18: redirect_to(request.create(settings)) 19: end
この状態でstepコマンドでcreateメソッドの処理を見に行ってみます。
From: /usr/local/bundle/gems/ruby-saml-1.13.0/lib/onelogin/ruby-saml/authrequest.rb:37 OneLogin::RubySaml::Authrequest#create: 36: def create(settings, params = {}) => 37: params = create_params(settings, params) 38: params_prefix = (settings.idp_sso_service_url =~ /\?/) ? '&' : '?' 39: saml_request = CGI.escape(params.delete("SAMLRequest")) 40: request_params = "#{params_prefix}SAMLRequest=#{saml_request}" 41: params.each_pair do |key, value| 42: request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}" 43: end 44: raise SettingError.new "Invalid settings, idp_sso_service_url is not set!" if settings.idp_sso_service_url.nil? or settings.idp_sso_service_url.empty? 45: @login_url = settings.idp_sso_service_url + request_params 46: end
44行目が今回の例外をraiseしているところですね。
$ settings.idp_sso_service_url.nil? or settings.idp_sso_service_url.empty? => true
true が返りました。 タイトルの例外が生じた原因は、settingsオブジェクトのidp_sso_service_url属性がnilまたは空だったからですね。
idp_sso_service_urlはsettingsオブジェクトのメソッドになっていました。
# @return [String] IdP Single Sign On Service URL # def idp_sso_service_url @idp_sso_service_url || @idp_sso_target_url end
idp_sso_service_url属性がDBに保存されているか、はたまたconfig値を引っ張ってきているかは各々のアプリケーション次第かと思いますが、
settingsオブジェクトの生成時に、idp_sso_service_url属性に値が必ず入るようにすればOKそうですね。
まとめ
ruby-samlのReadMe通りに実装してテストしているときにはあまり遭遇しないかもしれませんが、
DBから値を引っ張ってくるような構成の場合は、きちんと制約をかけてあげていないと、ハマってしまうかもしれませんね。
大いに参考にさせていただいたサイト
素晴らしいコンテンツの提供、誠にありがとうございます。