decidim-suomifi 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Suomifi
5
+ module Verification
6
+ # This is an engine that performs user authorization.
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace Decidim::Suomifi::Verification
9
+
10
+ paths["db/migrate"] = nil
11
+ paths["lib/tasks"] = nil
12
+
13
+ routes do
14
+ resource :authorizations, only: [:new], as: :authorization
15
+
16
+ root to: "authorizations#new"
17
+ end
18
+
19
+ initializer "decidim_suomifi.verification_workflow", after: :load_config_initializers do
20
+ next unless Decidim::Suomifi.configured?
21
+
22
+ # We cannot use the name `:suomifi` for the verification workflow
23
+ # because otherwise the route namespace (decidim_suomifi) would
24
+ # conflict with the main engine controlling the authentication flows.
25
+ # The main problem that this would bring is that the root path for
26
+ # this engine would not be found.
27
+ Decidim::Verifications.register_workflow(:suomifi_eid) do |workflow|
28
+ workflow.engine = Decidim::Suomifi::Verification::Engine
29
+
30
+ Decidim::Suomifi::Verification::Manager.configure_workflow(workflow)
31
+ end
32
+ end
33
+
34
+ def load_seed
35
+ # Enable the `:suomifi_eid` authorization
36
+ org = Decidim::Organization.first
37
+ org.available_authorizations << :suomifi_eid
38
+ org.save!
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Suomifi
5
+ module Verification
6
+ class Manager
7
+ def self.configure_workflow(workflow)
8
+ Decidim::Suomifi.workflow_configurator.call(workflow)
9
+ end
10
+
11
+ def self.metadata_collector_for(saml_attributes)
12
+ Decidim::Suomifi.metadata_collector_class.new(saml_attributes)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Suomifi
5
+ module Verification
6
+ class MetadataCollector
7
+ def initialize(saml_attributes)
8
+ @saml_attributes = saml_attributes
9
+ end
10
+
11
+ def metadata
12
+ hetu = Henkilotunnus::Hetu.new(
13
+ saml_attributes[:national_identification_number]
14
+ )
15
+ # In case the HETU was not sent by Suomi.fi, it will be empty and
16
+ # therefore invalid and will not have the gender information. With
17
+ # empty HETU, `Henkilotunnus::Hetu` would otherwise report "female" as
18
+ # the gender which would not be correct.
19
+ gender = nil
20
+ date_of_birth = nil
21
+
22
+ # Note that we cannot call hetu.valid? because it will also call
23
+ # `:valid_person_number?`. This checks that the HETU is in range
24
+ # 002-899 which are the actual HETU codes stored in the population
25
+ # register system. The numbers above 899 are temporary codes, e.g. in
26
+ # situations when a person does not yet have a HETU. Temporary codes
27
+ # may be returned by the Suomi.fi endpoint e.g. in the testing mode.
28
+ # Regarding the information needs here, it does not matter whether the
29
+ # HETU is temporary or permanent.
30
+ valid_hetu = hetu.send(:valid_format?) && hetu.send(:valid_checksum?)
31
+ if valid_hetu
32
+ gender = hetu.male? ? "m" : "f"
33
+ # `.to_s` returns an ISO 8601 formatted string (YYYY-MM-DD for dates)
34
+ date_of_birth = hetu.date_of_birth.to_s
35
+ elsif saml_attributes[:eidas_date_of_birth]
36
+ # xsd:date (YYYY-MM_DD)
37
+ date_of_birth = saml_attributes[:eidas_date_of_birth]
38
+ end
39
+
40
+ postal_code_permanent = true
41
+ postal_code = saml_attributes[:permanent_domestic_address_postal_code]
42
+ unless postal_code
43
+ postal_code_permanent = false
44
+ postal_code = saml_attributes[:temporary_domestic_address_postal_code]
45
+ end
46
+
47
+ first_name = saml_attributes[:first_names]
48
+ last_name = saml_attributes[:last_name]
49
+ given_name = saml_attributes[:given_name]
50
+
51
+ eidas = false
52
+ if saml_attributes[:eidas_person_identifier]
53
+ eidas = true
54
+ first_name = saml_attributes[:eidas_first_names]
55
+ last_name = saml_attributes[:eidas_family_name]
56
+ end
57
+
58
+ {
59
+ eidas: eidas,
60
+ gender: gender,
61
+ date_of_birth: date_of_birth,
62
+ pin_digest: person_identifier_digest,
63
+ # The first name will contain all first names of the person
64
+ first_name: first_name,
65
+ # The given name is the primary first name of the person, also known
66
+ # as "calling name" (kutsumanimi).
67
+ given_name: given_name,
68
+ last_name: last_name,
69
+ # The municipality number, see:
70
+ # http://tilastokeskus.fi/meta/luokitukset/kunta/001-2017/index.html
71
+ municipality: saml_attributes[:home_municipality_number],
72
+ municipality_name: saml_attributes[:home_municipality_name_fi],
73
+ postal_code: postal_code,
74
+ permanent_address: postal_code_permanent
75
+ }
76
+ end
77
+
78
+ # Digested format of the person's identifier unique to the person. The
79
+ # digested format is used because the undigested format may hold
80
+ # personal sensitive information about the user and may require special
81
+ # care regarding the privacy policy. These will still be unique hashes
82
+ # bound to the person's identification number.
83
+ def person_identifier_digest
84
+ @person_identifier_digest ||= begin
85
+ prefix = nil
86
+ pin = nil
87
+
88
+ if saml_attributes[:national_identification_number]
89
+ prefix = "FI"
90
+ pin = saml_attributes[:national_identification_number]
91
+ elsif saml_attributes[:eidas_person_identifier]
92
+ prefix = "EIDAS"
93
+ pin = saml_attributes[:eidas_person_identifier]
94
+ end
95
+
96
+ if prefix && pin
97
+ Digest::MD5.hexdigest(
98
+ "#{prefix}:#{pin}:#{Rails.application.secrets.secret_key_base}"
99
+ )
100
+ end
101
+ end
102
+ end
103
+
104
+ protected
105
+
106
+ attr_reader :saml_attributes
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Suomifi
5
+ VERSION = "0.18.0"
6
+ DECIDIM_VERSION = "~> 0.18.0"
7
+ end
8
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+
5
+ module Decidim
6
+ module Suomifi
7
+ module Generators
8
+ class InstallGenerator < Rails::Generators::Base
9
+ source_root File.expand_path("../../templates", __dir__)
10
+
11
+ desc "Creates a Devise initializer and copy locale files to your application."
12
+
13
+ class_option(
14
+ :dummy_cert,
15
+ desc: "Defines whether to create a dummy certificate for localhost.",
16
+ type: :boolean,
17
+ default: false
18
+ )
19
+
20
+ class_option(
21
+ :test_initializer,
22
+ desc: "Copies the test initializer instead of the actual one (for test dummy app).",
23
+ type: :boolean,
24
+ default: false,
25
+ hide: true
26
+ )
27
+
28
+ def copy_initializer
29
+ if options[:test_initializer]
30
+ copy_file "suomifi_initializer_test.rb", "config/initializers/suomifi.rb"
31
+ else
32
+ copy_file "suomifi_initializer.rb", "config/initializers/suomifi.rb"
33
+ end
34
+ end
35
+
36
+ def copy_dummy_certificate
37
+ if options[:dummy_cert]
38
+ empty_directory "config/cert"
39
+ copy_file "suomifi_localhost.crt", "config/cert/suomifi.crt"
40
+ copy_file "suomifi_localhost.key", "config/cert/suomifi.key"
41
+ end
42
+ end
43
+
44
+ def enable_authentication
45
+ secrets_path = Rails.application.root.join("config", "secrets.yml")
46
+ secrets = YAML.safe_load(File.read(secrets_path), [], [], true)
47
+
48
+ if secrets["default"]["omniauth"]["suomifi"]
49
+ say_status :identical, "config/secrets.yml", :blue
50
+ else
51
+ mod = SecretsModifier.new(secrets_path)
52
+ final = mod.modify
53
+
54
+ target_path = Rails.application.root.join("config", "secrets.yml")
55
+ File.open(target_path, "w") { |f| f.puts final }
56
+
57
+ say_status :insert, "config/secrets.yml", :green
58
+ end
59
+ end
60
+
61
+ class SecretsModifier
62
+ def initialize(filepath)
63
+ @filepath = filepath
64
+ end
65
+
66
+ def modify
67
+ self.inside_config = false
68
+ self.inside_omniauth = false
69
+ self.config_branch = nil
70
+ @final = ""
71
+
72
+ @empty_line_count = 0
73
+ File.readlines(filepath).each do |line|
74
+ if line =~ /^$/
75
+ @empty_line_count += 1
76
+ next
77
+ else
78
+ handle_line line
79
+ insert_empty_lines
80
+ end
81
+
82
+ @final += line
83
+ end
84
+ insert_empty_lines
85
+
86
+ @final
87
+ end
88
+
89
+ private
90
+
91
+ attr_accessor :filepath, :empty_line_count, :inside_config, :inside_omniauth, :config_branch
92
+
93
+ def handle_line(line)
94
+ if inside_config && line =~ /^ omniauth:/
95
+ self.inside_omniauth = true
96
+ elsif inside_omniauth && line =~ /^( )?[a-z]+/
97
+ inject_suomifi_config
98
+ self.inside_omniauth = false
99
+ end
100
+
101
+ return unless line =~ /^[a-z]+/
102
+
103
+ # A new root configuration block starts
104
+ self.inside_config = false
105
+ self.inside_omniauth = false
106
+
107
+ if line =~ /^default:/
108
+ self.inside_config = true
109
+ self.config_branch = :default
110
+ elsif line =~ /^development:/
111
+ self.inside_config = true
112
+ self.config_branch = :development
113
+ end
114
+ end
115
+
116
+ def insert_empty_lines
117
+ @final += "\n" * empty_line_count
118
+ @empty_line_count = 0
119
+ end
120
+
121
+ def inject_suomifi_config
122
+ @final += " suomifi:\n"
123
+ if config_branch == :development
124
+ @final += " enabled: true\n"
125
+ @final += " mode: test\n"
126
+ else
127
+ @final += " enabled: false\n"
128
+ end
129
+ @final += " icon: globe\n"
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ cert_path = Rails.application.root.join("config", "cert")
4
+
5
+ Decidim::Suomifi.configure do |config|
6
+ config.scope_of_data = :medium_extensive
7
+ # Define the service provider entity ID included in the Suomi.fi metadata:
8
+ # config.sp_entity_id = "https://www.example.org/users/auth/suomifi/metadata"
9
+ # Or define it in your application configuration and apply it here:
10
+ # config.sp_entity_id = Rails.application.config.suomifi_entity_id
11
+ config.certificate_file = "#{cert_path}/suomifi.crt"
12
+ config.private_key_file = "#{cert_path}/suomifi.key"
13
+ # Enable automatically assigned emails
14
+ config.auto_email_domain = "example.org"
15
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Decidim::Suomifi::Test::Runtime.initialize
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDeTCCAmGgAwIBAgIUP/YcljlSpKAPYLzhUXy7HpqBvvkwDQYJKoZIhvcNAQEL
3
+ BQAwTDELMAkGA1UEBhMCRkkxEDAOBgNVBAgMB1V1c2ltYWExFzAVBgNVBAoMDk1h
4
+ aW5pbyBUZWNoIE95MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTkwNzI0MTQ1MTUw
5
+ WhcNMjkwNzIxMTQ1MTUwWjBMMQswCQYDVQQGEwJGSTEQMA4GA1UECAwHVXVzaW1h
6
+ YTEXMBUGA1UECgwOTWFpbmlvIFRlY2ggT3kxEjAQBgNVBAMMCWxvY2FsaG9zdDCC
7
+ ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMNWfaZe5zwFCEqDBD2AEdFA
8
+ wdg0FV4N3OxtQrk9hgqbDpNSvWI6wIq4lIDIrlI4hM2VQzWtJRy4UcfecLnz5q1J
9
+ 7SZ/uzTKkcqbSvCVfMeh5Yr9kjT9FYA9m7lxuiA1/AnX6Ho+8Hm8k/ggpOPCvDs/
10
+ uO6e0SROqc0+eiy6It9YfZrrdU1YpOVkO0DNz6ndXMlFW1HZWaU/uSb0qKQoNlvD
11
+ OZgXX0zwHgGn++Q6cGilIHUm+4OG6miItyoR7jxwupwbklAyq3QD1vgViERdVz/L
12
+ qZyUK4+3QjJSY8iPvW87nram+Tn97qD9Tg4xrU9xclo1CsZAYrR1RYNurV0MN2UC
13
+ AwEAAaNTMFEwHQYDVR0OBBYEFMAzak2Fbdc2zH/c8bQTi8OarjqtMB8GA1UdIwQY
14
+ MBaAFMAzak2Fbdc2zH/c8bQTi8OarjqtMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
15
+ hvcNAQELBQADggEBALh7yn9oklviyBomSJJU8voS7wSeuVVNbCKkX7SeJvPpjcZA
16
+ S2B9QjRYYY1l7Cknwop6790fmHgDTpi4Wr+kirMv1wS+X8v5CQtVJ3uj1ZVfGrop
17
+ pjzJNmYkkrTKr9n8JP+qYJO1PGXLjlIMqQCcujdNXvMGqHpzZiLf4jn3vLEGlkN7
18
+ 8N96dlRYrWd7CVnEB+VuZFlDuXXcVjVvhNBy2+YJxOy2ketpiz2WM6afz0q5jiV8
19
+ EYgoBLpreJGtVGyIRNmMm41weandbReztyCIMzVZL/5GsgXHvsk1Z0JSQQMVgSl5
20
+ GDV2YgWcKHPCqLAfiRiNxMEijiNrM1dfzTzZzBQ=
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDDVn2mXuc8BQhK
3
+ gwQ9gBHRQMHYNBVeDdzsbUK5PYYKmw6TUr1iOsCKuJSAyK5SOITNlUM1rSUcuFHH
4
+ 3nC58+atSe0mf7s0ypHKm0rwlXzHoeWK/ZI0/RWAPZu5cbogNfwJ1+h6PvB5vJP4
5
+ IKTjwrw7P7juntEkTqnNPnosuiLfWH2a63VNWKTlZDtAzc+p3VzJRVtR2VmlP7km
6
+ 9KikKDZbwzmYF19M8B4Bp/vkOnBopSB1JvuDhupoiLcqEe48cLqcG5JQMqt0A9b4
7
+ FYhEXVc/y6mclCuPt0IyUmPIj71vO562pvk5/e6g/U4OMa1PcXJaNQrGQGK0dUWD
8
+ bq1dDDdlAgMBAAECggEBAKCKJv5jJRw47pV+lC+PYBVgaXAtbho8voM5UQs5Oz7g
9
+ LNx7tdZTfwcDqFknlc1RUiQ8Nl6ZDNVLzzq64F6Ty9RD27o2ZD+A9M1VUAPmeAUC
10
+ U8sll9Ig5ljdSWzhwRzUAW59mj1OGQmUKPBWs+3UkCsJtg23TR/P3tImNPcpi5uO
11
+ hhuRvMVK+6NjRsU/sCoYOMdBxWLhoAALmoQx1PwETS4KSDH78eFMdhoozgWHprDv
12
+ 9NrmoNRCz+YkAID5lW8u2PzM1kUTF54hP3qn5cBD/1OkOqTFy0c7ZznAX0eL2lea
13
+ Ayl7RjKittIjtePzxO5Qlq8CZbtVb8hrv9J5bOUBlUECgYEA/l3jfSz1TxJ/vYzz
14
+ ycjGWZOF6+B9dFmDfn1RWFfpmauA68Og38tc/IrfS/8X6qtG1Nt2rDKuH6fho2RA
15
+ ft6PQyFqxF/bd/N0WY9FI8wmrY6BwNSEYoXhw1ib8FjFPmZxFi9AYC0dU+fL9hUw
16
+ QReYpIwUYh69fDBEKoTHS5Pu470CgYEAxJeTCX+IUVq06fOpZ1o9OLrdMeFcVpjD
17
+ L0kClZ1Z6p1/Rd9RXBJ9FvUJClJnwH37EzVAzvITc40yx9EjmdqYW2Qw+agDpGMP
18
+ WpmIufuVoxGYBFMQAPJNztOXx8gkTDzymLXL37d2sZI8TbyPWWfkL+WtgJkpXDog
19
+ A04neavriMkCgYEAoD35f/QAnc2jl3/iXK4U9n1PEqeboN57TgYYZrULPnmif+P/
20
+ xrxQWfAKd8+9+2Hm/1U6T4Sl2N9j8BDJ6KLAUaQNpKRWmBxQodL11XVYsGFkMFwx
21
+ Afghn3SE2Ea0C3lxqG4f+fax0Rfnj6ENgxQgXxi4BpAjAsdNShPXkS8igWkCgYEA
22
+ gzgpDM3zT1ocJ4xcJoA1HQidXA3wdFzC62zwLK06tz8pFJpa0/oDRK+JuToHxpRQ
23
+ YiHJgFhUY2x72KPf/3HJADd/+SQMSk1UkkSo3nrvBklYDoriw7738HWLee49TCXi
24
+ R8wQqOLsdtoFJl4V0LdnuBC2HoAc+1JQy+P+tVfrfwECgYA4fBLCEA8I7A26NA03
25
+ K11RoLiwG+lH02kpFEXTka7x7yA24sivdZN0lJ2AI6iSWNygAFRmIgTiXJj628aS
26
+ oETUX+hlMJTirgpDSeWpMGaaexKoXrBQsp2JKmnNy6uRF0lTyZLphloPqFoCVdyp
27
+ Hy3GU3LWvG/TkY+yh3Uqn3OvVQ==
28
+ -----END PRIVATE KEY-----
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: decidim-suomifi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.18.0
5
+ platform: ruby
6
+ authors:
7
+ - Antti Hukkanen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: decidim-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.18.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.18.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: henkilotunnus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: omniauth-suomifi
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: decidim-dev
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.18.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.18.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: xmlenc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.1
83
+ description: Adds Suomi.fi authentication provider to Decidim.
84
+ email:
85
+ - antti.hukkanen@mainiotech.fi
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - LICENSE-AGPLv3.txt
91
+ - README.md
92
+ - Rakefile
93
+ - app/controllers/decidim/suomifi/omniauth_callbacks_controller.rb
94
+ - app/controllers/decidim/suomifi/verification/authorizations_controller.rb
95
+ - config/locales/en.yml
96
+ - config/locales/fi.yml
97
+ - config/locales/sv.yml
98
+ - lib/decidim/suomifi.rb
99
+ - lib/decidim/suomifi/engine.rb
100
+ - lib/decidim/suomifi/mail_interceptors.rb
101
+ - lib/decidim/suomifi/mail_interceptors/generated_recipients_interceptor.rb
102
+ - lib/decidim/suomifi/test/cert_store.rb
103
+ - lib/decidim/suomifi/test/runtime.rb
104
+ - lib/decidim/suomifi/verification.rb
105
+ - lib/decidim/suomifi/verification/engine.rb
106
+ - lib/decidim/suomifi/verification/manager.rb
107
+ - lib/decidim/suomifi/verification/metadata_collector.rb
108
+ - lib/decidim/suomifi/version.rb
109
+ - lib/generators/decidim/suomifi/install_generator.rb
110
+ - lib/generators/templates/suomifi_initializer.rb
111
+ - lib/generators/templates/suomifi_initializer_test.rb
112
+ - lib/generators/templates/suomifi_localhost.crt
113
+ - lib/generators/templates/suomifi_localhost.key
114
+ homepage: https://github.com/mainio/decidim-module-suomifi
115
+ licenses:
116
+ - AGPL-3.0
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.0.3
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Provides possibility to bind Suomi.fi authentication provider to Decidim.
137
+ test_files: []