使用saml_idp gem实现SAML SSO时元数据拉取与主机识别异常
saml_idp 校验ACS Host不生效问题排查
场景背景
- 单应用双角色搭建SSO环境:IdP服务运行在
localhost:3000,SP服务运行在lvh.me:3000 - 依赖组件:IdP侧使用
saml_idpgem,SP侧使用omniauth-samlgem - 可复现现状:
- 绕过
saml_idpgem内SamlIdpController#validate_saml_request校验逻辑时,SSO全流程可正常运行,IdP可返回匹配config/saml_idp.rb配置、包含用户邮箱与姓名字段的合法SAML响应 - 保留校验逻辑时,请求流程中断,无法正常完成登录
- 绕过
触发报错
校验流程抛出的日志输出:
[] compare to lvh.meNo acceptable AssertionConsumerServiceURL, either configure them via config.service_provider.response_hosts or match to your metadata_url_host
现有配置
IdP端 config/saml_idp.rb
service_providers = { "my-application" => { fingerprint: ENV['SAML_CERT_FINGERPRINT'], metadata_url: "http://lvh.me:3000/auth/saml/metadata", response_hosts: ["lvh.me:3000"] }, }
已验证上述配置中指向的metadata_url路径下存在合法的SP元数据文件。
SP端 config/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do provider :saml, :assertion_consumer_service_url => "http://lvh.me:3000/auth/saml/callback", :issuer => "portal", :idp_sso_target_url => "http://localhost:3000/saml/auth", :idp_sso_target_url_runtime_params => {:original_request_param => :mapped_idp_param}, :idp_cert => ENV['SAML_CERT'], :idp_cert_fingerprint => ENV['SAML_CERT_FINGERPRINT'], :idp_cert_fingerprint_validator => lambda { |fingerprint| fingerprint }, :name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" end
根因定位
- 校验逻辑读取的允许响应host列表为空,对应日志开头的空数组
[],根源为IdP端SP配置的匹配键与SP实际发送的Issuer值不一致:saml_idpgem的ACS地址校验流程,会从SP发来的AuthnRequest中提取Issuer字段值,作为键去service_providers配置字典中匹配对应SP的规则- 当前SP端配置的
issuer值为portal,但IdP端service_providers的配置键为my-application,校验流程完全匹配不到对应配置,因此读取不到response_hosts、metadata_url的配置值,最终拿到的允许host列表为空 - 空host列表自然无法与请求中的
lvh.mehost匹配,触发ACS地址不合法的报错。绕过校验时因跳过了配置匹配环节,流程不受影响。
修复方案
- 将IdP端
config/saml_idp.rb中service_providers的配置键,从my-application修改为与SP端issuer值完全一致的portal - 配置修改完成后重启Rails服务,避免配置缓存导致的规则不生效问题
- 修复后校验流程可正确读取到配置中的
response_hosts: ["lvh.me:3000"]规则,完成host匹配,ACS校验即可正常通过
内容的提问来源于stack exchange,提问作者Linda
相关产品推荐
相关产品推荐

