spid 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spid
4
- class IdentityProviderConfiguration # :nodoc:
5
- attr_reader :idp_metadata, :idp_metadata_hash
6
-
7
- def initialize(idp_metadata:)
8
- @idp_metadata = idp_metadata
9
- @idp_metadata_hash = idp_metadata_parser.parse_to_hash(idp_metadata)
10
- end
11
-
12
- def entity_id
13
- @entity_id ||= idp_metadata_hash[:idp_entity_id]
14
- end
15
-
16
- def sso_target_url
17
- @sso_target_url ||= idp_metadata_hash[:idp_sso_target_url]
18
- end
19
-
20
- def slo_target_url
21
- @slo_target_url ||= idp_metadata_hash[:idp_slo_target_url]
22
- end
23
-
24
- def cert_fingerprint
25
- @cert_fingerprint ||= idp_metadata_hash[:idp_cert_fingerprint]
26
- end
27
-
28
- private
29
-
30
- def idp_metadata_parser
31
- @idp_metadata_parser ||= ::OneLogin::RubySaml::IdpMetadataParser.new
32
- end
33
- end
34
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "faraday"
4
- require "faraday_middleware"
5
-
6
- module Spid
7
- class IdentityProviders # :nodoc:
8
- class MetadataFetchError < StandardError; end
9
-
10
- def self.fetch_all
11
- new.fetch_all
12
- end
13
-
14
- def fetch_all
15
- spid_idp_entities.map do |idp|
16
- metadata_url = check_for_final_metadata_url(idp["metadata_url"])
17
- {
18
- name: idp["entity_name"].gsub(/ ID$/, "").downcase,
19
- metadata_url: metadata_url,
20
- entity_id: idp["entity_id"]
21
- }
22
- end
23
- end
24
-
25
- private
26
-
27
- def check_for_final_metadata_url(metadata_url)
28
- response = Faraday.get(metadata_url)
29
- case response.status
30
- when 200
31
- metadata_url
32
- when 301, 302
33
- response["Location"]
34
- end
35
- end
36
-
37
- def spid_idp_entities
38
- return [] if response.body["spidFederationRegistry"].nil?
39
- response.body["spidFederationRegistry"]["entities"]
40
- end
41
-
42
- def response
43
- connection.get do |req|
44
- req.url "/api/identity-providers"
45
- req.headers["Accept"] = "application/json"
46
- end
47
- end
48
-
49
- def connection
50
- Faraday.new("https://registry.spid.gov.it") do |conn|
51
- conn.response :json, content_type: /\bjson$/
52
-
53
- conn.adapter Faraday.default_adapter
54
- end
55
- end
56
- end
57
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "singleton"
4
- require "onelogin/ruby-saml/idp_metadata_parser"
5
-
6
- module Spid
7
- class IdpMetadata # :nodoc:
8
- include Singleton
9
-
10
- def initialize
11
- @identity_providers = Spid::IdentityProviders.fetch_all
12
- @metadata = {}
13
- end
14
-
15
- def [](idp_name)
16
- return @metadata[idp_name] unless @metadata[idp_name].nil?
17
- idp_hash = identity_provider_hash(idp_name)
18
-
19
- @metadata[idp_name] = parser.parse_remote_to_hash(
20
- idp_hash[:metadata_url],
21
- idp_hash[:metadata_url].start_with?("https://")
22
- )
23
- @metadata[idp_name]
24
- end
25
-
26
- def identity_provider_hash(idp_name)
27
- @identity_providers.find do |idp|
28
- idp[:name] == idp_name.to_s
29
- end
30
- end
31
-
32
- private
33
-
34
- def parser
35
- @parser ||= ::OneLogin::RubySaml::IdpMetadataParser.new
36
- end
37
- end
38
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "uri"
4
-
5
- module Spid
6
- class ServiceProviderConfiguration # :nodoc:
7
- attr_reader :host,
8
- :sso_path,
9
- :slo_path,
10
- :metadata_path,
11
- :private_key_file_path,
12
- :certificate_file_path,
13
- :digest_method,
14
- :signature_method
15
-
16
- # rubocop:disable Metrics/ParameterLists
17
- def initialize(
18
- host:,
19
- sso_path:,
20
- slo_path:,
21
- metadata_path:,
22
- private_key_file_path:,
23
- certificate_file_path:,
24
- digest_method:,
25
- signature_method:
26
- )
27
- @host = host
28
- @sso_path = sso_path
29
- @slo_path = slo_path
30
- @metadata_path = metadata_path
31
- @private_key_file_path = private_key_file_path
32
- @certificate_file_path = certificate_file_path
33
- @digest_method = digest_method
34
- @signature_method = signature_method
35
- validate_attributes
36
- end
37
- # rubocop:enable Metrics/ParameterLists
38
-
39
- def sso_url
40
- @sso_url ||= URI.join(host, sso_path).to_s
41
- end
42
-
43
- def slo_url
44
- @slo_url ||= URI.join(host, slo_path).to_s
45
- end
46
-
47
- def metadata_url
48
- @metadata_url ||= URI.join(host, metadata_path).to_s
49
- end
50
-
51
- def private_key
52
- @private_key ||= File.read(private_key_file_path)
53
- end
54
-
55
- def certificate
56
- @certificate ||= File.read(certificate_file_path)
57
- end
58
-
59
- private
60
-
61
- def validate_attributes
62
- if !DIGEST_METHODS.include?(digest_method)
63
- raise UnknownDigestMethodError,
64
- "Provided digest method is not valid:" \
65
- " use one of #{DIGEST_METHODS.join(', ')}"
66
- elsif !SIGNATURE_METHODS.include?(signature_method)
67
- raise UnknownSignatureMethodError,
68
- "Provided digest method is not valid:" \
69
- " use one of #{SIGNATURE_METHODS.join(', ')}"
70
- end
71
- end
72
- end
73
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spid/logout_request"
4
- require "onelogin/ruby-saml/settings"
5
-
6
- module Spid
7
- class SloRequest # :nodoc:
8
- attr_reader :slo_settings
9
-
10
- def initialize(slo_settings:)
11
- @slo_settings = slo_settings
12
- end
13
-
14
- def to_saml
15
- logout_request.create(slo_settings)
16
- end
17
-
18
- private
19
-
20
- def logout_request
21
- LogoutRequest.new
22
- end
23
- end
24
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "onelogin/ruby-saml/logoutresponse"
4
-
5
- module Spid
6
- class SloResponse # :nodoc:
7
- attr_reader :body, :slo_settings
8
-
9
- def initialize(body:, slo_settings:)
10
- @body = body
11
- @slo_settings = slo_settings
12
- end
13
-
14
- def valid?
15
- saml_response.validate
16
- end
17
-
18
- private
19
-
20
- def saml_response
21
- @saml_response ||= ::OneLogin::RubySaml::Logoutresponse.new(
22
- body,
23
- slo_settings
24
- )
25
- end
26
- end
27
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "onelogin/ruby-saml/settings"
4
-
5
- module Spid
6
- class SloSettings < ::OneLogin::RubySaml::Settings # :nodoc:
7
- attr_reader :service_provider_configuration,
8
- :identity_provider_configuration,
9
- :session_index
10
-
11
- def initialize(
12
- service_provider_configuration:,
13
- identity_provider_configuration:,
14
- session_index:
15
- )
16
- @service_provider_configuration = service_provider_configuration
17
- @identity_provider_configuration = identity_provider_configuration
18
- @session_index = session_index
19
-
20
- super(slo_attributes)
21
- end
22
-
23
- # rubocop:disable Metrics/MethodLength
24
- # rubocop:disable Metrics/AbcSize
25
- def slo_attributes
26
- return @slo_attributes if @slo_attributes.present?
27
- @slo_attributes = {
28
- idp_slo_target_url: identity_provider_configuration.slo_target_url,
29
- issuer: service_provider_configuration.host,
30
- idp_name_qualifier: identity_provider_configuration.entity_id,
31
- name_identifier_value: generated_name_identifier_value,
32
- name_identifier_format: name_identifier_format_value,
33
- private_key: service_provider_configuration.private_key,
34
- certificate: service_provider_configuration.certificate,
35
- idp_cert_fingerprint: identity_provider_configuration.cert_fingerprint,
36
- sessionindex: session_index,
37
- security: {
38
- logout_requests_signed: true,
39
- embed_sign: true,
40
- digest_method: service_provider_configuration.digest_method,
41
- signature_method: service_provider_configuration.signature_method
42
- }
43
- }
44
- @slo_attributes
45
- end
46
- # rubocop:enable Metrics/AbcSize
47
- # rubocop:enable Metrics/MethodLength
48
-
49
- private
50
-
51
- def generated_name_identifier_value
52
- ::OneLogin::RubySaml::Utils.uuid
53
- end
54
-
55
- def name_identifier_format_value
56
- "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
57
- end
58
- end
59
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spid/authn_request"
4
- require "onelogin/ruby-saml/settings"
5
-
6
- module Spid
7
- class SsoRequest # :nodoc:
8
- attr_reader :sso_settings
9
-
10
- def initialize(sso_settings:)
11
- @sso_settings = sso_settings
12
- end
13
-
14
- def to_saml
15
- authn_request.create(sso_settings)
16
- end
17
-
18
- private
19
-
20
- def authn_request
21
- AuthnRequest.new
22
- end
23
- end
24
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "onelogin/ruby-saml/response"
4
- require "active_support/inflector/methods"
5
-
6
- module Spid
7
- class SsoResponse # :nodoc:
8
- attr_reader :body, :sso_settings
9
-
10
- def initialize(body:, sso_settings:)
11
- @body = body
12
- @sso_settings = sso_settings
13
- end
14
-
15
- def valid?
16
- saml_response.is_valid?
17
- end
18
-
19
- def attributes
20
- raw_attributes.each_with_object({}) do |(key, value), acc|
21
- acc[normalize_key(key)] = value
22
- end
23
- end
24
-
25
- def session_index
26
- saml_response.sessionindex
27
- end
28
-
29
- def raw_attributes
30
- saml_response.attributes.attributes
31
- end
32
-
33
- private
34
-
35
- def normalize_key(key)
36
- ActiveSupport::Inflector.underscore(
37
- key.to_s
38
- ).to_sym
39
- end
40
-
41
- def saml_response
42
- @saml_response ||= ::OneLogin::RubySaml::Response.new(
43
- body,
44
- settings: sso_settings
45
- )
46
- end
47
- end
48
- end
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spid
4
- class SsoSettings < ::OneLogin::RubySaml::Settings # :nodoc:
5
- attr_reader :service_provider_configuration,
6
- :identity_provider_configuration,
7
- :authn_context,
8
- :authn_context_comparison
9
-
10
- # rubocop:disable Metrics/MethodLength
11
- def initialize(
12
- service_provider_configuration:,
13
- identity_provider_configuration:,
14
- authn_context: Spid::L1,
15
- authn_context_comparison: Spid::EXACT_COMPARISON
16
- )
17
-
18
- unless AUTHN_CONTEXTS.include?(authn_context)
19
- raise Spid::UnknownAuthnContextError,
20
- "Provided authn_context is not valid:" \
21
- " use one of #{AUTHN_CONTEXTS.join(', ')}"
22
- end
23
-
24
- unless COMPARISON_METHODS.include?(authn_context_comparison)
25
- raise Spid::UnknownAuthnComparisonMethodError,
26
- "Provided authn_context_comparison_method is not valid:" \
27
- " use one of #{COMPARISON_METHODS.join(', ')}"
28
- end
29
-
30
- @service_provider_configuration = service_provider_configuration
31
- @identity_provider_configuration = identity_provider_configuration
32
- @authn_context = authn_context
33
- @authn_context_comparison = authn_context_comparison
34
-
35
- super(sso_attributes)
36
- end
37
- # rubocop:enable Metrics/MethodLength
38
-
39
- # rubocop:disable Metrics/MethodLength
40
- # rubocop:disable Metrics/AbcSize
41
- def sso_attributes
42
- return @sso_attributes if @sso_attributes.present?
43
- @sso_attributes = {
44
- idp_sso_target_url: identity_provider_configuration.sso_target_url,
45
- assertion_consumer_service_url: service_provider_configuration.sso_url,
46
- protocol_binding: protocol_binding_value,
47
- issuer: service_provider_configuration.host,
48
- private_key: service_provider_configuration.private_key,
49
- certificate: service_provider_configuration.certificate,
50
- name_identifier_format: name_identifier_format_value,
51
- authn_context: authn_context,
52
- authn_context_comparison: authn_context_comparison,
53
- idp_cert_fingerprint: identity_provider_configuration.cert_fingerprint,
54
- security: {
55
- authn_requests_signed: true,
56
- embed_sign: true,
57
- digest_method: service_provider_configuration.digest_method,
58
- signature_method: service_provider_configuration.signature_method
59
- }
60
- }
61
- @sso_attributes[:force_authn] = true if authn_context > Spid::L1
62
- @sso_attributes
63
- end
64
- # rubocop:enable Metrics/AbcSize
65
- # rubocop:enable Metrics/MethodLength
66
-
67
- private
68
-
69
- def protocol_binding_value
70
- "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
71
- end
72
-
73
- def name_identifier_format_value
74
- "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
75
- end
76
- end
77
- end