devise_saml_authenticatable 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,7 @@
1
1
  # Set up a SAML IdP
2
2
 
3
+ @email_address_attribute_key = ENV.fetch("EMAIL_ADDRESS_ATTRIBUTE_KEY", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")
4
+ @name_attribute_key = ENV.fetch("NAME_ATTRIBUTE_KEY", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name")
3
5
  @include_subject_in_attributes = ENV.fetch('INCLUDE_SUBJECT_IN_ATTRIBUTES')
4
6
  @valid_destination = ENV.fetch('VALID_DESTINATION', "true")
5
7
 
@@ -7,7 +9,7 @@ if Rails::VERSION::MAJOR < 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
7
9
  gsub_file 'config/secrets.yml', /secret_key_base:.*$/, 'secret_key_base: "34814fd41f91c493b89aa01ac73c44d241a31245b5bc5542fa4b7317525e1dcfa60ba947b3d085e4e229456fdee0d8af6aac6a63cf750d807ea6fe5d853dff4a"'
8
10
  end
9
11
 
10
- gem 'ruby-saml-idp', git: "https://github.com/lawrencepit/ruby-saml-idp.git", ref: "ec715b252e849105c7a96df27b731c6e7f725a51"
12
+ gem 'ruby-saml-idp', '~> 0.3.3'
11
13
  gem 'thin'
12
14
 
13
15
  insert_into_file('Gemfile', after: /\z/) {
@@ -1,6 +1,7 @@
1
- require 'open3'
2
- require 'socket'
3
- require 'timeout'
1
+ require "open3"
2
+ require "socket"
3
+ require "tempfile"
4
+ require "timeout"
4
5
 
5
6
  APP_READY_TIMEOUT ||= 30
6
7
 
@@ -17,25 +18,32 @@ rescue Errno::ESRCH
17
18
  end
18
19
 
19
20
  def create_app(name, env = {})
20
- rails_new_options = %w(-T -J -S --skip-spring --skip-listen --skip-bootsnap)
21
- rails_new_options << "-O" if name == 'idp'
22
- Dir.chdir(File.expand_path('../../support', __FILE__)) do
23
- FileUtils.rm_rf(name)
24
- system(env, "rails", "new", name, *rails_new_options, "-m", "#{name}_template.rb")
21
+ puts "[#{name}] Creating Rails app"
22
+ rails_new_options = %w[-T -J -S --skip-spring --skip-listen --skip-bootsnap]
23
+ rails_new_options << "-O" if name == "idp"
24
+ with_clean_env do
25
+ Dir.chdir(working_directory) do
26
+ FileUtils.rm_rf(name)
27
+ puts("rails _#{Rails.version}_ new #{name} #{rails_new_options.join(" ")} -m #{File.expand_path("../#{name}_template.rb", __FILE__)}")
28
+ system(env, "rails", "_#{Rails.version}_", "new", name, *rails_new_options, "-m", File.expand_path("../#{name}_template.rb", __FILE__))
29
+ end
25
30
  end
26
31
  end
27
32
 
28
33
  def start_app(name, port, options = {})
34
+ puts "[#{name}] Starting Rails app"
29
35
  pid = nil
30
- Bundler.with_clean_env do
31
- Dir.chdir(File.expand_path("../../support/#{name}", __FILE__)) do
32
- pid = Process.spawn({"RAILS_ENV" => "production"}, "bundle exec rails server -p #{port} -e production", out: "log/#{name}.log", err: "log/#{name}.err.log")
36
+ app_bundle_install(name)
37
+
38
+ with_clean_env do
39
+ Dir.chdir(app_dir(name)) do
40
+ pid = Process.spawn(app_env(name), "bundle exec rails server -p #{port} -e production", chdir: app_dir(name), out: "log/#{name}.log", err: "log/#{name}.err.log")
33
41
  begin
34
- Timeout::timeout(APP_READY_TIMEOUT) do
42
+ Timeout.timeout(APP_READY_TIMEOUT) do
35
43
  sleep 1 until app_ready?(pid, port)
36
44
  end
37
45
  if app_ready?(pid, port)
38
- puts "Launched #{name} on port #{port} (pid #{pid})..."
46
+ puts "[#{name}] Launched #{name} on port #{port} (pid #{pid})..."
39
47
  else
40
48
  raise "#{name} failed after starting"
41
49
  end
@@ -46,16 +54,33 @@ def start_app(name, port, options = {})
46
54
  end
47
55
  pid
48
56
  rescue RuntimeError => e
49
- $stdout.puts "#{File.read(File.expand_path("../../support/#{name}/log/#{name}.log", __FILE__))}"
50
- $stderr.puts "#{File.read(File.expand_path("../../support/#{name}/log/#{name}.err.log", __FILE__))}"
57
+ warn "=== #{name}"
58
+ Dir.chdir(app_dir(name)) do
59
+ warn File.read("log/#{name}.log") if File.exist?("log/#{name}.log")
60
+ warn File.read("log/#{name}.err.log") if File.exist?("log/#{name}.err.log")
61
+ end
51
62
  raise e
52
63
  end
53
64
 
54
- def stop_app(pid)
65
+ def stop_app(name, pid)
55
66
  if pid
56
67
  Process.kill(:INT, pid)
57
68
  Process.wait(pid)
58
69
  end
70
+ Dir.chdir(app_dir(name)) do
71
+ if File.exist?("log/#{name}.log")
72
+ puts "=== [#{name}] stdout"
73
+ puts File.read("log/#{name}.log")
74
+ end
75
+ if File.exist?("log/#{name}.err.log")
76
+ warn "=== [#{name}] stderr"
77
+ warn File.read("log/#{name}.err.log")
78
+ end
79
+ if File.exist?("log/production.log")
80
+ puts "=== [#{name}] Rails logs"
81
+ puts File.read("log/production.log")
82
+ end
83
+ end
59
84
  end
60
85
 
61
86
  def port_open?(port)
@@ -64,7 +89,7 @@ def port_open?(port)
64
89
  s = TCPSocket.new('localhost', port)
65
90
  s.close
66
91
  return true
67
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
92
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EADDRNOTAVAIL
68
93
  # try 127.0.0.1
69
94
  end
70
95
  begin
@@ -78,3 +103,36 @@ def port_open?(port)
78
103
  rescue Timeout::Error
79
104
  false
80
105
  end
106
+
107
+ def app_bundle_install(name)
108
+ with_clean_env do
109
+ Open3.popen3(app_env(name), "bundle install", chdir: app_dir(name)) do |stdin, stdout, stderr, thread|
110
+ stdin.close
111
+ exit_status = thread.value
112
+
113
+ puts stdout.read
114
+ warn stderr.read
115
+ raise "bundle install failed" unless exit_status.success?
116
+ end
117
+ end
118
+ end
119
+
120
+ def app_dir(name)
121
+ File.join(working_directory, name)
122
+ end
123
+
124
+ def app_env(name)
125
+ {"BUNDLE_GEMFILE" => File.join(app_dir(name), "Gemfile"), "RAILS_ENV" => "production"}
126
+ end
127
+
128
+ def working_directory
129
+ $working_directory ||= Dir.mktmpdir("dsa_test")
130
+ end
131
+
132
+ def with_clean_env(&blk)
133
+ if Bundler.respond_to?(:with_original_env)
134
+ Bundler.with_original_env(&blk)
135
+ else
136
+ Bundler.with_clean_env(&blk)
137
+ end
138
+ end
@@ -17,10 +17,10 @@ class SamlIdpController < SamlIdp::IdpController
17
17
 
18
18
  def idp_make_saml_response(_)
19
19
  attributes = {
20
- "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" => "A User",
20
+ name_attribute_key => "A User",
21
21
  }
22
22
  if include_subject_in_attributes
23
- attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"] = "you@example.com"
23
+ attributes[email_address_attribute_key] = "you@example.com"
24
24
  end
25
25
  encode_SAMLResponse("you@example.com", attributes: attributes)
26
26
  end
@@ -33,6 +33,13 @@ class SamlIdpController < SamlIdp::IdpController
33
33
  }
34
34
  end
35
35
 
36
+ def email_address_attribute_key
37
+ "<%= @email_address_attribute_key %>"
38
+ end
39
+
40
+ def name_attribute_key
41
+ "<%= @name_attribute_key %>"
42
+ end
36
43
 
37
44
  def encode_SAMLResponse(nameID, opts = {})
38
45
  now = Time.now.utc
@@ -50,7 +57,7 @@ class SamlIdpController < SamlIdp::IdpController
50
57
  attribute_statement = ""
51
58
  end
52
59
 
53
- assertion = %[<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_#{session_index}" IssueInstant="#{now.iso8601}" Version="2.0"><Issuer>#{issuer_uri}</Issuer><Subject><NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">#{nameID}</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData InResponseTo="#{@saml_request_id}" NotOnOrAfter="#{(now+3*60).iso8601}" Recipient="#{@saml_acs_url}"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore="#{(now-5).iso8601}" NotOnOrAfter="#{(now+60*60).iso8601}"><AudienceRestriction><Audience>#{audience_uri}</Audience></AudienceRestriction></Conditions>#{attribute_statement}<AuthnStatement AuthnInstant="#{now.iso8601}" SessionIndex="_#{session_index}"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatement></Assertion>]
60
+ assertion = %[<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_#{session_index}" IssueInstant="#{now.iso8601}" Version="2.0"><Issuer>#{issuer_uri}</Issuer><Subject><NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">#{nameID}</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData InResponseTo="#{@saml_request_id}" NotOnOrAfter="#{(now+3*60).iso8601}" Recipient="#{@saml_acs_url}"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore="#{(now-5).iso8601}" NotOnOrAfter="#{(now+60*60).iso8601}"><AudienceRestriction><Audience>#{audience_uri}</Audience></AudienceRestriction></Conditions>#{attribute_statement}<AuthnStatement AuthnInstant="#{now.iso8601}" SessionIndex="_#{session_index}"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatement></Assertion>]
54
61
 
55
62
  digest_value = Base64.encode64(algorithm.digest(assertion)).gsub(/\n/, '')
56
63
 
@@ -115,7 +122,7 @@ class SamlIdpController < SamlIdp::IdpController
115
122
  def idp_make_saml_slo_response(person)
116
123
  attributes = {}
117
124
  if include_subject_in_attributes
118
- attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"] = "you@example.com"
125
+ attributes[email_address_attribute_key] = "you@example.com"
119
126
  end
120
127
  encode_SAML_SLO_Response("you@example.com", attributes: attributes)
121
128
  end
@@ -148,7 +155,7 @@ class SamlIdpController < SamlIdp::IdpController
148
155
  audience_uri = opts[:audience_uri] || (@saml_slo_acs_url && @saml_slo_acs_url[/^(.*?\/\/.*?\/)/, 1])
149
156
  issuer_uri = opts[:issuer_uri] || (defined?(request) && request.url.split("?")[0]) || "http://example.com"
150
157
 
151
- assertion = %[<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_#{session_index}" IssueInstant="#{now.iso8601}" Version="2.0"><Issuer2>#{issuer_uri}</Issuer2><Subject><NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">#{nameID}</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData InResponseTo="#{@saml_slo_request_id}" NotOnOrAfter="#{(now+3*60).iso8601}" Recipient="#{@saml_slo_acs_url}"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore="#{(now-5).iso8601}" NotOnOrAfter="#{(now+60*60).iso8601}"><AudienceRestriction><Audience>#{audience_uri}</Audience></AudienceRestriction></Conditions><AttributeStatement><Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"><AttributeValue>#{nameID}</AttributeValue></Attribute></AttributeStatement><AuthnStatement AuthnInstant="#{now.iso8601}" SessionIndex="_#{session_index}"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatement></Assertion>]
158
+ assertion = %[<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_#{session_index}" IssueInstant="#{now.iso8601}" Version="2.0"><Issuer2>#{issuer_uri}</Issuer2><Subject><NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">#{nameID}</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData InResponseTo="#{@saml_slo_request_id}" NotOnOrAfter="#{(now+3*60).iso8601}" Recipient="#{@saml_slo_acs_url}"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore="#{(now-5).iso8601}" NotOnOrAfter="#{(now+60*60).iso8601}"><AudienceRestriction><Audience>#{audience_uri}</Audience></AudienceRestriction></Conditions><AttributeStatement><Attribute Name="#{email_address_attribute_key}"><AttributeValue>#{nameID}</AttributeValue></Attribute></AttributeStatement><AuthnStatement AuthnInstant="#{now.iso8601}" SessionIndex="_#{session_index}"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatement></Assertion>]
152
159
 
153
160
  digest_value = Base64.encode64(algorithm.digest(assertion)).gsub(/\n/, '')
154
161
 
@@ -189,7 +196,7 @@ class SamlIdpController < SamlIdp::IdpController
189
196
  Destination="#{destination(@saml_slo_acs_url)}"
190
197
  IssueInstant="#{now.iso8601}">
191
198
  <saml:Issuer >#{issuer_uri}</saml:Issuer>
192
- <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">#{nameID}</saml:NameID>
199
+ <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">#{nameID}</saml:NameID>
193
200
  <samlp:SessionIndex>_#{session_index}</samlp:SessionIndex>
194
201
  </samlp:LogoutRequest>]
195
202
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "onelogin/ruby-saml/version"
4
4
 
5
+ attribute_map_resolver = ENV.fetch("ATTRIBUTE_MAP_RESOLVER", "nil")
5
6
  saml_session_index_key = ENV.fetch('SAML_SESSION_INDEX_KEY', ":session_index")
6
7
  use_subject_to_authenticate = ENV.fetch('USE_SUBJECT_TO_AUTHENTICATE')
7
8
  idp_settings_adapter = ENV.fetch('IDP_SETTINGS_ADAPTER', "nil")
@@ -12,7 +13,7 @@ if Rails::VERSION::MAJOR < 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::M
12
13
  gsub_file 'config/secrets.yml', /secret_key_base:.*$/, 'secret_key_base: "8b5889df1fcf03f76c7d66da02d8776bcc85b06bed7d9c592f076d9c8a5455ee6d4beae45986c3c030b40208db5e612f2a6ef8283036a352e3fae83c5eda36be"'
13
14
  end
14
15
 
15
- gem 'devise_saml_authenticatable', path: '../../..'
16
+ gem 'devise_saml_authenticatable', path: File.expand_path("../../..", __FILE__)
16
17
  gem 'ruby-saml', OneLogin::RubySaml::VERSION
17
18
  gem 'thin'
18
19
 
@@ -22,17 +23,26 @@ insert_into_file('Gemfile', after: /\z/) {
22
23
  if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.1")
23
24
  gem 'devise', '~> 3.5'
24
25
  gem 'nokogiri', '~> 1.6.8'
26
+ elsif Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.4")
27
+ gem 'responders', '~> 2.4'
25
28
  end
26
29
  GEMFILE
27
30
  }
31
+ if Rails::VERSION::MAJOR < 6
32
+ # sqlite3 is hard-coded in Rails < 6 to v1.3.x
33
+ gsub_file 'Gemfile', /^gem 'sqlite3'.*$/, "gem 'sqlite3', '~> 1.3.6'"
34
+ end
28
35
 
36
+ template File.expand_path('../attribute_map_resolver.rb.erb', __FILE__), 'app/lib/attribute_map_resolver.rb'
29
37
  template File.expand_path('../idp_settings_adapter.rb.erb', __FILE__), 'app/lib/idp_settings_adapter.rb'
30
38
 
31
- create_file 'config/attribute-map.yml', <<-ATTRIBUTES
39
+ if attribute_map_resolver == "nil"
40
+ create_file 'config/attribute-map.yml', <<-ATTRIBUTES
32
41
  ---
33
42
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": email
34
43
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": name
35
- ATTRIBUTES
44
+ ATTRIBUTES
45
+ end
36
46
 
37
47
  create_file('app/lib/our_saml_failed_callback_handler.rb', <<-CALLBACKHANDLER)
38
48
 
@@ -61,22 +71,6 @@ end
61
71
  READER
62
72
 
63
73
  after_bundle do
64
- generate :controller, 'home', 'index'
65
- insert_into_file('app/controllers/home_controller.rb', after: "class HomeController < ApplicationController\n") {
66
- <<-AUTHENTICATE
67
- before_action :authenticate_user!
68
- AUTHENTICATE
69
- }
70
- insert_into_file('app/views/home/index.html.erb', after: /\z/) {
71
- <<-HOME
72
- <%= current_user.email %> <%= current_user.name %>
73
- <%= form_tag destroy_user_session_path(entity_id: "http://localhost:8020/saml/metadata"), method: :delete do %>
74
- <%= submit_tag "Log out" %>
75
- <% end %>
76
- HOME
77
- }
78
- route "root to: 'home#index'"
79
-
80
74
  # Configure for our SAML IdP
81
75
  generate 'devise:install'
82
76
  gsub_file 'config/initializers/devise.rb', /^end$/, <<-CONFIG
@@ -85,6 +79,9 @@ after_bundle do
85
79
  config.saml_default_user_key = :email
86
80
  config.saml_session_index_key = #{saml_session_index_key}
87
81
 
82
+ if #{attribute_map_resolver}
83
+ config.saml_attribute_map_resolver = #{attribute_map_resolver}
84
+ end
88
85
  config.saml_use_subject = #{use_subject_to_authenticate}
89
86
  config.saml_create_user = true
90
87
  config.saml_update_user = true
@@ -98,11 +95,33 @@ after_bundle do
98
95
  settings.idp_slo_target_url = "http://localhost:8009/saml/logout"
99
96
  settings.idp_sso_target_url = "http://localhost:8009/saml/auth"
100
97
  settings.idp_cert_fingerprint = "9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D"
98
+ settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
101
99
  end
102
100
  end
103
101
  CONFIG
104
102
 
105
- generate :devise, "user", "email:string", "name:string", "session_index:string"
103
+ generate :controller, 'home', 'index'
104
+ insert_into_file('app/controllers/home_controller.rb', after: "class HomeController < ApplicationController\n") {
105
+ <<-AUTHENTICATE
106
+ before_action :authenticate_user!
107
+ AUTHENTICATE
108
+ }
109
+ insert_into_file('app/views/home/index.html.erb', after: /\z/) {
110
+ <<-HOME
111
+ <%= current_user.email %> <%= current_user.name %>
112
+ <%= form_tag destroy_user_session_path(entity_id: "http://localhost:8020/saml/metadata"), method: :delete do %>
113
+ <%= submit_tag "Log out" %>
114
+ <% end %>
115
+ HOME
116
+ }
117
+ route "root to: 'home#index'"
118
+
119
+ if Rails::VERSION::MAJOR < 6
120
+ generate :devise, "user", "email:string", "name:string", "session_index:string"
121
+ else
122
+ # devise seems to add `email` by default in Rails 6
123
+ generate :devise, "user", "name:string", "session_index:string"
124
+ end
106
125
  gsub_file 'app/models/user.rb', /database_authenticatable.*\n.*/, 'saml_authenticatable'
107
126
  route "resources :users, only: [:create]"
108
127
  create_file('app/controllers/users_controller.rb', <<-USERS)
@@ -119,6 +138,9 @@ end
119
138
  rake "db:migrate"
120
139
  rake "db:create", env: "production"
121
140
  rake "db:migrate", env: "production"
141
+
142
+ # Remove any specs so that future RSpec runs don't try to also run these
143
+ run 'rm -rf spec'
122
144
  end
123
145
 
124
146
  create_file 'public/stylesheets/application.css', ''
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_saml_authenticatable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josef Sauter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-05 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise
@@ -55,6 +55,7 @@ files:
55
55
  - app/controllers/devise/saml_sessions_controller.rb
56
56
  - devise_saml_authenticatable.gemspec
57
57
  - lib/devise_saml_authenticatable.rb
58
+ - lib/devise_saml_authenticatable/default_attribute_map_resolver.rb
58
59
  - lib/devise_saml_authenticatable/default_idp_entity_id_reader.rb
59
60
  - lib/devise_saml_authenticatable/exception.rb
60
61
  - lib/devise_saml_authenticatable/logger.rb
@@ -67,6 +68,7 @@ files:
67
68
  - lib/devise_saml_authenticatable/version.rb
68
69
  - rails/init.rb
69
70
  - spec/controllers/devise/saml_sessions_controller_spec.rb
71
+ - spec/devise_saml_authenticatable/default_attribute_map_resolver_spec.rb
70
72
  - spec/devise_saml_authenticatable/default_idp_entity_id_reader_spec.rb
71
73
  - spec/devise_saml_authenticatable/model_spec.rb
72
74
  - spec/devise_saml_authenticatable/saml_config_spec.rb
@@ -79,7 +81,9 @@ files:
79
81
  - spec/support/Gemfile.rails4
80
82
  - spec/support/Gemfile.rails5
81
83
  - spec/support/Gemfile.rails5.1
84
+ - spec/support/Gemfile.rails5.2
82
85
  - spec/support/attribute-map.yml
86
+ - spec/support/attribute_map_resolver.rb.erb
83
87
  - spec/support/idp_settings_adapter.rb.erb
84
88
  - spec/support/idp_template.rb
85
89
  - spec/support/rails_app.rb
@@ -106,13 +110,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
110
  - !ruby/object:Gem::Version
107
111
  version: '0'
108
112
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.4.6
113
+ rubygems_version: 3.0.6
111
114
  signing_key:
112
115
  specification_version: 4
113
116
  summary: SAML Authentication for devise
114
117
  test_files:
115
118
  - spec/controllers/devise/saml_sessions_controller_spec.rb
119
+ - spec/devise_saml_authenticatable/default_attribute_map_resolver_spec.rb
116
120
  - spec/devise_saml_authenticatable/default_idp_entity_id_reader_spec.rb
117
121
  - spec/devise_saml_authenticatable/model_spec.rb
118
122
  - spec/devise_saml_authenticatable/saml_config_spec.rb
@@ -125,7 +129,9 @@ test_files:
125
129
  - spec/support/Gemfile.rails4
126
130
  - spec/support/Gemfile.rails5
127
131
  - spec/support/Gemfile.rails5.1
132
+ - spec/support/Gemfile.rails5.2
128
133
  - spec/support/attribute-map.yml
134
+ - spec/support/attribute_map_resolver.rb.erb
129
135
  - spec/support/idp_settings_adapter.rb.erb
130
136
  - spec/support/idp_template.rb
131
137
  - spec/support/rails_app.rb
@@ -133,4 +139,3 @@ test_files:
133
139
  - spec/support/saml_idp-saml_slo_post.html.erb
134
140
  - spec/support/saml_idp_controller.rb.erb
135
141
  - spec/support/sp_template.rb
136
- has_rdoc: