omniauth-suomifi 0.1.0

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.
@@ -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>