class OmniAuth::Strategies::Suomifi

Public Class Methods

new(app, *args, &block) click to toggle source
Calls superclass method
# File lib/omniauth/strategies/suomifi.rb, line 491
def initialize(app, *args, &block)
  super

  # Add the request attributes to the options.
  options[:request_attributes] = scoped_request_attributes
  options[:sp_name_qualifier] = options[:sp_entity_id] if options[:sp_name_qualifier].nil?

  # Remove the nil options from the origianl options array that will be
  # defined by the Suomi.fi options
  %i[
    certificate
    private_key
    idp_name_qualifier
    name_identifier_format
    security
  ].each do |key|
    options.delete(key) if options[key].nil?
  end

  # Add the Suomi.fi options to the local options, most of which are
  # fetched from the metadata. The options array is the one that gets
  # priority in case it overrides some of the metadata or locally defined
  # option values.
  @options = OmniAuth::Strategy::Options.new(
    suomifi_options.merge(options)
  )
end

Public Instance Methods

callback_url() click to toggle source

Override the callback URL so that it always matches the one expected by Suomi.fi. No additional query string parameters can be included in the string.

# File lib/omniauth/strategies/suomifi.rb, line 551
def callback_url
  full_host + script_name + callback_path
end
request_phase() click to toggle source

Override the request phase to be able to pass the locale parameter to the redirect URL. Note that this needs to be the last parameter to be passed to the redirect URL.

# File lib/omniauth/strategies/suomifi.rb, line 522
def request_phase
  authn_request = OneLogin::RubySaml::Authrequest.new
  locale = locale_for_authn_request

  with_settings do |settings|
    url = authn_request.create(settings, additional_params_for_authn_request)
    url += "&locale=#{CGI.escape(locale)}" unless locale.nil?
    redirect(url)
  end
end
response_object() click to toggle source

This method can be used externally to fetch information about the response, e.g. in case of failures.

# File lib/omniauth/strategies/suomifi.rb, line 535
def response_object
  return nil unless request.params['SAMLResponse']

  with_settings do |settings|
    response = OneLogin::RubySaml::Response.new(
      request.params['SAMLResponse'],
      options_for_response_object.merge(settings: settings)
    )
    response.attributes['fingerprint'] = settings.idp_cert_fingerprint
    response
  end
end

Private Instance Methods

certificate() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 600
def certificate
  File.read(options.certificate_file) if options.certificate_file
end
idp_metadata_url() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 608
def idp_metadata_url
  case options.mode
  when :test
    'https://testi.apro.tunnistus.fi/static/metadata/idp-metadata.xml'
  else # :production
    'https://tunnistus.suomi.fi/static/metadata/idp-metadata-tunnistautuminen.xml'
  end
end
locale_for_authn_request() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 674
def locale_for_authn_request
  if options.idp_sso_service_url_locale_params.is_a?(Array)
    options.idp_sso_service_url_locale_params.each do |param|
      next unless request.params.key?(param.to_s)

      locale = parse_language_value(request.params[param.to_s])
      return locale unless locale.nil?
    end
  end

  options.idp_sso_service_url_default_locale
end
other_phase_for_spslo() click to toggle source

Suomi.fi requires that the service provider needs to end the local user session BEFORE sending the logout request to the identity provider.

Calls superclass method
# File lib/omniauth/strategies/suomifi.rb, line 559
def other_phase_for_spslo
  return super unless options.idp_slo_service_url

  with_settings do |settings|
    # Some session variables are needed when generating the logout request
    request = generate_logout_request(settings)
    # Destroy the local user session
    options[:idp_slo_session_destroy].call @env, session
    # Send the logout request to the identity provider
    redirect(request)
  end
end
parse_language_value(string) click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 687
def parse_language_value(string)
  language = string.sub('_', '-').split('-').first

  language if language =~ /^(fi|sv|en)$/
end
private_key() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 604
def private_key
  File.read(options.private_key_file) if options.private_key_file
end
saml_attributes() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 666
def saml_attributes
  {}.tap do |attrs|
    options.saml_attributes_map.each do |target, source|
      attrs[target] = find_attribute_by(source)
    end
  end
end
scoped_request_attributes() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 585
def scoped_request_attributes
  scopes = [:limited]
  scopes << :medium_extensive if options.scope_of_data == :medium_extensive
  scopes << :medium_extensive if options.scope_of_data == :extensive
  scopes << :extensive if options.scope_of_data == :extensive

  names = options.scoped_attributes.select do |key, _v|
    scopes.include?(key.to_sym)
  end.values.flatten

  options.possible_request_attributes.select do |attr|
    names.include?(attr[:name])
  end
end
search_success() click to toggle source

This will return true if the VTJ search (population information system, väestötietojärjestelmä) was successful and information about the person was transmitted in the SAML response.

# File lib/omniauth/strategies/suomifi.rb, line 661
def search_success
  success_string = find_attribute_by(['urn:oid:1.2.246.517.3002.111.2'])
  success_string == 'true'
end
slo_relay_state() click to toggle source

Overridden to disable passing the relay state with a request parameter which is possible in the default implementation.

Calls superclass method
# File lib/omniauth/strategies/suomifi.rb, line 574
def slo_relay_state
  state = super

  # Ensure that we are only using the relay states to redirect the user
  # within the current website. This forces the relay state to always
  # start with a single forward slash character (/).
  return '/' unless state =~ %r{^/[^/].*}

  state
end
suomifi_options() click to toggle source
# File lib/omniauth/strategies/suomifi.rb, line 617
def suomifi_options
  idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new

  # Returns OneLogin::RubySaml::Settings prepopulated with idp metadata
  # We are using the redirect binding for the SSO and SLO URLs as these
  # are the ones expected by omniauth-saml. Otherwise the default would be
  # the first one defined in the IdP metadata, which would be the
  # HTTP-POST binding.
  settings = idp_metadata_parser.parse_remote_to_hash(
    idp_metadata_url,
    true,
    sso_binding: ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'],
    slo_binding: ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect']
  )

  if settings[:idp_slo_response_service_url].nil? && settings[:idp_slo_target_url].nil?
    # Mitigation after ruby-saml update to 1.12.x. This gem has been
    # originally developed relying on the `:idp_slo_target_url` settings
    # which was removed from the newer versions. The SLO requests won't
    # work unless `:idp_slo_response_service_url` is defined in the
    # metadata through the `ResponseLocation` attribute in the
    # `<SingleLogoutService />` node.
    settings[:idp_slo_target_url] ||= settings[:idp_slo_service_url]
  end

  # Local certificate and private key to decrypt the responses
  settings[:certificate] = certificate
  settings[:private_key] = private_key

  # Define the security settings as there are some defaults that need to be
  # modified
  security_defaults = OneLogin::RubySaml::Settings::DEFAULTS[:security]
  settings[:security] = security_defaults.merge(options.security_settings)

  # Add some extra information that is necessary for correctly formatted
  # logout requests.
  settings[:idp_name_qualifier] = settings[:idp_entity_id]

  settings
end