ndr_authenticate 0.3.5

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +58 -0
  3. data/CODE_OF_CONDUCT.md +13 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +227 -0
  6. data/Rakefile +33 -0
  7. data/app/assets/config/ndr_authenticate_manifest.js +2 -0
  8. data/app/assets/images/ndr_authenticate/.keep +0 -0
  9. data/app/assets/javascripts/ndr_authenticate/ndr_authenticate.js +14 -0
  10. data/app/assets/stylesheets/ndr_authenticate/ndr_authenticate.scss +1 -0
  11. data/app/controllers/concerns/ndr_authenticate/authenticatable.rb +21 -0
  12. data/app/controllers/concerns/ndr_authenticate/devise_helpers.rb +17 -0
  13. data/app/controllers/concerns/ndr_authenticate/turbolinks.rb +31 -0
  14. data/app/controllers/concerns/ndr_authenticate/yubikey/authenticatable.rb +94 -0
  15. data/app/controllers/concerns/ndr_authenticate/yubikey/protectable.rb +103 -0
  16. data/app/controllers/ndr_authenticate/application_controller.rb +22 -0
  17. data/app/controllers/ndr_authenticate/authentication_controller.rb +27 -0
  18. data/app/controllers/ndr_authenticate/saml_sessions_controller.rb +46 -0
  19. data/app/controllers/ndr_authenticate/sessions_controller.rb +22 -0
  20. data/app/helpers/ndr_authenticate/application_helper.rb +22 -0
  21. data/app/helpers/ndr_authenticate/authentication_helper.rb +4 -0
  22. data/app/jobs/ndr_authenticate/application_job.rb +4 -0
  23. data/app/mailers/ndr_authenticate/application_mailer.rb +6 -0
  24. data/app/models/ndr_authenticate/application_record.rb +5 -0
  25. data/app/views/devise/passwords/edit.html.erb +23 -0
  26. data/app/views/devise/passwords/new.html.erb +18 -0
  27. data/app/views/devise/sessions/new.html.erb +21 -0
  28. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  29. data/app/views/devise/shared/_links.html.erb +25 -0
  30. data/app/views/layouts/ndr_authenticate/ndr_authenticate.html.erb +47 -0
  31. data/app/views/ndr_authenticate/authentication/check_active.html.erb +30 -0
  32. data/app/views/ndr_authenticate/shared/_legal_notice.html.erb +13 -0
  33. data/app/views/ndr_authenticate/yubikey/protectable/_form.html.erb +44 -0
  34. data/app/views/ndr_authenticate/yubikey/protectable/_modal.html.erb +10 -0
  35. data/app/views/ndr_authenticate/yubikey/protectable/_panel.html.erb +13 -0
  36. data/app/views/ndr_authenticate/yubikey/protectable/challenge.html.erb +9 -0
  37. data/app/views/ndr_authenticate/yubikey/protectable/challenge.js.erb +41 -0
  38. data/app/views/shared/_flash_messages.html.erb +17 -0
  39. data/config/certificates/saml/certificate.pem +23 -0
  40. data/config/certificates/saml/encryption.phe.adfs.pem +18 -0
  41. data/config/certificates/saml/signing.phe.adfs.pem +19 -0
  42. data/config/initializers/devise.rb +37 -0
  43. data/config/locales/en.yml +15 -0
  44. data/config/routes.rb +24 -0
  45. data/lib/generators/ndr_authenticate/install/USAGE +10 -0
  46. data/lib/generators/ndr_authenticate/install/install_generator.rb +20 -0
  47. data/lib/generators/ndr_authenticate/install/templates/attribute-map.yml +77 -0
  48. data/lib/generators/ndr_authenticate/install/templates/migration.rb +13 -0
  49. data/lib/generators/ndr_authenticate/install/templates/ndr_authenticate.rb +31 -0
  50. data/lib/ndr_authenticate/connector.rb +45 -0
  51. data/lib/ndr_authenticate/engine.rb +76 -0
  52. data/lib/ndr_authenticate/saml_config.rb +39 -0
  53. data/lib/ndr_authenticate/version.rb +3 -0
  54. data/lib/ndr_authenticate/yubikey/verify.rb +26 -0
  55. data/lib/ndr_authenticate/yubikey.rb +7 -0
  56. data/lib/ndr_authenticate.rb +127 -0
  57. data/lib/tasks/ndr_authenticate_tasks.rake +4 -0
  58. metadata +287 -0
@@ -0,0 +1,20 @@
1
+ require 'rails/generators/active_record/migration'
2
+
3
+ module NdrAuthenticate
4
+ # Installs configuration files required by NdrAuthenticate into host application.
5
+ class InstallGenerator < Rails::Generators::Base
6
+ include ActiveRecord::Generators::Migration
7
+
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+ def copy_config_files
11
+ config_path = Pathname.new(destination_root).join('config')
12
+ migrations_path = Pathname.new(db_migrate_path)
13
+
14
+ copy_file 'ndr_authenticate.rb', config_path.join('initializers', 'ndr_authenticate.rb')
15
+ copy_file 'attribute-map.yml', config_path.join('attribute-map.yml')
16
+
17
+ migration_template 'migration.rb', migrations_path.join('add_ndr_authenticate.rb')
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ phe: &phe
2
+ objectGuid: object_guid
3
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress:
4
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname:
5
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name:
6
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn:
7
+ # http://schemas.xmlsoap.org/claims/CommonName:
8
+ # http://schemas.xmlsoap.org/claims/EmailAddress:
9
+ # http://schemas.xmlsoap.org/claims/Group:
10
+ # http://schemas.xmlsoap.org/claims/UPN:
11
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/role:
12
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname:
13
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier:
14
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier:
15
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant:
16
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod:
17
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid:
18
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid:
19
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid:
20
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid:
21
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid:
22
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid:
23
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname:
24
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/isregistereduser:
25
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/identifier:
26
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/registrationid:
27
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/displayname:
28
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/ostype:
29
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/osversion:
30
+ # http://schemas.microsoft.com/2012/01/devicecontext/claims/ismanaged:
31
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip:
32
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application:
33
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent:
34
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-ip:
35
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path:
36
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy:
37
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/relyingpartytrustid:
38
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/applicationpolicy:
39
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/authoritykeyidentifier:
40
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/basicconstraints:
41
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/eku:
42
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/issuer:
43
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/issuername:
44
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/keyusage:
45
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/notafter:
46
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/notbefore:
47
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatepolicy:
48
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa:
49
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/rawdata:
50
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/san:
51
+ # http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber:
52
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/signaturealgorithm:
53
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/subject:
54
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/subjectkeyidentifier:
55
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/subjectname:
56
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplateinformation:
57
+ # http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplatename:
58
+ # http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint:
59
+ # http://schemas.microsoft.com/2012/12/certificatecontext/field/x509version:
60
+ # http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork:
61
+ # http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime:
62
+ # http://schemas.microsoft.com/ws/2012/01/passwordexpirationdays:
63
+ # http://schemas.microsoft.com/ws/2012/01/passwordchangeurl:
64
+ # http://schemas.microsoft.com/claims/authnmethodsreferences:
65
+ # http://schemas.microsoft.com/2012/01/requestcontext/claims/client-request-id:
66
+ # http://schemas.microsoft.com/ws/2013/11/alternateloginid:
67
+
68
+ default: &default {}
69
+
70
+ development:
71
+ <<: *default
72
+
73
+ test:
74
+ <<: *default
75
+
76
+ production:
77
+ <<: *default
@@ -0,0 +1,13 @@
1
+ class AddNdrAuthenticate < ActiveRecord::Migration[5.2]
2
+ class User < NdrAuthenticate.user_class.constantize; end
3
+
4
+ def change
5
+ add_column User.table_name, saml_session_index_key, :string
6
+ end
7
+
8
+ private
9
+
10
+ def saml_session_index_key
11
+ Devise.saml_session_index_key || :session_index
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ NdrAuthenticate.configure do |config|
2
+ # Name of the user class within the host application.
3
+ config.user_class = 'User'
4
+
5
+ # Callable object that controls availability of SSO logins.
6
+ config.sso_enabled = ->(_request) { Rails.env.production? }
7
+
8
+ # Additional parameters to be filtered from Rails logs.
9
+ # config.filter_parameters = %i[
10
+ # SAMLRequest
11
+ # SAMLResponse
12
+ # password
13
+ # password_confirmation
14
+ # reset_password_token
15
+ # ]
16
+
17
+ # Credentials for Yubico Web Services (https://upgrade.yubico.com/getapikey/)
18
+ # config.yubikey_api_id = nil
19
+ # config.yubikey_api_key = nil
20
+
21
+ # Strategies for validating OTPWs for protected actions.
22
+ # Host applications are invited to add their own challenges. These should be `call`able objects
23
+ # that accept OTPW, user and controller context objects and return a boolean value.
24
+ # config.invalid_otp_reasons = {
25
+ # missing: ->(otp, _user, _context) { otp.blank? },
26
+ # invalid: ->(otp, _user, _context) { !Yubikey::Verify.call(otp) }
27
+ # }
28
+
29
+ # Apply pre-configured PHE ADFS SAML configuration.
30
+ config.load_defaults :phe
31
+ end
@@ -0,0 +1,45 @@
1
+ require 'net/ldap'
2
+ module NdrAuthenticate
3
+ # Logic to connect to PHE AD via ldap protocol to find out if user exists
4
+ # and has an active/enabled account
5
+ class Connector
6
+ def configure_ldap
7
+ config = YAML.load_file(Rails.root.join('config', 'ldap.yml'))[Rails.env]
8
+ @hosts = config.fetch(:hosts)
9
+ @username = config.fetch(:username)
10
+ @password = config.fetch(:password)
11
+ end
12
+
13
+ def search_for(email)
14
+ configure_ldap
15
+
16
+ ldap = Net::LDAP.new(hosts: @hosts,
17
+ auth: {
18
+ method: :simple,
19
+ username: @username,
20
+ password: @password
21
+ },
22
+ encryption: {
23
+ method: :simple_tls,
24
+ tls_options: {
25
+ ca_file: Rails.root.join('config', 'phe_cacert.pem').to_s,
26
+ ssl_version: 'TLSv1_1'
27
+ }
28
+ })
29
+
30
+ email_filter = Net::LDAP::Filter.eq('userPrincipalName', email)
31
+ category_filter = Net::LDAP::Filter.eq('objectCategory', 'person')
32
+ objectclass_filter = Net::LDAP::Filter.eq('objectClass', 'user')
33
+ enable_filter = ~Net::LDAP::Filter.present('userAccountControl:1.2.840.113556.1.4.803:=2')
34
+ filter = email_filter & category_filter & objectclass_filter & enable_filter
35
+ treebase = 'OU=User Objects - Employee Accounts,OU=Administrated Objects,DC=phe,DC=gov,DC=uk'
36
+
37
+ user = ldap.search(base: treebase,
38
+ filter: filter,
39
+ attributes: %w[sAMAccountName], # can use attribute to ensure looking \
40
+ # at right person
41
+ return_result: true)
42
+ user.size == 1
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,76 @@
1
+ # We need to require these explicitly here, to avoid Rails zeitwerk autoload issues
2
+ require File.join(__dir__, '../../app/controllers/concerns/ndr_authenticate/devise_helpers')
3
+ require File.join(__dir__, '../../app/controllers/concerns/ndr_authenticate/yubikey/protectable')
4
+
5
+ module NdrAuthenticate
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace NdrAuthenticate
8
+
9
+ initializer 'ndr_authenticate.assets.precompile' do |app|
10
+ app.config.assets.precompile += %w[
11
+ ndr_authenticate/ndr_authenticate.css
12
+ ndr_authenticate/ndr_authenticate.js
13
+ ndr_authenticate/bootstrap/glyphicons-halflings-regular*
14
+ ]
15
+ end
16
+
17
+ # Patch DeviseSamlAuthenticatable with the ability to configure IdP/SP automagically.
18
+ initializer 'ndr_authenticate.devise_saml_authenticatable' do
19
+ DeviseSamlAuthenticatable::SamlConfig.prepend(NdrAuthenticate::SamlConfig)
20
+ end
21
+
22
+ initializer 'ndr_authenticate.action_controller' do
23
+ ActiveSupport.on_load(:action_controller, run_once: true) do
24
+ include NdrAuthenticate::DeviseHelpers
25
+ include NdrAuthenticate::Yubikey::Protectable
26
+ end
27
+ end
28
+
29
+ initializer 'ndr_authenticate.filter_parameters' do |app|
30
+ app.config.filter_parameters += NdrAuthenticate.filter_parameters
31
+ end
32
+
33
+ initializer 'ndr_authenticate.yubikey.configure' do
34
+ ::Yubikey.configure do |config|
35
+ config.url = NdrAuthenticate.yubikey_api_url || ::Yubikey::Configuration::DEFAULT_API_URL
36
+ config.api_id = NdrAuthenticate.yubikey_api_id
37
+ config.api_key = NdrAuthenticate.yubikey_api_key
38
+ end
39
+
40
+ # Patch intended as a workaround for issues (hardcoded certs, SNI requirement) with the
41
+ # Yubikey gem follwing the YubiCloud service upgrade.
42
+ # See https://status.yubico.com/2019/11/21/2019-11-21-yubicloud-service-upgrade/
43
+ # TODO: When time allows, we should probably look at dropping the dependency and
44
+ # rolling our own implementation.
45
+ ::Yubikey::OTP::Verify.prepend(Module.new do
46
+ def verify(args)
47
+ query = "id=#{@api_id}&otp=#{args[:otp]}&nonce=#{@nonce}"
48
+
49
+ uri = URI.parse(@url) + 'verify'
50
+ uri.query = query
51
+
52
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
53
+ http.cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths)
54
+
55
+ result = http.get(uri.request_uri)
56
+ @status = result.body[/status=(.*)$/, 1].strip
57
+
58
+ if @status == 'BAD_OTP' || @status == 'BACKEND_ERROR'
59
+ raise ::Yubikey::OTP::InvalidOTPError, "Received error: #{@status}"
60
+ end
61
+
62
+ @status = 'BAD_RESPONSE' unless verify_response(result.body)
63
+ end
64
+ end
65
+ end)
66
+ end
67
+
68
+ initializer 'ndr_authenticate.turbolinks' do
69
+ ActiveSupport.on_load(:action_controller) do
70
+ if const_defined?('Turbolinks')
71
+ NdrAuthenticate::SamlSessionsController.include(NdrAuthenticate::Turbolinks)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,39 @@
1
+ module NdrAuthenticate
2
+ # Patch for DeviseSamlAuthenticatable::SamlConfig.
3
+ # Allows for SAML configuration to be composed and cached.
4
+ module SamlConfig
5
+ include Engine.routes.url_helpers
6
+
7
+ mattr_accessor :cache
8
+ self.cache = {}
9
+
10
+ def saml_config(idp_entity_id = nil, request = nil)
11
+ cache.fetch(idp_entity_id) do |idp|
12
+ settings = super
13
+
14
+ settings.issuer ||= saml_metadata_url
15
+ settings.assertion_consumer_service_url ||= saml_user_session_url
16
+ settings.assertion_consumer_logout_service_url ||= idp_destroy_saml_user_session_url
17
+
18
+ idp_settings.each { |key, value| settings.try("#{key}=", value) }
19
+
20
+ cache.store(idp, settings)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def default_url_options
27
+ { host: request.host_with_port, protocol: request.protocol }
28
+ end
29
+
30
+ def idp_settings
31
+ return {} unless NdrAuthenticate.idp_metadata_url
32
+
33
+ OneLogin::RubySaml::IdpMetadataParser.new.
34
+ parse_remote_to_hash(NdrAuthenticate.idp_metadata_url)
35
+ rescue OneLogin::RubySaml::HttpError
36
+ {}
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module NdrAuthenticate
2
+ VERSION = '0.3.5'.freeze
3
+ end
@@ -0,0 +1,26 @@
1
+ module NdrAuthenticate
2
+ module Yubikey
3
+ # Performs basic validity check of YubiKey OTPWs.
4
+ class Verify
5
+ attr_reader :otp
6
+
7
+ def self.call(otp)
8
+ new(otp).valid?
9
+ end
10
+
11
+ def initialize(otp)
12
+ @otp = otp
13
+ end
14
+
15
+ def valid?
16
+ verify.valid?
17
+ rescue ::Yubikey::OTP::InvalidOTPError
18
+ false
19
+ end
20
+
21
+ def verify
22
+ @verify ||= ::Yubikey::OTP::Verify.new(otp: otp)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ require 'ndr_authenticate/yubikey/verify'
2
+
3
+ module NdrAuthenticate
4
+ # Namespace for Yubikey related code
5
+ module Yubikey
6
+ end
7
+ end
@@ -0,0 +1,127 @@
1
+ require 'devise'
2
+ require 'devise_saml_authenticatable'
3
+ require 'yubikey'
4
+ require 'ndr_ui'
5
+ require 'ndr_authenticate/engine'
6
+ require 'ndr_authenticate/saml_config'
7
+ require 'ndr_authenticate/yubikey'
8
+
9
+ # Configuration and convenience methods.
10
+ module NdrAuthenticate
11
+ # Name of the user class within the host application.
12
+ mattr_accessor :user_class
13
+ self.user_class = 'User'
14
+
15
+ # Callable object that controls availability of SSO logins.
16
+ # Set to false to disable entirely.
17
+ mattr_accessor :sso_enabled
18
+ self.sso_enabled = ->(_request) { Rails.env.production? }
19
+
20
+ # URL for the IdP metadata endpoint. When set allows IdP to be configured automagically,
21
+ # providing the URL is reachable.
22
+ mattr_accessor :idp_metadata_url
23
+ self.idp_metadata_url = nil
24
+
25
+ # Additional parameters to be filtered from Rails logs.
26
+ mattr_accessor :filter_parameters
27
+ self.filter_parameters = %i[
28
+ SAMLRequest
29
+ SAMLResponse
30
+ password
31
+ password_confirmation
32
+ reset_password_token
33
+ ]
34
+
35
+ # Configuration for Yubico Web Services (https://upgrade.yubico.com/getapikey/)
36
+ mattr_accessor :yubikey_api_url
37
+ mattr_accessor :yubikey_api_id
38
+ mattr_accessor :yubikey_api_key
39
+
40
+ # TODO: There's likely to be significant overlap with :invalid_otp_reasons - can we DRY
41
+ # this is up somehow?
42
+ mattr_accessor :invalid_key_reasons
43
+ self.invalid_key_reasons = {
44
+ missing: ->(key, _user, _context) { key.blank? }
45
+ }
46
+
47
+ # Strategies for validating OTPWs for protected actions.
48
+ # Host applications are invited to add their own challenges. These should be `call`able objects
49
+ # that accept OTPW, user and controller context objects and return a boolean value.
50
+ mattr_accessor :invalid_otp_reasons
51
+ self.invalid_otp_reasons = {
52
+ missing: ->(otp, _user, _context) { otp.blank? },
53
+ invalid: ->(otp, _user, _context) { !Yubikey::Verify.call(otp) }
54
+ }
55
+
56
+ class << self
57
+ # Syntactic sugar for configuring NdrAuthenticate in an initializer file within host app.
58
+ def configure
59
+ yield(self)
60
+ end
61
+
62
+ def devise
63
+ Devise
64
+ end
65
+
66
+ def default_certificate
67
+ File.read(saml_certificates_path.join('certificate.pem'))
68
+ end
69
+
70
+ def load_defaults(name = :phe)
71
+ case name.to_sym
72
+ when :phe
73
+ load_phe_defaults
74
+ else
75
+ raise "Unknown configuration: #{name}"
76
+ end
77
+ end
78
+
79
+ def sso_enabled_ever?
80
+ sso_enabled.present?
81
+ end
82
+
83
+ private
84
+
85
+ def saml_certificates_path
86
+ @saml_certificates_path ||= Pathname.new(Engine.root.join('config', 'certificates', 'saml'))
87
+ end
88
+
89
+ def load_phe_defaults
90
+ devise.setup do |config|
91
+ config.saml_default_user_key = :object_guid
92
+ end
93
+
94
+ devise.saml_configure do |config|
95
+ # General
96
+ config.name_identifier_format = 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
97
+
98
+ # IdP (ADFS)
99
+ config.idp_entity_id = 'http://fs.phe.gov.uk/adfs/services/trust'
100
+ config.idp_sso_target_url = 'https://fs.phe.gov.uk/adfs/ls/'
101
+ config.idp_slo_target_url = 'https://fs.phe.gov.uk/adfs/ls/'
102
+
103
+ # Privacy/Security
104
+ security = config.security
105
+ security[:authn_requests_signed] = true
106
+ security[:logout_requests_signed] = true
107
+ security[:logout_responses_signed] = true
108
+ security[:want_assertions_signed] = true
109
+ security[:want_assertions_encrypted] = true
110
+ security[:want_name_id] = true
111
+ security[:metadata_signed] = true
112
+ security[:embed_sign] = true
113
+ security[:check_idp_cert_expiration] = true
114
+ security[:check_sp_cert_expiration] = true
115
+ security[:digest_method] = 'http://www.w3.org/2001/04/xmlenc#sha256'
116
+ security[:signature_method] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
117
+
118
+ # Certificates
119
+ config.certificate = default_certificate
120
+ config.idp_cert_multi = {
121
+ encryption: [File.read(saml_certificates_path.join('encryption.phe.adfs.pem'))],
122
+ signing: [File.read(saml_certificates_path.join('signing.phe.adfs.pem'))]
123
+ }
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :ndr_authenticate do
3
+ # # Task goes here
4
+ # end