devise_saml_authenticatable 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 269c0505d92b49c3b9a79d1b8aece87533018b10
4
- data.tar.gz: 259f7e012808aabe3ab06e854a01deab8959843a
3
+ metadata.gz: 9a26db022c02d24566654e1d965c374a0e3b3380
4
+ data.tar.gz: 1341712900741f3c7326ddb7f099468bbc1d1066
5
5
  SHA512:
6
- metadata.gz: 83a89cbe087accbcf239e047027188a35793c9cdcb3198fd207edeb95652bb6e8957ef8e0aeaa9b919f01cbb91677bf4c5ade49fae0a85b86cf95edc4b09592b
7
- data.tar.gz: 230f5490186a0853cd63f401b390afa29129b8f103de04cbb64a734274edd88de9467030784122cccdc743fbd5eb7babf75ad3635be5b51d2a5af467d4e17b1f
6
+ metadata.gz: 9ee3d6d7075cccdb05b87c8cea6e7f9feab58d3f2a0ae4fc1cbc9d6e679b82d1c59e675195c520867903808070cc8e9fb49ff99028b7816f039e029f0d455a6a
7
+ data.tar.gz: 9ea8211cda495a8347e5e2672214e5fc8448e232ca1d961645dde9f22b18eaf9bd6bcf8e6876dea110cbe2292a8d01fdc303039629cbe781f3901a15ab73efc8
@@ -32,6 +32,10 @@ matrix:
32
32
  - rvm: "2.1.10"
33
33
  gemfile: spec/support/Gemfile.ruby-saml-1.3
34
34
 
35
+ before_install:
36
+ # update bundler to avoid https://github.com/travis-ci/travis-ci/issues/5239
37
+ - gem install bundler
38
+
35
39
  script:
36
40
  - bundle exec rake
37
41
 
data/README.md CHANGED
@@ -69,8 +69,9 @@ In `config/initializers/devise.rb`:
69
69
  # and implements a #handle method. This method can then redirect the user, return error messages, etc.
70
70
  # config.saml_failed_callback = nil
71
71
 
72
- # Configure with your SAML settings (see [ruby-saml][] for more information).
72
+ # Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
73
73
  config.saml_configure do |settings|
74
+ # assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
74
75
  settings.assertion_consumer_service_url = "http://localhost:3000/users/saml/auth"
75
76
  settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
76
77
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
@@ -159,6 +160,7 @@ class IdPSettingsAdapter
159
160
  end
160
161
  end
161
162
  ```
163
+ Settings specified in the adapter will override settings in `config/initializers/devise.rb`. This is useful for establishing common settings or defaults across all IdPs.
162
164
 
163
165
  Detecting the entity ID passed to the `settings` method is done by `config.idp_entity_id_reader`.
164
166
 
@@ -192,10 +194,12 @@ Logout requests from the IDP are supported by the `idp_sign_out` endpoint. Dire
192
194
 
193
195
  `saml_session_index_key` must be configured to support this feature.
194
196
 
195
- ## Signing and Encrypting Authentication Requests
197
+ ## Signing and Encrypting Authentication Requests and Assertions
196
198
 
197
199
  ruby-saml 1.0.0 supports signature and decrypt. The only requirement is to set the public certificate and the private key. For more information, see [the ruby-saml documentation](https://github.com/onelogin/ruby-saml#signing).
198
200
 
201
+ If you have multiple IdPs, the certificate and private key must be in the shared settings in `config/initializers/devise.rb`.
202
+
199
203
  ## Thanks
200
204
 
201
205
  The continued maintenance of this gem could not have been possible without the hard work of [Adam Stegman](https://github.com/adamstegman) and [Mitch Lindsay](https://github.com/mitch-lindsay). Thank you guys for keeping this project alive.
@@ -53,8 +53,9 @@ class Devise::SamlSessionsController < Devise::SessionsController
53
53
 
54
54
  # Override devise to send user to IdP logout for SLO
55
55
  def after_sign_out_path_for(_)
56
+ idp_entity_id = get_idp_entity_id(params)
56
57
  request = OneLogin::RubySaml::Logoutrequest.new
57
- request.create(saml_config)
58
+ request.create(saml_config(idp_entity_id))
58
59
  end
59
60
 
60
61
  def generate_idp_logout_response(saml_config, logout_request_id)
@@ -7,6 +7,7 @@ Gem::Specification.new do |gem|
7
7
  gem.description = %q{SAML Authentication for devise}
8
8
  gem.summary = %q{SAML Authentication for devise }
9
9
  gem.homepage = ""
10
+ gem.license = "MIT"
10
11
 
11
12
  gem.files = `git ls-files`.split($\)
12
13
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -94,7 +94,7 @@ module Devise
94
94
  end
95
95
 
96
96
  # Proc that is called if Devise.saml_update_user and/or Devise.saml_create_user are true.
97
- # Recieves the user object, saml_response and auth_value, and defines how the object's values are
97
+ # Receives the user object, saml_response and auth_value, and defines how the object's values are
98
98
  # updated with regards to the SAML response. See saml_default_update_resource_hook for an example.
99
99
  mattr_accessor :saml_update_resource_hook
100
100
  @@saml_update_resource_hook = @@saml_default_update_resource_hook
@@ -107,7 +107,7 @@ module Devise
107
107
  end
108
108
 
109
109
  # Proc that is called to resolve the saml_response and auth_value into the correct user object.
110
- # Recieves a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
110
+ # Receives a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
111
111
  # one instance of the provided model that is the matched account, or nil if none exists.
112
112
  # See saml_default_resource_locator above for an example.
113
113
  mattr_accessor :saml_resource_locator
@@ -4,11 +4,13 @@ module DeviseSamlAuthenticatable
4
4
  if params[:SAMLRequest]
5
5
  OneLogin::RubySaml::SloLogoutrequest.new(
6
6
  params[:SAMLRequest],
7
+ settings: Devise.saml_config,
7
8
  allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
8
9
  ).issuer
9
10
  elsif params[:SAMLResponse]
10
11
  OneLogin::RubySaml::Response.new(
11
12
  params[:SAMLResponse],
13
+ settings: Devise.saml_config,
12
14
  allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
13
15
  ).issuers.first
14
16
  end
@@ -8,6 +8,7 @@ module Devise
8
8
  if params[:SAMLResponse]
9
9
  OneLogin::RubySaml::Response.new(
10
10
  params[:SAMLResponse],
11
+ settings: Devise.saml_config,
11
12
  allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
12
13
  )
13
14
  else
@@ -1,3 +1,3 @@
1
1
  module DeviseSamlAuthenticatable
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -66,6 +66,7 @@ describe Devise::SamlSessionsController, type: :controller do
66
66
  it "uses the DefaultIdpEntityIdReader" do
67
67
  expect(DeviseSamlAuthenticatable::DefaultIdpEntityIdReader).to receive(:entity_id)
68
68
  do_get
69
+ expect(idp_providers_adapter).to have_received(:settings).with(nil)
69
70
  end
70
71
 
71
72
  context "with a relay_state lambda defined" do
@@ -104,6 +105,7 @@ describe Devise::SamlSessionsController, type: :controller do
104
105
 
105
106
  it "redirects to the associated IdP SSO target url" do
106
107
  do_get
108
+ expect(idp_providers_adapter).to have_received(:settings).with("http://www.example.com")
107
109
  expect(response).to redirect_to(%r(\Ahttp://idp_sso_url\?SAMLRequest=))
108
110
  end
109
111
  end
@@ -147,10 +149,57 @@ describe Devise::SamlSessionsController, type: :controller do
147
149
  end
148
150
 
149
151
  describe '#destroy' do
150
- it 'signs out and redirects to the IdP' do
151
- expect(controller).to receive(:sign_out)
152
- delete :destroy
153
- expect(response).to redirect_to(%r(\Ahttp://localhost:8009/saml/logout\?SAMLRequest=))
152
+ context "when using the default saml config" do
153
+ it 'signs out and redirects to the IdP' do
154
+ expect(controller).to receive(:sign_out)
155
+ delete :destroy
156
+ expect(response).to redirect_to(%r(\Ahttp://localhost:8009/saml/logout\?SAMLRequest=))
157
+ end
158
+ end
159
+
160
+ context "with a specified idp" do
161
+ before do
162
+ Devise.idp_settings_adapter = idp_providers_adapter
163
+ end
164
+
165
+ it "redirects to the associated IdP SSO target url" do
166
+ expect(controller).to receive(:sign_out)
167
+ expect(DeviseSamlAuthenticatable::DefaultIdpEntityIdReader).to receive(:entity_id)
168
+ delete :destroy
169
+ expect(response).to redirect_to(%r(\Ahttp://idp_slo_url\?SAMLRequest=))
170
+ end
171
+
172
+ context "with a specified idp entity id reader" do
173
+ class OurIdpEntityIdReader
174
+ def self.entity_id(params)
175
+ params[:entity_id]
176
+ end
177
+ end
178
+
179
+ subject(:do_delete) {
180
+ if Rails::VERSION::MAJOR > 4
181
+ delete :destroy, params: {entity_id: "http://www.example.com"}
182
+ else
183
+ delete :destroy, entity_id: "http://www.example.com"
184
+ end
185
+ }
186
+
187
+ before do
188
+ @default_reader = Devise.idp_entity_id_reader
189
+ Devise.idp_entity_id_reader = OurIdpEntityIdReader # which will have some different behavior
190
+ end
191
+
192
+ after do
193
+ Devise.idp_entity_id_reader = @default_reader
194
+ end
195
+
196
+ it "redirects to the associated IdP SLO target url" do
197
+ expect(controller).to receive(:sign_out)
198
+ do_delete
199
+ expect(idp_providers_adapter).to have_received(:settings).with("http://www.example.com")
200
+ expect(response).to redirect_to(%r(\Ahttp://idp_slo_url\?SAMLRequest=))
201
+ end
202
+ end
154
203
  end
155
204
  end
156
205
 
@@ -138,7 +138,6 @@ describe "SAML Authentication", type: :feature do
138
138
  end
139
139
 
140
140
  context "when the idp_settings_adapter key is set" do
141
-
142
141
  before(:each) do
143
142
  create_app('idp', 'INCLUDE_SUBJECT_IN_ATTRIBUTES' => "false")
144
143
  create_app('sp', 'USE_SUBJECT_TO_AUTHENTICATE' => "true", 'IDP_SETTINGS_ADAPTER' => "IdpSettingsAdapter", 'IDP_ENTITY_ID_READER' => "OurEntityIdReader")
@@ -156,7 +155,24 @@ describe "SAML Authentication", type: :feature do
156
155
  create_user("you@example.com")
157
156
 
158
157
  visit 'http://localhost:8020/users/saml/sign_in/?entity_id=http%3A%2F%2Flocalhost%3A8020%2Fsaml%2Fmetadata'
159
- expect(current_url).to match(%r(\Ahttp://www.example.com/\?SAMLRequest=))
158
+ expect(current_url).to match(%r(\Ahttp://www.example.com/sso\?SAMLRequest=))
159
+ end
160
+
161
+ it "logs a user out of the IdP via the SP" do
162
+ sign_in
163
+
164
+ # prove user is still signed in
165
+ visit 'http://localhost:8020/'
166
+ expect(page).to have_content("you@example.com")
167
+ expect(current_url).to eq("http://localhost:8020/")
168
+
169
+ click_on "Log out"
170
+ #confirm the logout response redirected to the SP which in turn attempted to sign th e
171
+ expect(current_url).to match(%r(\Ahttp://www.example.com/slo\?SAMLRequest=))
172
+
173
+ # prove user is now signed out
174
+ visit 'http://localhost:8020/users/saml/sign_in/?entity_id=http%3A%2F%2Flocalhost%3A8020%2Fsaml%2Fmetadata'
175
+ expect(current_url).to match(%r(\Ahttp://www.example.com/sso\?SAMLRequest=))
160
176
  end
161
177
  end
162
178
 
@@ -4,7 +4,6 @@ source 'https://rubygems.org'
4
4
  gemspec path: '../..'
5
5
 
6
6
  group :test do
7
- gem 'rake'
8
7
  gem 'rspec', '~> 3.0'
9
8
  gem 'rails', '~> 4.0'
10
9
  gem 'rspec-rails'
@@ -16,7 +15,15 @@ group :test do
16
15
  if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.0")
17
16
  gem 'addressable', '~> 2.4.0'
18
17
  gem 'mime-types', '~> 2.99'
18
+ gem 'public_suffix', '~> 1.4.6'
19
+ gem 'rake', '~> 12.2.0'
20
+ elsif Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.1")
21
+ gem 'public_suffix', '~> 2.0.5'
22
+ gem 'rake'
23
+ else
24
+ gem 'rake'
19
25
  end
26
+
20
27
  if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.1")
21
28
  gem 'devise', '~> 3.5'
22
29
  gem 'nokogiri', '~> 1.6.8'
@@ -14,11 +14,9 @@ group :test do
14
14
  gem 'poltergeist'
15
15
 
16
16
  # Lock down versions of gems for older versions of Ruby
17
- if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.0")
18
- gem 'mime-types', '~> 2.99'
19
- end
20
17
  if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new("2.1")
21
18
  gem 'devise', '~> 3.5'
19
+ gem 'public_suffix', '~> 2.0.5'
22
20
  gem 'nokogiri', '~> 1.6.8'
23
21
  end
24
22
  end
@@ -8,8 +8,8 @@ class IdpSettingsAdapter
8
8
  issuer: "sp_issuer",
9
9
  idp_entity_id: "http://localhost:8020/saml/metadata",
10
10
  authn_context: "",
11
- idp_slo_target_url: "http://www.example.com",
12
- idp_sso_target_url: "http://www.example.com",
11
+ idp_slo_target_url: "http://www.example.com/slo",
12
+ idp_sso_target_url: "http://www.example.com/sso",
13
13
  idp_cert: "idp_cert"
14
14
  }
15
15
  else
@@ -68,7 +68,7 @@ after_bundle do
68
68
  insert_into_file('app/views/home/index.html.erb', after: /\z/) {
69
69
  <<-HOME
70
70
  <%= current_user.email %> <%= current_user.name %>
71
- <%= form_tag destroy_user_session_path, method: :delete do %>
71
+ <%= form_tag destroy_user_session_path(entity_id: "http://localhost:8020/saml/metadata"), method: :delete do %>
72
72
  <%= submit_tag "Log out" %>
73
73
  <% end %>
74
74
  HOME
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.3.2
4
+ version: 1.4.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: 2017-05-22 00:00:00.000000000 Z
11
+ date: 2018-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise
@@ -85,7 +85,8 @@ files:
85
85
  - spec/support/saml_idp_controller.rb.erb
86
86
  - spec/support/sp_template.rb
87
87
  homepage: ''
88
- licenses: []
88
+ licenses:
89
+ - MIT
89
90
  metadata: {}
90
91
  post_install_message:
91
92
  rdoc_options: []