decidim-suomifi 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/decidim/suomifi/omniauth_callbacks_controller.rb +29 -124
- data/app/controllers/decidim/suomifi/sessions_controller.rb +52 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/fi.yml +1 -0
- data/config/locales/sv.yml +1 -0
- data/lib/decidim/suomifi.rb +25 -1
- data/lib/decidim/suomifi/authentication.rb +4 -0
- data/lib/decidim/suomifi/authentication/authenticator.rb +178 -0
- data/lib/decidim/suomifi/authentication/errors.rb +21 -0
- data/lib/decidim/suomifi/engine.rb +36 -0
- data/lib/decidim/suomifi/version.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 150ac439de1d3aa6d6b1d4f751a2d9aaa42d71df7258e2ad1ce4ff17dda14908
|
|
4
|
+
data.tar.gz: d507607ae2555b4b22d264084b0e4ae5b2ea92cec8fd40d99a684649d1ecd914
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '060508a9c89d455df3abc8ae4c97d0d1fe4cf3602574209dd937f06675c007bdd6a67925c7082138d941e47c4f638bbbd9397d9ea7c1df54ab61337558c6a30e'
|
|
7
|
+
data.tar.gz: 1632a366514b05b264d90e0d3f47479d0bedd753127de042f654cf49af9e581b18422c2502998095bc90077a630ff7224b970d7b3dc30fb4ccb2d807d623699a
|
|
@@ -13,33 +13,20 @@ module Decidim
|
|
|
13
13
|
# This is called always after the user returns from the authentication
|
|
14
14
|
# flow from the Suomi.fi identity provider.
|
|
15
15
|
def suomifi
|
|
16
|
+
session["decidim-suomifi.signed_in"] = true
|
|
17
|
+
|
|
18
|
+
authenticator.validate!
|
|
19
|
+
|
|
16
20
|
if user_signed_in?
|
|
17
21
|
# The user is most likely returning from an authorization request
|
|
18
22
|
# because they are already signed in. In this case, add the
|
|
19
23
|
# authorization and redirect the user back to the authorizations view.
|
|
20
24
|
|
|
21
25
|
# Make sure the user has an identity created in order to aid future
|
|
22
|
-
# Suomi.fi sign ins.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
uid: user_identifier
|
|
27
|
-
)
|
|
28
|
-
unless identity
|
|
29
|
-
# Check that the identity is not already bound to another user.
|
|
30
|
-
id = Decidim::Identity.find_by(
|
|
31
|
-
organization: current_organization,
|
|
32
|
-
provider: oauth_data[:provider],
|
|
33
|
-
uid: user_identifier
|
|
34
|
-
)
|
|
35
|
-
return fail_authorize(:identity_bound_to_other_user) if id
|
|
36
|
-
|
|
37
|
-
current_user.identities.create!(
|
|
38
|
-
organization: current_organization,
|
|
39
|
-
provider: oauth_data[:provider],
|
|
40
|
-
uid: user_identifier
|
|
41
|
-
)
|
|
42
|
-
end
|
|
26
|
+
# Suomi.fi sign ins. In case this fails, it will raise a
|
|
27
|
+
# Decidim::Suomifi::Authentication::IdentityBoundToOtherUserError
|
|
28
|
+
# which is handled below.
|
|
29
|
+
authenticator.identify_user!(current_user)
|
|
43
30
|
|
|
44
31
|
# Add the authorization for the user
|
|
45
32
|
return fail_authorize unless authorize_user(current_user)
|
|
@@ -57,6 +44,10 @@ module Decidim
|
|
|
57
44
|
|
|
58
45
|
# Normal authentication request, proceed with Decidim's internal logic.
|
|
59
46
|
send(:create)
|
|
47
|
+
rescue Decidim::Suomifi::Authentication::ValidationError => e
|
|
48
|
+
fail_authorize(e.validation_key)
|
|
49
|
+
rescue Decidim::Suomifi::Authentication::IdentityBoundToOtherUserError
|
|
50
|
+
fail_authorize(:identity_bound_to_other_user)
|
|
60
51
|
end
|
|
61
52
|
|
|
62
53
|
def failure
|
|
@@ -132,31 +123,9 @@ module Decidim
|
|
|
132
123
|
private
|
|
133
124
|
|
|
134
125
|
def authorize_user(user)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
if authorization
|
|
140
|
-
return nil if authorization.user != user
|
|
141
|
-
else
|
|
142
|
-
authorization = Decidim::Authorization.find_or_initialize_by(
|
|
143
|
-
name: "suomifi_eid",
|
|
144
|
-
user: user
|
|
145
|
-
)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
authorization.attributes = {
|
|
149
|
-
unique_id: user_signature,
|
|
150
|
-
metadata: authorization_metadata
|
|
151
|
-
}
|
|
152
|
-
authorization.save!
|
|
153
|
-
|
|
154
|
-
# This will update the "granted_at" timestamp of the authorization which
|
|
155
|
-
# will postpone expiration on re-authorizations in case the
|
|
156
|
-
# authorization is set to expire (by default it will not expire).
|
|
157
|
-
authorization.grant!
|
|
158
|
-
|
|
159
|
-
authorization
|
|
126
|
+
authenticator.authorize_user!(user)
|
|
127
|
+
rescue Decidim::Suomifi::Authentication::AuthorizationBoundToOtherUserError
|
|
128
|
+
nil
|
|
160
129
|
end
|
|
161
130
|
|
|
162
131
|
def fail_authorize(failure_message_key = :already_authorized)
|
|
@@ -164,13 +133,15 @@ module Decidim
|
|
|
164
133
|
"failure.#{failure_message_key}",
|
|
165
134
|
scope: "decidim.suomifi.omniauth_callbacks"
|
|
166
135
|
)
|
|
167
|
-
redirect_to stored_location_for(resource || :user) || decidim.root_path
|
|
168
|
-
end
|
|
169
136
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
137
|
+
redirect_path = stored_location_for(resource || :user) || decidim.root_path
|
|
138
|
+
if session.delete("decidim-suomifi.signed_in")
|
|
139
|
+
params = "?RelayState=#{CGI.escape(redirect_path)}"
|
|
140
|
+
|
|
141
|
+
return redirect_to user_suomifi_omniauth_spslo_path + params
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
redirect_to redirect_path
|
|
174
145
|
end
|
|
175
146
|
|
|
176
147
|
# Needs to be specifically defined because the core engine routes are not
|
|
@@ -183,84 +154,18 @@ module Decidim
|
|
|
183
154
|
# Private: Create form params from omniauth hash
|
|
184
155
|
# Since we are using trusted omniauth data we are generating a valid signature.
|
|
185
156
|
def user_params_from_oauth_hash
|
|
186
|
-
|
|
187
|
-
return nil if saml_attributes.empty?
|
|
188
|
-
return nil if user_identifier.blank?
|
|
189
|
-
|
|
190
|
-
{
|
|
191
|
-
provider: oauth_data[:provider],
|
|
192
|
-
uid: user_identifier,
|
|
193
|
-
name: user_full_name,
|
|
194
|
-
# The nickname is automatically "parametrized" by Decidim core from
|
|
195
|
-
# the name string, i.e. it will be in correct format.
|
|
196
|
-
nickname: user_full_name,
|
|
197
|
-
oauth_signature: user_signature,
|
|
198
|
-
avatar_url: oauth_data[:info][:image],
|
|
199
|
-
raw_data: oauth_hash
|
|
200
|
-
}
|
|
157
|
+
authenticator.user_params_from_oauth_hash
|
|
201
158
|
end
|
|
202
159
|
|
|
203
|
-
def
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
first_name = begin
|
|
208
|
-
saml_attributes[:given_name] ||
|
|
209
|
-
saml_attributes[:first_names] ||
|
|
210
|
-
saml_attributes[:eidas_first_names]
|
|
211
|
-
end
|
|
212
|
-
last_name = begin
|
|
213
|
-
saml_attributes[:last_name] ||
|
|
214
|
-
saml_attributes[:eidas_family_name]
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
"#{first_name} #{last_name}"
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def user_signature
|
|
222
|
-
@user_signature ||= OmniauthRegistrationForm.create_signature(
|
|
223
|
-
oauth_data[:provider],
|
|
224
|
-
user_identifier
|
|
225
|
-
)
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
# See the omniauth-suomi gem's notes about the UID. It should be always
|
|
229
|
-
# unique per person as long as it can be determined from the user's data.
|
|
230
|
-
# This consists of one of the following in this order:
|
|
231
|
-
# - The person's electronic identifier (SATU ID, sähköinen asiointitunnus)
|
|
232
|
-
# - The person's personal identifier (HETU ID, henkilötunnus) in hashed
|
|
233
|
-
# format
|
|
234
|
-
# - The person's eIDAS personal identifier (eIDAS PID) in hashed format
|
|
235
|
-
# - The SAML NameID in the SAML response in case no unique personal data
|
|
236
|
-
# is available as defined above
|
|
237
|
-
def user_identifier
|
|
238
|
-
@user_identifier ||= oauth_data[:uid]
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def person_identifier_digest
|
|
242
|
-
metadata_collector.person_identifier_digest
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def metadata_collector
|
|
246
|
-
@metadata_collector ||= Decidim::Suomifi::Verification::Manager.metadata_collector_for(
|
|
247
|
-
saml_attributes
|
|
160
|
+
def authenticator
|
|
161
|
+
@authenticator ||= Decidim::Suomifi.authenticator_for(
|
|
162
|
+
current_organization,
|
|
163
|
+
oauth_hash
|
|
248
164
|
)
|
|
249
165
|
end
|
|
250
166
|
|
|
251
167
|
def verified_email
|
|
252
|
-
|
|
253
|
-
if saml_attributes[:email]
|
|
254
|
-
saml_attributes[:email]
|
|
255
|
-
elsif Decidim::Suomifi.auto_email_domain
|
|
256
|
-
domain = Decidim::Suomifi.auto_email_domain
|
|
257
|
-
"suomifi-#{person_identifier_digest}@#{domain}"
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
def saml_attributes
|
|
263
|
-
@saml_attributes ||= oauth_hash[:extra][:saml_attributes]
|
|
168
|
+
authenticator.verified_email
|
|
264
169
|
end
|
|
265
170
|
end
|
|
266
171
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Suomifi
|
|
5
|
+
class SessionsController < ::Decidim::Devise::SessionsController
|
|
6
|
+
def destroy
|
|
7
|
+
# In case the user is signed in through Suomi.fi, redirect them through
|
|
8
|
+
# the SPSLO flow.
|
|
9
|
+
if session.delete("decidim-suomifi.signed_in")
|
|
10
|
+
# These session variables get destroyed along with the user's active
|
|
11
|
+
# session. They are needed for the SLO request.
|
|
12
|
+
saml_uid = session["saml_uid"]
|
|
13
|
+
saml_session_index = session["saml_session_index"]
|
|
14
|
+
|
|
15
|
+
# End the local user session.
|
|
16
|
+
signed_out = (::Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
|
17
|
+
|
|
18
|
+
# Store the SAML parameters for the SLO request utilized by
|
|
19
|
+
# omniauth-saml. These are used to generate a valid SLO request.
|
|
20
|
+
session["saml_uid"] = saml_uid
|
|
21
|
+
session["saml_session_index"] = saml_session_index
|
|
22
|
+
|
|
23
|
+
# Generate the SLO redirect path and parameters.
|
|
24
|
+
relay = slo_callback_user_session_path
|
|
25
|
+
relay += "?success=1" if signed_out
|
|
26
|
+
params = "?RelayState=#{CGI.escape(relay)}"
|
|
27
|
+
|
|
28
|
+
return redirect_to user_suomifi_omniauth_spslo_path + params
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Otherwise, continue normally
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def slo
|
|
36
|
+
# This is handled already by omniauth
|
|
37
|
+
redirect_to decidim.root_path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def spslo
|
|
41
|
+
# This is handled already by omniauth
|
|
42
|
+
redirect_to decidim.root_path
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def slo_callback
|
|
46
|
+
set_flash_message! :notice, :signed_out if params[:success] == "1"
|
|
47
|
+
|
|
48
|
+
redirect_to after_sign_out_path_for(resource_name)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/config/locales/en.yml
CHANGED
|
@@ -11,6 +11,7 @@ en:
|
|
|
11
11
|
already_authorized: Another user has already authorized themselves with the same identity.
|
|
12
12
|
conditions: The authentication request was not handled within an allowed timeframe. Please try again.
|
|
13
13
|
identity_bound_to_other_user: Another user has already been identified using this identity. Please sign out and sign in again directly using Suomi.fi.
|
|
14
|
+
invalid_data: You cannot be authenticated through Suomi.fi.
|
|
14
15
|
session_expiration: Authentication session expired. Please try again.
|
|
15
16
|
success_status: Authentication failed or cancelled. Please try again.
|
|
16
17
|
verification:
|
data/config/locales/fi.yml
CHANGED
|
@@ -10,6 +10,7 @@ fi:
|
|
|
10
10
|
already_authorized: Toinen käyttäjä on tunnistanut itsensä jo samalla henkilöllisyydellä.
|
|
11
11
|
conditions: Tunnistuspyyntöä ei käsitelty sallitun aikarajan sisällä. Yritä uudestaan.
|
|
12
12
|
identity_bound_to_other_user: Toinen käyttäjä on jo tunnistanut itsensä tällä henkilöllisyydellä. Kirjaudu ulos ja kirjaudu uudestaan sisään käyttäen suoraan Suomi.fi-tunnistusta.
|
|
13
|
+
invalid_data: Sinua ei voida tunnistaa Suomi.fi-palvelun avulla.
|
|
13
14
|
session_expiration: Tunnistusistunto vanhentui. Yritä uudestaan.
|
|
14
15
|
success_status: Tunnistus epäonnistui tai peruutettiin. Yritä uudestaan.
|
|
15
16
|
verification:
|
data/config/locales/sv.yml
CHANGED
|
@@ -10,6 +10,7 @@ sv:
|
|
|
10
10
|
already_authorized: En annan användare har redan godkänt sig med samma identitet.
|
|
11
11
|
conditions: Autentiseringsbegäran hanterades inte inom en tillåten tidsram. Var god försök igen.
|
|
12
12
|
identity_bound_to_other_user: En annan användare har redan identifierats med denna identitet. Logga ut och logga in igen direkt med Suomi.fi.
|
|
13
|
+
invalid_data: Du kan inte verifiera dig genom Suomi.fi.
|
|
13
14
|
session_expiration: Autentiseringssessionen har gått ut. Var god försök igen.
|
|
14
15
|
success_status: Autentiseringen misslyckades eller avbröts. Var god försök igen.
|
|
15
16
|
verification:
|
data/lib/decidim/suomifi.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "henkilotunnus"
|
|
|
6
6
|
|
|
7
7
|
require_relative "suomifi/version"
|
|
8
8
|
require_relative "suomifi/engine"
|
|
9
|
+
require_relative "suomifi/authentication"
|
|
9
10
|
require_relative "suomifi/verification"
|
|
10
11
|
require_relative "suomifi/mail_interceptors"
|
|
11
12
|
|
|
@@ -46,6 +47,18 @@ module Decidim
|
|
|
46
47
|
# The private key file for the application
|
|
47
48
|
config_accessor :private_key_file
|
|
48
49
|
|
|
50
|
+
# Defines how the session gets cleared when the OmniAuth strategy logs the
|
|
51
|
+
# user out. This has been customized to preserve the flash messages in the
|
|
52
|
+
# session after the session is destroyed.
|
|
53
|
+
config_accessor :idp_slo_session_destroy do
|
|
54
|
+
proc do |_env, session|
|
|
55
|
+
flash = session["flash"]
|
|
56
|
+
result = session.clear
|
|
57
|
+
session["flash"] = flash if flash
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
49
62
|
# Extra configuration for the omniauth strategy
|
|
50
63
|
config_accessor :extra do
|
|
51
64
|
{}
|
|
@@ -62,6 +75,12 @@ module Decidim
|
|
|
62
75
|
end
|
|
63
76
|
end
|
|
64
77
|
|
|
78
|
+
# Allows customizing parts of the authentication flow such as validating
|
|
79
|
+
# the authorization data before allowing the user to be authenticated.
|
|
80
|
+
config_accessor :authenticator_class do
|
|
81
|
+
Decidim::Suomifi::Authentication::Authenticator
|
|
82
|
+
end
|
|
83
|
+
|
|
65
84
|
# Allows customizing how the authorization metadata gets collected from
|
|
66
85
|
# the SAML attributes passed from the authorization endpoint.
|
|
67
86
|
config_accessor :metadata_collector_class do
|
|
@@ -77,6 +96,10 @@ module Decidim
|
|
|
77
96
|
super
|
|
78
97
|
end
|
|
79
98
|
|
|
99
|
+
def self.authenticator_for(organization, oauth_hash)
|
|
100
|
+
authenticator_class.new(organization, oauth_hash)
|
|
101
|
+
end
|
|
102
|
+
|
|
80
103
|
def self.mode
|
|
81
104
|
return config.mode if config.mode
|
|
82
105
|
return :production unless Rails.application.secrets.omniauth
|
|
@@ -111,7 +134,8 @@ module Decidim
|
|
|
111
134
|
scope_of_data: scope_of_data,
|
|
112
135
|
sp_entity_id: sp_entity_id,
|
|
113
136
|
certificate: certificate,
|
|
114
|
-
private_key: private_key
|
|
137
|
+
private_key: private_key,
|
|
138
|
+
idp_slo_session_destroy: idp_slo_session_destroy
|
|
115
139
|
}
|
|
116
140
|
settings.merge!(config.extra) if config.extra.is_a?(Hash)
|
|
117
141
|
settings
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Suomifi
|
|
5
|
+
module Authentication
|
|
6
|
+
class Authenticator
|
|
7
|
+
include ActiveModel::Validations
|
|
8
|
+
|
|
9
|
+
def initialize(organization, oauth_hash)
|
|
10
|
+
@organization = organization
|
|
11
|
+
@oauth_hash = oauth_hash
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def verified_email
|
|
15
|
+
@verified_email ||= begin
|
|
16
|
+
if saml_attributes[:email]
|
|
17
|
+
saml_attributes[:email]
|
|
18
|
+
elsif Decidim::Suomifi.auto_email_domain
|
|
19
|
+
domain = Decidim::Suomifi.auto_email_domain
|
|
20
|
+
"suomifi-#{person_identifier_digest}@#{domain}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Private: Create form params from omniauth hash
|
|
26
|
+
# Since we are using trusted omniauth data we are generating a valid signature.
|
|
27
|
+
def user_params_from_oauth_hash
|
|
28
|
+
return nil if oauth_data.empty?
|
|
29
|
+
return nil if saml_attributes.empty?
|
|
30
|
+
return nil if user_identifier.blank?
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
provider: oauth_data[:provider],
|
|
34
|
+
uid: user_identifier,
|
|
35
|
+
name: user_full_name,
|
|
36
|
+
# The nickname is automatically "parametrized" by Decidim core from
|
|
37
|
+
# the name string, i.e. it will be in correct format.
|
|
38
|
+
nickname: user_full_name,
|
|
39
|
+
oauth_signature: user_signature,
|
|
40
|
+
avatar_url: oauth_data[:info][:image],
|
|
41
|
+
raw_data: oauth_hash
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def validate!
|
|
46
|
+
raise ValidationError, "No SAML data provided" if saml_attributes.blank?
|
|
47
|
+
|
|
48
|
+
data_blank = saml_attributes.all? { |_k, val| val.blank? }
|
|
49
|
+
raise ValidationError, "Invalid SAML data" if data_blank
|
|
50
|
+
raise ValidationError, "Invalid person dentifier" if person_identifier_digest.blank?
|
|
51
|
+
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def identify_user!(user)
|
|
56
|
+
identity = user.identities.find_by(
|
|
57
|
+
organization: organization,
|
|
58
|
+
provider: oauth_data[:provider],
|
|
59
|
+
uid: user_identifier
|
|
60
|
+
)
|
|
61
|
+
return identity if identity
|
|
62
|
+
|
|
63
|
+
# Check that the identity is not already bound to another user.
|
|
64
|
+
id = Decidim::Identity.find_by(
|
|
65
|
+
organization: organization,
|
|
66
|
+
provider: oauth_data[:provider],
|
|
67
|
+
uid: user_identifier
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
raise IdentityBoundToOtherUserError if id
|
|
71
|
+
|
|
72
|
+
user.identities.create!(
|
|
73
|
+
organization: organization,
|
|
74
|
+
provider: oauth_data[:provider],
|
|
75
|
+
uid: user_identifier
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def authorize_user!(user)
|
|
80
|
+
authorization = Decidim::Authorization.find_by(
|
|
81
|
+
name: "suomifi_eid",
|
|
82
|
+
unique_id: user_signature
|
|
83
|
+
)
|
|
84
|
+
if authorization
|
|
85
|
+
raise AuthorizationBoundToOtherUserError if authorization.user != user
|
|
86
|
+
else
|
|
87
|
+
authorization = Decidim::Authorization.find_or_initialize_by(
|
|
88
|
+
name: "suomifi_eid",
|
|
89
|
+
user: user
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
authorization.attributes = {
|
|
94
|
+
unique_id: user_signature,
|
|
95
|
+
metadata: authorization_metadata
|
|
96
|
+
}
|
|
97
|
+
authorization.save!
|
|
98
|
+
|
|
99
|
+
# This will update the "granted_at" timestamp of the authorization
|
|
100
|
+
# which will postpone expiration on re-authorizations in case the
|
|
101
|
+
# authorization is set to expire (by default it will not expire).
|
|
102
|
+
authorization.grant!
|
|
103
|
+
|
|
104
|
+
authorization
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
protected
|
|
108
|
+
|
|
109
|
+
attr_reader :organization, :oauth_hash
|
|
110
|
+
|
|
111
|
+
def oauth_data
|
|
112
|
+
@oauth_data ||= oauth_hash.slice(:provider, :uid, :info)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def saml_attributes
|
|
116
|
+
@saml_attributes ||= oauth_hash[:extra][:saml_attributes]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# See the omniauth-suomi gem's notes about the UID. It should be always
|
|
120
|
+
# unique per person as long as it can be determined from the user's data.
|
|
121
|
+
# This consists of one of the following in this order:
|
|
122
|
+
# - The person's electronic identifier (SATU ID, sähköinen asiointitunnus)
|
|
123
|
+
# - The person's personal identifier (HETU ID, henkilötunnus) in hashed
|
|
124
|
+
# format
|
|
125
|
+
# - The person's eIDAS personal identifier (eIDAS PID) in hashed format
|
|
126
|
+
# - The SAML NameID in the SAML response in case no unique personal data
|
|
127
|
+
# is available as defined above
|
|
128
|
+
def user_identifier
|
|
129
|
+
@user_identifier ||= oauth_data[:uid]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Create a unique signature for the user that will be used for the
|
|
133
|
+
# granted authorization.
|
|
134
|
+
def user_signature
|
|
135
|
+
@user_signature ||= ::Decidim::OmniauthRegistrationForm.create_signature(
|
|
136
|
+
oauth_data[:provider],
|
|
137
|
+
user_identifier
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def user_full_name
|
|
142
|
+
return oauth_data[:info][:name] if oauth_data[:info][:name]
|
|
143
|
+
|
|
144
|
+
@user_full_name ||= begin
|
|
145
|
+
first_name = begin
|
|
146
|
+
saml_attributes[:given_name] ||
|
|
147
|
+
saml_attributes[:first_names] ||
|
|
148
|
+
saml_attributes[:eidas_first_names]
|
|
149
|
+
end
|
|
150
|
+
last_name = begin
|
|
151
|
+
saml_attributes[:last_name] ||
|
|
152
|
+
saml_attributes[:eidas_family_name]
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
"#{first_name} #{last_name}"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def metadata_collector
|
|
160
|
+
@metadata_collector ||= ::Decidim::Suomifi::Verification::Manager.metadata_collector_for(
|
|
161
|
+
saml_attributes
|
|
162
|
+
)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Data that is stored against the authorization "permanently" (i.e. as
|
|
166
|
+
# long as the authorization is valid).
|
|
167
|
+
def authorization_metadata
|
|
168
|
+
metadata_collector.metadata
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# The digest that is created from the person identifier.
|
|
172
|
+
def person_identifier_digest
|
|
173
|
+
metadata_collector.person_identifier_digest
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Suomifi
|
|
5
|
+
module Authentication
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
class AuthorizationBoundToOtherUserError < Error; end
|
|
9
|
+
class IdentityBoundToOtherUserError < Error; end
|
|
10
|
+
|
|
11
|
+
class ValidationError < Error
|
|
12
|
+
attr_reader :validation_key
|
|
13
|
+
|
|
14
|
+
def initialize(msg = nil, validation_key = :invalid_data)
|
|
15
|
+
@validation_key = validation_key
|
|
16
|
+
super(msg)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -25,6 +25,42 @@ module Decidim
|
|
|
25
25
|
as: "user_suomifi_omniauth_callback",
|
|
26
26
|
via: [:get, :post]
|
|
27
27
|
)
|
|
28
|
+
|
|
29
|
+
# Add the SLO and SPSLO paths to be able to pass these requests to
|
|
30
|
+
# OmniAuth.
|
|
31
|
+
match(
|
|
32
|
+
"/users/auth/suomifi/slo",
|
|
33
|
+
to: "sessions#slo",
|
|
34
|
+
as: "user_suomifi_omniauth_slo",
|
|
35
|
+
via: [:get, :post]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
match(
|
|
39
|
+
"/users/auth/suomifi/spslo",
|
|
40
|
+
to: "sessions#spslo",
|
|
41
|
+
as: "user_suomifi_omniauth_spslo",
|
|
42
|
+
via: [:get, :post]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Manually map the sign out path in order to control the sign out
|
|
46
|
+
# flow through OmniAuth when the user signs out from the service.
|
|
47
|
+
# In these cases, the user needs to be also signed out from Suomi.fi
|
|
48
|
+
# which is handled by the OmniAuth strategy.
|
|
49
|
+
match(
|
|
50
|
+
"/users/sign_out",
|
|
51
|
+
to: "sessions#destroy",
|
|
52
|
+
as: "destroy_user_session",
|
|
53
|
+
via: [:delete, :post]
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# This is the callback route after a returning from a successful sign
|
|
57
|
+
# out request through OmniAuth.
|
|
58
|
+
match(
|
|
59
|
+
"/users/slo_callback",
|
|
60
|
+
to: "sessions#slo_callback",
|
|
61
|
+
as: "slo_callback_user_session",
|
|
62
|
+
via: [:get]
|
|
63
|
+
)
|
|
28
64
|
end
|
|
29
65
|
end
|
|
30
66
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: decidim-suomifi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.18.
|
|
4
|
+
version: 0.18.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Antti Hukkanen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-10-
|
|
11
|
+
date: 2019-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: decidim-core
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: 0.3.0
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: 0.3.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: decidim-dev
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -91,11 +91,15 @@ files:
|
|
|
91
91
|
- README.md
|
|
92
92
|
- Rakefile
|
|
93
93
|
- app/controllers/decidim/suomifi/omniauth_callbacks_controller.rb
|
|
94
|
+
- app/controllers/decidim/suomifi/sessions_controller.rb
|
|
94
95
|
- app/controllers/decidim/suomifi/verification/authorizations_controller.rb
|
|
95
96
|
- config/locales/en.yml
|
|
96
97
|
- config/locales/fi.yml
|
|
97
98
|
- config/locales/sv.yml
|
|
98
99
|
- lib/decidim/suomifi.rb
|
|
100
|
+
- lib/decidim/suomifi/authentication.rb
|
|
101
|
+
- lib/decidim/suomifi/authentication/authenticator.rb
|
|
102
|
+
- lib/decidim/suomifi/authentication/errors.rb
|
|
99
103
|
- lib/decidim/suomifi/engine.rb
|
|
100
104
|
- lib/decidim/suomifi/mail_interceptors.rb
|
|
101
105
|
- lib/decidim/suomifi/mail_interceptors/generated_recipients_interceptor.rb
|