1

我正在尝试在我的项目中添加ruby​​-saml。但是我对如何在我的场景中实现它有点困惑。我在一个网站上,比如说 abc.com,并且有一个按钮。当我单击按钮时,我需要重定向到网站 xyz.com,我需要在其中传递 SAML XML 并将其发送到 xyz.com/SAML。SAML 请求将由 xyz.com 处理,然后他们会向我发送回复。谁能给我一些想法如何实现它?

另外,我对这些领域感到困惑。有人可以给我一个快速的总结吗?

settings.assertion_consumer_service_url
settings.sp_entity_id
settings.idp_entity_id
settings.idp_sso_service_url
settings.idp_slo_service_url

def init
  request = OneLogin::RubySaml::Authrequest.new
  saml_settings.name_identifier_value_requested = "testuser@example.com"
  saml_settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
  redirect_to(request.create(saml_settings))
end



 def saml_settings
  settings = OneLogin::RubySaml::Settings.new

  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
  settings.idp_sso_service_url            = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
  settings.idp_sso_service_binding        = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" # or :post, :redirect
  settings.idp_slo_service_binding        = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" # or :post, :redirect
  settings.idp_cert_fingerprint           = OneLoginAppCertFingerPrint
  settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
  settings.name_identifier_format         = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"

  # Optional for most SAML IdPs
  settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
  # or as an array
  settings.authn_context = [
    "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
    "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
  ]

  # Optional bindings (defaults to Redirect for logout POST for ACS)
  settings.single_logout_service_binding      = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" # or :post, :redirect
  settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" # or :post, :redirect

  settings
end
4

1 回答 1

2

你想要_____吗:

  • a.) 从其他服务(如 Microsoft Azure Directory、OneLogin 等)启用 SAML 登录?(那么您就是 SP = 服务提供商)
  • b.) 您的应用拥有用户并为其他应用提供登录服务(IDP = 身份提供者)

我想它是a)?然后取决于:它是每个客户的提供商,那么它是动态的吗?每个客户可以配置自己的 IDP,还是为整个应用程序固定一个?如果是后者,那么我强烈建议omniauth-saml改用它,这更容易配置。

但是,如果您想使用 Enterprise Sign In Per Customer,那么我们就是这样做的。

  • 第一:我从不纠结所有的具体设置和 url,Saml 可以通过“元数据 url”自动配置,我们让我们的客户指定一个元数据 uri,这个 uri 包含我们需要的所有信息,所以我们可以用提供的解析它班级:
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
settings = idp_metadata_parser.parse_remote(organisation.idp_meta_data_url)

然后我们添加我们自己的设置+路线信息给它:

   settings.assertion_consumer_service_url = "https://#{request.host}/saml/consume/#{organisation.id}"
        settings.issuer                         = "https://#{@request.host}/saml/metadata/#{organisation.id}"
        settings.name_identifier_format         = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
        # Optional for most SAML IdPs
        settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
# You would need a normal certificate/private key to enable signature stuff
        settings.certificate = File.read('config/saml/certificate.crt')
        settings.private_key = File.read('config/saml/private_key.key')
# In our case customer can optional activate signature validation:
        if organisation.signature_enabled?
          settings.security[:authn_requests_signed]   = true     # Enable or not signature on AuthNRequest
          settings.security[:logout_requests_signed]  = true     # Enable or not signature on Logout Request
          settings.security[:logout_responses_signed] = true     # Enable or not signature on Logout Response
          settings.security[:want_assertions_signed]  = true     # Enable or not the requirement of signed assertion
          settings.security[:metadata_signed]         = true     # Enable or not signature on Metadata

          settings.security[:digest_method]    = XMLSecurity::Document::SHA1
          settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
        end

请求/响应

这些或多或少来自 ruby​​-saml 示例:

控制器:

  skip_before_action :verify_authenticity_token

  def init
    @saml_request = OneLogin::RubySaml::Authrequest.new
    redirect_url = @saml_request.create(saml_settings)
    if redirect_uri
      redirect_to(redirect_uri)
    else
      @error = t('saml_controller.error')
      render 'error'
    end
  end

  def consume
    @saml_response = OneLogin::RubySaml::Response.new(params[:SAMLResponse])
    @saml_response.settings = saml_settings
  
    if @saml_response.is_valid?
      # do application logic, create user/update user sign in user
      sign_in(....) 
      session[:session_valid_for] = 12.hours.from_now.to_i
      redirect_to '/'
      else
        redirect_to '/watcher/profile'
      end
    else
      @error = @saml_response.errors
      render 'error'
    end
  end

元数据

大多数客户也需要元数据 uri,以便将 SP 添加到他们的 IDP 中(并自动配置该部分),因此您还需要提供元数据,例如“/saml/#{org.id}/metadata”和返回元数据:

def metadata
  meta = OneLogin::RubySaml::Metadata.new
  render xml: meta.generate(saml_settings), content_type: "application/samlmetadata+xml"
end

更新:使用omniauth-saml

我们还在应用程序中使用 Omniauth saml。这很简单,但配置取决于您要集成的服务器。您将需要一个 sso 目标 url(来自另一端的使用 url)和一个证书指纹或证书以确保安全。您还可以指定“名称标识符”、电子邮件或用户名或类似的东西。

Rails.application.config.middleware.use OmniAuth::Builder do
  use OmniAuth::Strategies::SAML,
    idp_sso_target_url: "??",
    idp_slo_target_url: "??",
    idp_cert_fingerprint: "??",
    name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", 
    # or "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" for E-Mail
    issuer: "YourAppName.com"

Have a look at omniauth-saml's good Readme doc for a list of all options. You can also request more attributes from OneLogin/IDP by using the request_attributes:

:request_attributes - Used to build the metadata file to inform the IdP to send certain attributes along with the SAMLResponse messages. Defaults to requesting name, first_name, last_name and email attributes. See the OneLogin::RubySaml::AttributeService class in the Ruby SAML gem for the available options for each attribute.

Update: Passing dynamic parameters to omniauth saml's redirect to Idp:

There seems to be no option in Omniauth-saml to have dynamic parameters, so you can try to patch/override the behavior. Omniauth-SAML is a Rack-middleware, so you only have access to the request object but not normal Rails stuff. If you trust your users (which you should not) then you can put the info in the param to omniauth: /auth/saml?something1=foo&bar=2, or you could encrypt the parameters with ActiveSupport Message Encryptor.

If you then know how to extract the dynamic parameters from the request you can apply this patch dynamically, because Ruby!

# put this into
#
# config/initializers/omniauth_patch.rb
#
module OmniauthPatch
  def additional_params_for_authn_request
    # here you should have access to the current request
    # try around with binding.irb what you can do
    binding.irb
    # return parameters you want to pass to the saml redirect
    {
      email: email,
      # ...
    }
  end
end

OmniAuth::Strategies::SAML.include OmniauthPatch
于 2021-09-10T07:48:35.013 回答