omniauth-suomifi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,608 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth-saml'
4
+
5
+ module OmniAuth
6
+ module Strategies
7
+ class Suomifi < SAML
8
+ # Mode:
9
+ # :production - Suomi.fi production environment
10
+ # :test - Suomi.fi test environment
11
+ option :mode, :production
12
+
13
+ # The certificate file to define the certificate.
14
+ option :certificate_file, nil
15
+
16
+ # The private key file to define the private key.
17
+ option :private_key_file, nil
18
+
19
+ # The request attributes for Suomi.fi
20
+ option :possible_request_attributes, [
21
+ ##############################
22
+ ### Finnish authentication ###
23
+ ##############################
24
+ # Electronic identification number
25
+ # Sähköinen asiointitunnus
26
+ {
27
+ name: 'urn:oid:1.2.246.22',
28
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
29
+ friendly_name: 'electronicIdentificationNumber'
30
+ },
31
+ # National identification number
32
+ # Henkilötunnus
33
+ {
34
+ name: 'urn:oid:1.2.246.21',
35
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
36
+ friendly_name: 'nationalIdentificationNumber'
37
+ },
38
+ # Katso-ID
39
+ {
40
+ name: 'urn:oid:1.2.246.517.3003.113.4',
41
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
42
+ friendly_name: 'kid'
43
+ },
44
+ # Foreign person identifier
45
+ # Ulkomaisen henkilön tunniste
46
+ {
47
+ name: 'urn:oid:1.2.246.517.3002.111.17',
48
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
49
+ friendly_name: 'foreignpersonIdentifier'
50
+ },
51
+ # Email address
52
+ # Sähköpostiosoite
53
+ {
54
+ name: 'urn:oid:0.9.2342.19200300.100.1.3',
55
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
56
+ friendly_name: 'mail'
57
+ },
58
+ # Name, common name (full name = family name + all first names)
59
+ # Nimi, common name (koko nimi = sukunimi + kaikki etunimet)
60
+ {
61
+ name: 'urn:oid:2.5.4.3',
62
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
63
+ friendly_name: 'cn'
64
+ },
65
+ # Full name (calling name + last name)
66
+ # Koko nimi (kutsumanimi + sukunimi)
67
+ {
68
+ name: 'urn:oid:2.16.840.1.113730.3.1.241',
69
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
70
+ friendly_name: 'displayName'
71
+ },
72
+ # First names
73
+ # Etunimet
74
+ # NOTE: Also available in the eIDAS attributes
75
+ {
76
+ name: 'http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName',
77
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
78
+ friendly_name: 'FirstName'
79
+ },
80
+ # Given name
81
+ # Kutsumanimi
82
+ {
83
+ name: 'urn:oid:2.5.4.42',
84
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
85
+ friendly_name: 'givenName'
86
+ },
87
+ # Last name
88
+ # Sukunimi
89
+ {
90
+ name: 'urn:oid:2.5.4.4',
91
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
92
+ friendly_name: 'sn'
93
+ },
94
+ # Home municipality number
95
+ # Kotikunnan numero
96
+ # Defined at:
97
+ # http://tilastokeskus.fi/meta/luokitukset/kunta/001-2017/index.html
98
+ # http://tilastokeskus.fi/meta/luokitukset/kunta/001-2017/index_en.html
99
+ {
100
+ name: 'urn:oid:1.2.246.517.2002.2.18',
101
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
102
+ friendly_name: 'KotikuntaKuntanumero'
103
+ },
104
+ # Home municipality in Finnish
105
+ # Kotikunta suomeksi
106
+ {
107
+ name: 'urn:oid:1.2.246.517.2002.2.19',
108
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
109
+ friendly_name: 'KotikuntaKuntaS'
110
+ },
111
+ # Home municipality in Swedish
112
+ # Kotikunta ruotsiksi
113
+ {
114
+ name: 'urn:oid:1.2.246.517.2002.2.20',
115
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
116
+ friendly_name: 'KotikuntaKuntaR'
117
+ },
118
+ # Permanent domestic postal address, street address in Finnish
119
+ # Vakinainen kotimainen lähiosoite, katuosoite suomeksi
120
+ {
121
+ name: 'urn:oid:1.2.246.517.2002.2.4',
122
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
123
+ friendly_name: 'VakinainenKotimainenLahiosoiteS'
124
+ },
125
+ # Permanent domestic postal address, street address in Swedish
126
+ # Vakinainen kotimainen lähiosoite, katuosoite ruotsiksi
127
+ {
128
+ name: 'urn:oid:1.2.246.517.2002.2.5',
129
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
130
+ friendly_name: 'VakinainenKotimainenLahiosoiteR'
131
+ },
132
+ # Permanent domestic postal address, postal code
133
+ # Vakinainen kotimainen lähiosoite, postinumero
134
+ {
135
+ name: 'urn:oid:1.2.246.517.2002.2.6',
136
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
137
+ friendly_name: 'VakinainenKotimainenLahiosoitePostinumero'
138
+ },
139
+ # Permanent domestic postal address, municipality name (locality) in Finnish
140
+ # Vakinainen kotimainen lähiosoite, postitoimipaikka suomeksi
141
+ {
142
+ name: 'urn:oid:1.2.246.517.2002.2.7',
143
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
144
+ friendly_name: 'VakinainenKotimainenLahiosoitePostitoimipaikkaS'
145
+ },
146
+ # Permanent domestic postal address, municipality name (locality) in Swedish
147
+ # Vakinainen kotimainen lähiosoite, postitoimipaikka ruotsiksi
148
+ {
149
+ name: 'urn:oid:1.2.246.517.2002.2.8',
150
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
151
+ friendly_name: 'VakinainenKotimainenLahiosoitePostitoimipaikkaR'
152
+ },
153
+ # Permanent foreign postal address, street address
154
+ # Vakinainen ulkomainen lähiosoite, katuosoite
155
+ {
156
+ name: 'urn:oid:1.2.246.517.2002.2.11',
157
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
158
+ friendly_name: 'VakinainenUlkomainenLahiosoite'
159
+ },
160
+ # Permanent foreign postal address, municipality (locality) and state in Finnish
161
+ # Vakinainen ulkomainen lähiosoite, paikkakunta ja valtio suomeksi
162
+ {
163
+ name: 'urn:oid:1.2.246.517.2002.2.12',
164
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
165
+ friendly_name: 'VakinainenUlkomainenLahiosoitePaikkakuntaJaValtioS'
166
+ },
167
+ # Permanent foreign postal address, municipality (locality) and state in Swedish
168
+ # Vakinainen ulkomainen lähiosoite, paikkakunta ja valtio ruotsiksi
169
+ {
170
+ name: 'urn:oid:1.2.246.517.2002.2.13',
171
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
172
+ friendly_name: 'VakinainenUlkomainenLahiosoitePaikkakuntaJaValtioR'
173
+ },
174
+ # Permanent foreign postal address, municipality (locality) and state in plain text
175
+ # Vakinainen ulkomainen lähiosoite, paikkakunta ja valtio selväkielinen
176
+ # In case the foreign state name is not in the ISO3166 standard, it will
177
+ # be defined here in plain text.
178
+ {
179
+ name: 'urn:oid:1.2.246.517.2002.2.14',
180
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
181
+ friendly_name: 'VakinainenUlkomainenLahiosoitePaikkakuntaJaValtioSelvakielinen'
182
+ },
183
+ # Permanent foreign address state code
184
+ # Vakinaisen ulkomaisen osoitteen valtiokoodi
185
+ # In case the state is defined in the ISO3166 standard.
186
+ {
187
+ name: 'urn:oid:1.2.246.517.2002.2.15',
188
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
189
+ friendly_name: 'VakinainenUlkomainenLahiosoiteValtiokoodi'
190
+ },
191
+ # Temporary domestic postal address, street address in Finnish
192
+ # Tilapäinen kotimainen lähiosoite, katuosoite suomeksi
193
+ {
194
+ name: 'urn:oid:1.2.246.517.2002.2.31',
195
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
196
+ friendly_name: 'TilapainenKotimainenLahiosoiteS'
197
+ },
198
+ # Temporary domestic postal address, street address in Swedish
199
+ # Tilapäinen kotimainen lähiosoite, katuosoite ruotsiksi
200
+ {
201
+ name: 'urn:oid:1.2.246.517.2002.2.32',
202
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
203
+ friendly_name: 'TilapainenKotimainenLahiosoiteR'
204
+ },
205
+ # Temporary domestic postal address, postal code
206
+ # Tilapäinen kotimainen lähiosoite, postinumero
207
+ {
208
+ name: 'urn:oid:1.2.246.517.2002.2.33',
209
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
210
+ friendly_name: 'TilapainenKotimainenLahiosoitePostinumero'
211
+ },
212
+ # Temporary domestic postal address, municipality name (locality) in Finnish
213
+ # Tilapäinen kotimainen lähiosoite, postitoimipaikka suomeksi
214
+ {
215
+ name: 'urn:oid:1.2.246.517.2002.2.34',
216
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
217
+ friendly_name: 'TilapainenKotimainenLahiosoitePostitoimipaikkaS'
218
+ },
219
+ # Temporary domestic postal address, municipality name (locality) in Swedish
220
+ # Tilapäinen kotimainen lähiosoite, postitoimipaikka ruotsiksi
221
+ {
222
+ name: 'urn:oid:1.2.246.517.2002.2.35',
223
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
224
+ friendly_name: 'TilapainenKotimainenLahiosoitePostitoimipaikkaR'
225
+ },
226
+ # Finnish citizenship
227
+ # Suomen kansalaisuus
228
+ # In case the person is a Finnish citizen, the value of this will be
229
+ # '1'. Note that in order to get this information, the scope of the
230
+ # fetched data needs to be the 'extensive personal data'.
231
+ {
232
+ name: 'urn:oid:1.2.246.517.2002.2.26',
233
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
234
+ friendly_name: 'SuomenKansalaisuusTietokoodi'
235
+ },
236
+ # Information security denial
237
+ # Turvakielto
238
+ # In case the citizen has the security denial enabled, address
239
+ # information will not be sent during the authentication request.
240
+ # In this case, the value of this attribute is '1'.
241
+ {
242
+ name: 'urn:oid:1.2.246.517.2002.2.27',
243
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
244
+ friendly_name: 'TurvakieltoTieto'
245
+ },
246
+ #############
247
+ ### eIDAS ###
248
+ #############
249
+ # NOTE:
250
+ # The eIDAS attributes won't be sent over when the user is
251
+ # authenticating using a Finnish authentication method.
252
+ #
253
+ # eIDAS personal identifier (PID)
254
+ # eIDAS-asetuksen mukainen yksilöivä tunniste (PID)
255
+ #
256
+ # The format depends the issuing country and the number may be
257
+ # e.g. attached to the identity card and change in case the card
258
+ # is changed. The identifier is unique per person, so no two persons can
259
+ # hold the same identifier.
260
+ {
261
+ name: 'http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier',
262
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
263
+ friendly_name: 'PersonIdentifier'
264
+ },
265
+ # Last name
266
+ # Sukunimi
267
+ {
268
+ name: 'http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName',
269
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
270
+ friendly_name: 'FamilyName'
271
+ },
272
+ # Date of birth
273
+ # Syntymäaika
274
+ {
275
+ name: 'http://eidas.europa.eu/attributes/naturalperson/DateOfBirth',
276
+ name_format: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
277
+ friendly_name: 'DateOfBirth'
278
+ }
279
+ ]
280
+
281
+ # Maps the SAML attributes to OmniAuth info schema:
282
+ # https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later
283
+ option(
284
+ :attribute_statements,
285
+ # Display name
286
+ name: ['urn:oid:2.16.840.1.113730.3.1.241'],
287
+ email: ['urn:oid:0.9.2342.19200300.100.1.3'],
288
+ # Given name
289
+ first_name: ['urn:oid:2.5.4.42'],
290
+ last_name: ['urn:oid:2.5.4.4'],
291
+ # Permanent domestic address city name in Finnish
292
+ location: ['urn:oid:1.2.246.517.2002.2.7']
293
+ )
294
+
295
+ option(
296
+ :security_settings,
297
+ authn_requests_signed: true,
298
+ logout_requests_signed: true,
299
+ logout_responses_signed: true,
300
+ want_assertions_signed: true,
301
+ digest_method: XMLSecurity::Document::SHA256,
302
+ signature_method: XMLSecurity::Document::RSA_SHA256
303
+ )
304
+
305
+ # The attribute key maps to the SAML URIs so that we have more descriptive
306
+ # attribute keys available for use. These will be mapped to the OmniAuth
307
+ # `extra` information hash under the `:saml_attributes` key.
308
+ option(
309
+ :saml_attributes_map,
310
+ electronic_identification_number: ['urn:oid:1.2.246.22'],
311
+ national_identification_number: ['urn:oid:1.2.246.21'],
312
+ katso_id: ['urn:oid:1.2.246.517.3003.113.4'],
313
+ foreign_person_identifier: ['urn:oid:1.2.246.517.3002.111.17'],
314
+ email: ['urn:oid:0.9.2342.19200300.100.1.3'],
315
+ common_name: ['urn:oid:2.5.4.3'],
316
+ display_name: ['urn:oid:2.16.840.1.113730.3.1.241'],
317
+ first_names: ['http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName'],
318
+ given_name: ['urn:oid:2.5.4.42'],
319
+ last_name: ['urn:oid:2.5.4.4'],
320
+ home_municipality_number: ['urn:oid:1.2.246.517.2002.2.18'],
321
+ home_municipality_name_fi: ['urn:oid:1.2.246.517.2002.2.19'],
322
+ home_municipality_name_sv: ['urn:oid:1.2.246.517.2002.2.20'],
323
+ permanent_domestic_address_street_fi: ['urn:oid:1.2.246.517.2002.2.4'],
324
+ permanent_domestic_address_street_sv: ['urn:oid:1.2.246.517.2002.2.5'],
325
+ permanent_domestic_address_postal_code: ['urn:oid:1.2.246.517.2002.2.6'],
326
+ permanent_domestic_address_locality_fi: ['urn:oid:1.2.246.517.2002.2.7'],
327
+ permanent_domestic_address_locality_sv: ['urn:oid:1.2.246.517.2002.2.8'],
328
+ permanent_foreign_address_street: ['urn:oid:1.2.246.517.2002.2.11'],
329
+ permanent_foreign_address_locality_state_fi: ['urn:oid:1.2.246.517.2002.2.12'],
330
+ permanent_foreign_address_locality_state_sv: ['urn:oid:1.2.246.517.2002.2.13'],
331
+ permanent_foreign_address_locality_state_plain: ['urn:oid:1.2.246.517.2002.2.14'],
332
+ permanent_foreign_address_state_code: ['urn:oid:1.2.246.517.2002.2.15'],
333
+ temporary_domestic_address_street_fi: ['urn:oid:1.2.246.517.2002.2.31'],
334
+ temporary_domestic_address_street_sv: ['urn:oid:1.2.246.517.2002.2.32'],
335
+ temporary_domestic_address_postal_code: ['urn:oid:1.2.246.517.2002.2.33'],
336
+ temporary_domestic_address_locality_fi: ['urn:oid:1.2.246.517.2002.2.34'],
337
+ temporary_domestic_address_locality_sv: ['urn:oid:1.2.246.517.2002.2.35'],
338
+ finnish_citizenship: ['urn:oid:1.2.246.517.2002.2.26'],
339
+ information_security_denial: ['urn:oid:1.2.246.517.2002.2.27'],
340
+ eidas_person_identifier: ['http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier'],
341
+ eidas_first_names: ['http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName'],
342
+ eidas_family_name: ['http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName'],
343
+ eidas_date_of_birth: ['http://eidas.europa.eu/attributes/naturalperson/DateOfBirth']
344
+ )
345
+
346
+ # Defines the scope of data, i.e. which attributes to fetch from the
347
+ # Suomi.fi endpoint. Possible values are:
348
+ # - :limited
349
+ # - :medium_extensive
350
+ # - :extensive
351
+ #
352
+ # Please refer to the documentation for more information.
353
+ option :scope_of_data, :medium_extensive
354
+
355
+ # Defines the attribute names for each scope.
356
+ option(
357
+ :scoped_attributes,
358
+ limited: %w[
359
+ urn:oid:1.2.246.22
360
+ urn:oid:1.2.246.21
361
+ urn:oid:2.5.4.3
362
+ urn:oid:2.16.840.1.113730.3.1.241
363
+ urn:oid:2.5.4.42
364
+ urn:oid:2.5.4.4
365
+ urn:oid:1.2.246.517.3003.113.4
366
+ urn:oid:1.2.246.517.3002.111.17
367
+ http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName
368
+ http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier
369
+ http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName
370
+ http://eidas.europa.eu/attributes/naturalperson/DateOfBirth
371
+ ],
372
+ medium_extensive: %w[
373
+ urn:oid:1.2.246.517.2002.2.27
374
+ urn:oid:0.9.2342.19200300.100.1.3
375
+ urn:oid:1.2.246.517.2002.2.18
376
+ urn:oid:1.2.246.517.2002.2.19
377
+ urn:oid:1.2.246.517.2002.2.20
378
+ urn:oid:1.2.246.517.2002.2.4
379
+ urn:oid:1.2.246.517.2002.2.5
380
+ urn:oid:1.2.246.517.2002.2.6
381
+ urn:oid:1.2.246.517.2002.2.7
382
+ urn:oid:1.2.246.517.2002.2.8
383
+ urn:oid:1.2.246.517.2002.2.11
384
+ urn:oid:1.2.246.517.2002.2.12
385
+ urn:oid:1.2.246.517.2002.2.13
386
+ urn:oid:1.2.246.517.2002.2.14
387
+ urn:oid:1.2.246.517.2002.2.15
388
+ urn:oid:1.2.246.517.2002.2.31
389
+ urn:oid:1.2.246.517.2002.2.32
390
+ urn:oid:1.2.246.517.2002.2.33
391
+ urn:oid:1.2.246.517.2002.2.34
392
+ urn:oid:1.2.246.517.2002.2.35
393
+ ],
394
+ extensive: %w[urn:oid:1.2.246.517.2002.2.26]
395
+ )
396
+
397
+ # Salt that is used for the UID hashing. If not set, will use Rails
398
+ # secret_key_base when under Rails. If not set and not using Rails, the
399
+ # salt will be an empty string (not suggested).
400
+ option :uid_salt, nil
401
+
402
+ # Default relay state to the root path. This will redirect the logout
403
+ # requests to the root of the application in case this configuration is
404
+ # not overridden. Please refer to the omniauth-saml gem's documentation in
405
+ # order to define this option.
406
+ option :slo_default_relay_state, '/'
407
+
408
+ # Customize the UID fetching as this has few conditions.
409
+ #
410
+ # The electronic identification number (sähköinen asiointitunnus, SATU) is
411
+ # a unique electronic ID bound to the person. The ID itself does not
412
+ # reveal any personal information of the person holding it unlike the
413
+ # national identifiers can do.
414
+ #
415
+ # The SATU ID is only assigned to real people and cannot be therefore
416
+ # determined e.g. in the Suomi.fi testing environment which is why we
417
+ # provide a fallback using the national identifier which is always set for
418
+ # Suomi.fi authentication requests
419
+ #
420
+ # For eIDAS authentications, both SATU ID and the national identifier are
421
+ # NOT set, so in those cases we need to use the eIDAS personal identifier.
422
+ #
423
+ # The national identifier and eIDAS personal identifier are hashed in
424
+ # order to hide any personal details they are carrying (such as date of
425
+ # birth, gender, etc.). Please provide a salt with the `uid_salt`
426
+ # configuration option for proper hashing of the strings. For Rails, it
427
+ # will be automatically set by
428
+ # `Rails.application.secrets.secret_key_base`.
429
+ #
430
+ # Finally, fallback to the SAML NameID which is only unique per session.
431
+ # This should not happen with any valid authentication requests.
432
+ uid do
433
+ electronic_id = find_attribute_by(['urn:oid:1.2.246.22'])
434
+ national_id = find_attribute_by(['urn:oid:1.2.246.21'])
435
+ eidas_id = find_attribute_by(
436
+ ['http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier']
437
+ )
438
+ hash_salt = begin
439
+ if options.uid_salt
440
+ options.uid_salt
441
+ elsif defined?(::Rails) && ::Rails.application
442
+ ::Rails.application.secrets.secret_key_base
443
+ else
444
+ ''
445
+ end
446
+ end
447
+
448
+ if !electronic_id.nil?
449
+ 'FINUID:' + electronic_id
450
+ elsif !national_id.nil?
451
+ 'FIHETU:' + Digest::MD5.hexdigest("FI:#{national_id}:#{hash_salt}")
452
+ elsif !eidas_id.nil?
453
+ 'EIDASPID:' + Digest::MD5.hexdigest("EIDAS:#{eidas_id}:#{hash_salt}")
454
+ else
455
+ @name_id
456
+ end
457
+ end
458
+
459
+ # Add the SAML attributes and the VTJ search success state to the extra
460
+ # hash for easier access.
461
+ extra do
462
+ {
463
+ search_success: search_success,
464
+ saml_attributes: saml_attributes
465
+ }
466
+ end
467
+
468
+ def initialize(app, *args, &block)
469
+ super
470
+
471
+ # Add the request attributes to the options.
472
+ options[:request_attributes] = scoped_request_attributes
473
+ options[:sp_name_qualifier] = options[:sp_entity_id] if options[:sp_name_qualifier].nil?
474
+
475
+ # Remove the nil options from the origianl options array that will be
476
+ # defined by the Suomi.fi options
477
+ %i[
478
+ certificate
479
+ private_key
480
+ idp_name_qualifier
481
+ name_identifier_format
482
+ security
483
+ ].each do |key|
484
+ options.delete(key) if options[key].nil?
485
+ end
486
+
487
+ # Add the Suomi.fi options to the local options, most of which are
488
+ # fetched from the metadata. The options array is the one that gets
489
+ # priority in case it overrides some of the metadata or locally defined
490
+ # option values.
491
+ @options = OmniAuth::Strategy::Options.new(
492
+ suomifi_options.merge(options)
493
+ )
494
+ end
495
+
496
+ # This method can be used externally to fetch information about the
497
+ # response, e.g. in case of failures.
498
+ def response_object
499
+ return nil unless request.params['SAMLResponse']
500
+
501
+ with_settings do |settings|
502
+ response = OneLogin::RubySaml::Response.new(
503
+ request.params['SAMLResponse'],
504
+ options_for_response_object.merge(settings: settings)
505
+ )
506
+ response.attributes['fingerprint'] = settings.idp_cert_fingerprint
507
+ response
508
+ end
509
+ end
510
+
511
+ private
512
+
513
+ # Suomi.fi requires that the service provider needs to end the local user
514
+ # session BEFORE sending the logout request to the identity provider.
515
+ def other_phase_for_spslo
516
+ return super unless options.idp_slo_target_url
517
+
518
+ with_settings do |settings|
519
+ # Some session variables are needed when generating the logout request
520
+ request = generate_logout_request(settings)
521
+ # Destroy the local user session
522
+ options[:idp_slo_session_destroy].call @env, session
523
+ # Send the logout request to the identity provider
524
+ redirect(request)
525
+ end
526
+ end
527
+
528
+ def scoped_request_attributes
529
+ scopes = [:limited]
530
+ scopes << :medium_extensive if options.scope_of_data == :medium_extensive
531
+ scopes << :medium_extensive if options.scope_of_data == :extensive
532
+ scopes << :extensive if options.scope_of_data == :extensive
533
+
534
+ names = options.scoped_attributes.select do |key, _v|
535
+ scopes.include?(key.to_sym)
536
+ end.values.flatten
537
+
538
+ options.possible_request_attributes.select do |attr|
539
+ names.include?(attr[:name])
540
+ end
541
+ end
542
+
543
+ def certificate
544
+ File.read(options.certificate_file) if options.certificate_file
545
+ end
546
+
547
+ def private_key
548
+ File.read(options.private_key_file) if options.private_key_file
549
+ end
550
+
551
+ def idp_metadata_url
552
+ case options.mode
553
+ when :test
554
+ 'https://testi.apro.tunnistus.fi/static/metadata/idp-metadata.xml'
555
+ else
556
+ 'https://tunnistus.suomi.fi/static/metadata/idp-metadata-secondary.xml'
557
+ end
558
+ end
559
+
560
+ def suomifi_options
561
+ idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
562
+
563
+ # Returns OneLogin::RubySaml::Settings prepopulated with idp metadata
564
+ # We are using the redirect binding for the SSO and SLO URLs as these
565
+ # are the ones expected by omniauth-saml. Otherwise the default would be
566
+ # the first one defined in the IdP metadata, which would be the
567
+ # HTTP-POST binding.
568
+ settings = idp_metadata_parser.parse_remote_to_hash(
569
+ idp_metadata_url,
570
+ true,
571
+ sso_binding: ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'],
572
+ slo_binding: ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect']
573
+ )
574
+
575
+ # Local certificate and private key to decrypt the responses
576
+ settings[:certificate] = certificate
577
+ settings[:private_key] = private_key
578
+
579
+ # Define the security settings as there are some defaults that need to be
580
+ # modified
581
+ security_defaults = OneLogin::RubySaml::Settings::DEFAULTS[:security]
582
+ settings[:security] = security_defaults.merge(options.security_settings)
583
+
584
+ # Add some extra information that is necessary for correctly formatted
585
+ # logout requests.
586
+ settings[:idp_name_qualifier] = settings[:idp_entity_id]
587
+
588
+ settings
589
+ end
590
+
591
+ # This will return true if the VTJ search (population information system,
592
+ # väestötietojärjestelmä) was successful and information about the person
593
+ # was transmitted in the SAML response.
594
+ def search_success
595
+ success_string = find_attribute_by(['urn:oid:1.2.246.517.3002.111.2'])
596
+ success_string == 'true'
597
+ end
598
+
599
+ def saml_attributes
600
+ {}.tap do |attrs|
601
+ options.saml_attributes_map.each do |target, source|
602
+ attrs[target] = find_attribute_by(source)
603
+ end
604
+ end
605
+ end
606
+ end
607
+ end
608
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module Suomifi
5
+ module Test
6
+ class CertificateGenerator
7
+ def private_key
8
+ @private_key ||= OpenSSL::PKey::RSA.new(2048)
9
+ end
10
+
11
+ def certificate
12
+ @certificate ||= begin
13
+ public_key = private_key.public_key
14
+
15
+ subject = '/C=FI/O=Test/OU=Test/CN=Test'
16
+
17
+ cert = OpenSSL::X509::Certificate.new
18
+ cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
19
+ cert.not_before = Time.now
20
+ cert.not_after = Time.now + 365 * 24 * 60 * 60
21
+ cert.public_key = public_key
22
+ cert.serial = 0x0
23
+ cert.version = 2
24
+
25
+ inject_certificate_extensions(cert)
26
+
27
+ cert.sign(private_key, OpenSSL::Digest::SHA1.new)
28
+
29
+ cert
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def inject_certificate_extensions(cert)
36
+ ef = OpenSSL::X509::ExtensionFactory.new
37
+ ef.subject_certificate = cert
38
+ ef.issuer_certificate = cert
39
+ cert.extensions = [
40
+ ef.create_extension('basicConstraints', 'CA:TRUE', true),
41
+ ef.create_extension('subjectKeyIdentifier', 'hash')
42
+ ]
43
+ cert.add_extension ef.create_extension(
44
+ 'authorityKeyIdentifier',
45
+ 'keyid:always,issuer:always'
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ <xenc:EncryptedData
2
+ Id="_dd298c0227265312ce7734f3fb5efb75"
3
+ Type="http://www.w3.org/2001/04/xmlenc#Element"
4
+ xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
5
+ <xenc:EncryptionMethod
6
+ Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"
7
+ xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
8
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
9
+ <xenc:EncryptedKey
10
+ Id="_d42382ed503d12d288b0e63b4123d244"
11
+ Recipient="http://localhost:3000/users/auth/suomifi/metadata"
12
+ xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
13
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
14
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
15
+ </xenc:EncryptionMethod>
16
+ <ds:KeyInfo>
17
+ <ds:X509Data>
18
+ <ds:X509Certificate></ds:X509Certificate>
19
+ </ds:X509Data>
20
+ </ds:KeyInfo>
21
+ <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
22
+ <xenc:CipherValue></xenc:CipherValue>
23
+ </xenc:CipherData>
24
+ </xenc:EncryptedKey>
25
+ </ds:KeyInfo>
26
+ <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
27
+ <xenc:CipherValue></xenc:CipherValue>
28
+ </xenc:CipherData>
29
+ </xenc:EncryptedData>