devise_saml_authenticatable 1.3.2 → 1.6.1
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.
- checksums.yaml +5 -5
- data/.gitignore +0 -2
- data/.travis.yml +29 -22
- data/Gemfile +2 -2
- data/README.md +105 -32
- data/app/controllers/devise/saml_sessions_controller.rb +35 -7
- data/devise_saml_authenticatable.gemspec +2 -1
- data/lib/devise_saml_authenticatable.rb +27 -2
- data/lib/devise_saml_authenticatable/default_attribute_map_resolver.rb +26 -0
- data/lib/devise_saml_authenticatable/default_idp_entity_id_reader.rb +2 -0
- data/lib/devise_saml_authenticatable/exception.rb +1 -1
- data/lib/devise_saml_authenticatable/model.rb +16 -18
- data/lib/devise_saml_authenticatable/routes.rb +17 -6
- data/lib/devise_saml_authenticatable/saml_mapped_attributes.rb +15 -2
- data/lib/devise_saml_authenticatable/strategy.rb +1 -0
- data/lib/devise_saml_authenticatable/version.rb +1 -1
- data/spec/controllers/devise/saml_sessions_controller_spec.rb +118 -11
- data/spec/devise_saml_authenticatable/default_attribute_map_resolver_spec.rb +58 -0
- data/spec/devise_saml_authenticatable/model_spec.rb +68 -7
- data/spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb +50 -0
- data/spec/features/saml_authentication_spec.rb +45 -21
- data/spec/rails_helper.rb +6 -2
- data/spec/routes/routes_spec.rb +102 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/Gemfile.rails4 +23 -6
- data/spec/support/Gemfile.rails5 +13 -2
- data/spec/support/Gemfile.rails5.1 +25 -0
- data/spec/support/Gemfile.rails5.2 +25 -0
- data/spec/support/attribute-map.yml +12 -0
- data/spec/support/attribute_map_resolver.rb.erb +14 -0
- data/spec/support/idp_settings_adapter.rb.erb +5 -5
- data/spec/support/idp_template.rb +6 -2
- data/spec/support/rails_app.rb +75 -17
- data/spec/support/saml_idp_controller.rb.erb +13 -6
- data/spec/support/sp_template.rb +45 -21
- metadata +25 -13
- data/spec/support/Gemfile.ruby-saml-1.3 +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d3ca38cfe51cdf71fc8a264de868fc285bfa413307aa4798e097fbf88e85020d
|
4
|
+
data.tar.gz: 2371ef1371e29547b4eb9681066fa43f0b6d39236b7df8676236bf13678e2d01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 872bfb214a00504735d9183d169e4119ebb9c6ae3129de729be642f39c4675b57040bb1c9d46899e73d534aa82d7ac9291c425109c10eaeb290831480e7976ab
|
7
|
+
data.tar.gz: 3269ef293937aef443afa9a325acc0addf027c3ad7421865a9ebe1554d7215461767ffe9e34cd4cc2bf8edbae831e7e342dd3c47245d57209d8ddd820a128212
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,45 +1,52 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- "1.9.3"
|
4
3
|
- "2.0.0"
|
5
4
|
- "2.1.10"
|
6
|
-
- "2.2.
|
7
|
-
- "2.3.
|
8
|
-
- "2.4.
|
5
|
+
- "2.2.10"
|
6
|
+
- "2.3.8"
|
7
|
+
- "2.4.10"
|
8
|
+
- "2.5.8"
|
9
|
+
- "2.6.6"
|
10
|
+
- "2.7.1"
|
9
11
|
gemfile:
|
10
12
|
- Gemfile
|
13
|
+
- spec/support/Gemfile.rails5.2
|
14
|
+
- spec/support/Gemfile.rails5.1
|
11
15
|
- spec/support/Gemfile.rails5
|
12
16
|
- spec/support/Gemfile.rails4
|
13
|
-
- spec/support/Gemfile.ruby-saml-1.3
|
14
17
|
matrix:
|
15
18
|
allow_failures:
|
16
|
-
- rvm: "1.9.3"
|
17
|
-
gemfile: Gemfile
|
18
|
-
- rvm: "1.9.3"
|
19
|
-
gemfile: spec/support/Gemfile.rails5
|
20
|
-
- rvm: "1.9.3"
|
21
|
-
gemfile: spec/support/Gemfile.ruby-saml-1.3
|
22
19
|
- rvm: "2.0.0"
|
23
20
|
gemfile: Gemfile
|
24
21
|
- rvm: "2.0.0"
|
25
22
|
gemfile: spec/support/Gemfile.rails5
|
26
23
|
- rvm: "2.0.0"
|
27
|
-
gemfile: spec/support/Gemfile.
|
24
|
+
gemfile: spec/support/Gemfile.rails5.1
|
25
|
+
- rvm: "2.0.0"
|
26
|
+
gemfile: spec/support/Gemfile.rails5.2
|
28
27
|
- rvm: "2.1.10"
|
29
28
|
gemfile: Gemfile
|
30
29
|
- rvm: "2.1.10"
|
31
30
|
gemfile: spec/support/Gemfile.rails5
|
32
31
|
- rvm: "2.1.10"
|
33
|
-
gemfile: spec/support/Gemfile.
|
32
|
+
gemfile: spec/support/Gemfile.rails5.1
|
33
|
+
- rvm: "2.1.10"
|
34
|
+
gemfile: spec/support/Gemfile.rails5.2
|
35
|
+
- rvm: "2.2.10"
|
36
|
+
gemfile: Gemfile
|
37
|
+
- rvm: "2.2.10"
|
38
|
+
gemfile: spec/support/Gemfile.rails5.2
|
39
|
+
- rvm: "2.3.8"
|
40
|
+
gemfile: Gemfile
|
41
|
+
- rvm: "2.4.10"
|
42
|
+
gemfile: Gemfile
|
43
|
+
- rvm: "2.6.6"
|
44
|
+
gemfile: spec/support/Gemfile.rails4
|
45
|
+
- rvm: "2.7.1"
|
46
|
+
gemfile: spec/support/Gemfile.rails4
|
47
|
+
|
48
|
+
before_install:
|
49
|
+
- command -v bundle || gem install bundler -v '~> 1.17.3'
|
34
50
|
|
35
51
|
script:
|
36
52
|
- bundle exec rake
|
37
|
-
|
38
|
-
notifications:
|
39
|
-
hipchat:
|
40
|
-
rooms:
|
41
|
-
secure: cuDak5a6fBeg+sp61COqxQfzdcFEsjwCqtwvCISso0RNh5SR8v+uVYKcA8rlK+GE1l9uR7tLRHeHF3ZmzvFSOat07NvpScvjZXi+OSpWlc6rwQ6Pl6bBP6gu6sREiKVe0eT/uGrvJloyWKZaXIhiiBzQ+ZERx/ssGA9WMmNkhlwy1OgGnPNurNNHZLBjEZn1V6kdyxiXx6QPASNpjNEgN1G8dUh3qzcWUGVQGNZSJk65A6ie1MveNyecTjDhw+ADBU8nS28Ja4y6ohRm4FzofSgespYrvfygIZ5rYF0HPMj5FW1ZDWtM5355ojCk8RLT+ZkuhssCn1OJk7ogaOVjnYcOFRxEfpu3eIbjtMmUz3j4umatFqbgas+6SXMVIPkr5HUoTrP8HNFssIpcEBOnPwAF8QCpx+daHc0r2cc8lGuXhtJfpW0P2F0dmwJNiQ7//nz2y2xs84x4Gb7MV9tEDYp0FqEClMuFBkPNizBljarm04PkiLSrqvR52aMDfQz7YAX2oXAvFjPzI1GC0K8x7xX8TuHT9yuHy7fI+rUSNivZYLKO+IEZqPPDdJpXISUbVwanZoNvmQYk5PZV21MfDSGwQrz8eO/uFiAblj18yIlNbAfb2hdZDVYsm4EvWxELJtfaTxgrj6M3Y3m/KbCbCoDp+2jE307M2rxL0Gum2gk=
|
42
|
-
template:
|
43
|
-
- '%{repository}<a href="%{build_url}">#%{build_number}</a> (%{branch} - <a href="%{compare_url}">%{commit}</a> : %{author}): %{message}'
|
44
|
-
format: html
|
45
|
-
on_pull_requests: true
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -6,19 +6,20 @@ It uses [ruby-saml][] to handle all SAML-related stuff.
|
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
-
Add this
|
9
|
+
Add this gem to your application's Gemfile:
|
10
10
|
|
11
|
-
|
11
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
12
|
+
gem "devise_saml_authenticatable", github: "apokalipto/devise_saml_authenticatable"
|
12
13
|
|
13
14
|
And then execute:
|
14
15
|
|
15
16
|
$ bundle
|
16
17
|
|
17
|
-
|
18
|
+
## Usage
|
18
19
|
|
19
|
-
|
20
|
+
Follow the [normal devise installation process](https://github.com/plataformatec/devise/tree/master#getting-started). The controller filters and helpers are unchanged from normal devise usage.
|
20
21
|
|
21
|
-
|
22
|
+
### Configuring Models
|
22
23
|
|
23
24
|
In `app/models/<YOUR_MODEL>.rb` set the `:saml_authenticatable` strategy.
|
24
25
|
|
@@ -32,6 +33,37 @@ In the example the model is `user.rb`:
|
|
32
33
|
end
|
33
34
|
```
|
34
35
|
|
36
|
+
### Configuring routes
|
37
|
+
|
38
|
+
In `config/routes.rb` add `devise_for` to set up helper methods and routes:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
devise_for :users
|
42
|
+
```
|
43
|
+
|
44
|
+
The named routes can be customized in the initializer config file.
|
45
|
+
|
46
|
+
### Configuring the IdP
|
47
|
+
|
48
|
+
An extra step in SAML SSO setup is adding your application to your identity provider. The required setup is specific to each IdP, but we have some examples in [our wiki](https://github.com/apokalipto/devise_saml_authenticatable/wiki). You'll need to tell your IdP how to send requests and responses to your application.
|
49
|
+
|
50
|
+
- Creating a new session: `/users/saml/auth`
|
51
|
+
- IdPs may call this the "consumer," "recipient," "destination," or even "single sign-on." This is where they send a SAML response for an authenticated user.
|
52
|
+
- Metadata: `/users/saml/metadata`
|
53
|
+
- IdPs may call this the "audience."
|
54
|
+
- Single Logout: `/users/saml/idp_sign_out`
|
55
|
+
- if desired, you can ask the IdP to send a Logout request to this endpoint to sign the user out of your application when they sign out of the IdP itself.
|
56
|
+
|
57
|
+
Your IdP should give you some information you need to configure in [ruby-saml](https://github.com/onelogin/ruby-saml), as in the next section:
|
58
|
+
|
59
|
+
- Issuer (`idp_entity_id`)
|
60
|
+
- SSO endpoint (`idp_sso_target_url`)
|
61
|
+
- SLO endpoint (`idp_slo_target_url`)
|
62
|
+
- Certificate fingerprint (`idp_cert_fingerprint`) and algorithm (`idp_cert_fingerprint_algorithm`)
|
63
|
+
- Or the certificate itself (`idp_cert`)
|
64
|
+
|
65
|
+
### Configuring handling of IdP requests and responses
|
66
|
+
|
35
67
|
In `config/initializers/devise.rb`:
|
36
68
|
|
37
69
|
```ruby
|
@@ -69,8 +101,19 @@ In `config/initializers/devise.rb`:
|
|
69
101
|
# and implements a #handle method. This method can then redirect the user, return error messages, etc.
|
70
102
|
# config.saml_failed_callback = nil
|
71
103
|
|
72
|
-
#
|
104
|
+
# You can customize the named routes generated in case of named route collisions with
|
105
|
+
# other Devise modules or libraries. Set the saml_route_helper_prefix to a string that will
|
106
|
+
# be appended to the named route.
|
107
|
+
# If saml_route_helper_prefix = 'saml' then the new_user_session route becomes new_saml_user_session
|
108
|
+
# config.saml_route_helper_prefix = 'saml'
|
109
|
+
|
110
|
+
# You can add allowance for clock drift between the sp and idp.
|
111
|
+
# This is a time in seconds.
|
112
|
+
# config.allowed_clock_drift_in_seconds = 0
|
113
|
+
|
114
|
+
# Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
|
73
115
|
config.saml_configure do |settings|
|
116
|
+
# 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
117
|
settings.assertion_consumer_service_url = "http://localhost:3000/users/saml/auth"
|
75
118
|
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
76
119
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
@@ -78,29 +121,32 @@ In `config/initializers/devise.rb`:
|
|
78
121
|
settings.authn_context = ""
|
79
122
|
settings.idp_slo_target_url = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
|
80
123
|
settings.idp_sso_target_url = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
|
81
|
-
settings.
|
82
|
-
|
83
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
84
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
85
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
86
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
87
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
88
|
-
1111111111111_______IDP_CERTIFICATE________111111111111111111111
|
89
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
90
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
91
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
92
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
93
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
94
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
95
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
96
|
-
111111111111111111
|
97
|
-
-----END CERTIFICATE-----
|
98
|
-
CERT
|
124
|
+
settings.idp_cert_fingerprint = "00:A1:2B:3C:44:55:6F:A7:88:CC:DD:EE:22:33:44:55:D6:77:8F:99"
|
125
|
+
settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
|
99
126
|
end
|
100
127
|
end
|
101
128
|
```
|
102
129
|
|
103
|
-
|
130
|
+
#### Attributes
|
131
|
+
|
132
|
+
There are two ways to map SAML attributes to User attributes:
|
133
|
+
|
134
|
+
- [initializer](#attribute-map-initializer)
|
135
|
+
- [config file](#attribute-map-config-file)
|
136
|
+
|
137
|
+
The attribute mappings are very dependent on the way the IdP encodes the attributes.
|
138
|
+
In these examples the attributes are given in URN style.
|
139
|
+
Other IdPs might provide them as OID's, or by other means.
|
140
|
+
|
141
|
+
You are now ready to test it against an IdP.
|
142
|
+
|
143
|
+
When the user visits `/users/saml/sign_in` they will be redirected to the login page of the IdP.
|
144
|
+
|
145
|
+
Upon successful login the user is redirected to the Devise `user_root_path`.
|
146
|
+
|
147
|
+
##### Attribute map config file
|
148
|
+
|
149
|
+
Create a YAML file (`config/attribute-map.yml`) that maps SAML attributes with your model's fields:
|
104
150
|
|
105
151
|
```yaml
|
106
152
|
# attribute-map.yml
|
@@ -111,15 +157,39 @@ In the config directory, create a YAML file (`attribute-map.yml`) that maps SAML
|
|
111
157
|
"urn:mace:dir:attribute-def:givenName": "name"
|
112
158
|
```
|
113
159
|
|
114
|
-
|
115
|
-
In this example the attributes are given in URN style.
|
116
|
-
Other IdPs might provide them as OID's, or by other means.
|
160
|
+
##### Attribute map initializer
|
117
161
|
|
118
|
-
|
162
|
+
In `config/initializers/devise.rb` (see above), add an attribute map resolver.
|
163
|
+
The resolver gets the [SAML response from the IdP](https://github.com/onelogin/ruby-saml/blob/master/lib/onelogin/ruby-saml/response.rb) so it can decide which attribute map to load.
|
164
|
+
If you only have one IdP, you can use the config file above, or just return a single hash.
|
119
165
|
|
120
|
-
|
166
|
+
```ruby
|
167
|
+
# config/initializers/devise.rb
|
168
|
+
Devise.setup do |config|
|
169
|
+
...
|
170
|
+
# ==> Configuration for :saml_authenticatable
|
121
171
|
|
122
|
-
|
172
|
+
config.saml_attribute_map_resolver = MyAttributeMapResolver
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
# app/lib/my_attribute_map_resolver
|
178
|
+
class MyAttributeMapResolver < DeviseSamlAuthenticatable::DefaultAttributeMapResolver
|
179
|
+
def attribute_map
|
180
|
+
issuer = saml_response.issuers.first
|
181
|
+
case issuer
|
182
|
+
when "idp_entity_id"
|
183
|
+
{
|
184
|
+
"urn:mace:dir:attribute-def:uid" => "user_name",
|
185
|
+
"urn:mace:dir:attribute-def:email" => "email",
|
186
|
+
"urn:mace:dir:attribute-def:name" => "last_name",
|
187
|
+
"urn:mace:dir:attribute-def:givenName" => "name",
|
188
|
+
}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
```
|
123
193
|
|
124
194
|
## Supporting Multiple IdPs
|
125
195
|
|
@@ -159,6 +229,7 @@ class IdPSettingsAdapter
|
|
159
229
|
end
|
160
230
|
end
|
161
231
|
```
|
232
|
+
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
233
|
|
163
234
|
Detecting the entity ID passed to the `settings` method is done by `config.idp_entity_id_reader`.
|
164
235
|
|
@@ -192,10 +263,12 @@ Logout requests from the IDP are supported by the `idp_sign_out` endpoint. Dire
|
|
192
263
|
|
193
264
|
`saml_session_index_key` must be configured to support this feature.
|
194
265
|
|
195
|
-
## Signing and Encrypting Authentication Requests
|
266
|
+
## Signing and Encrypting Authentication Requests and Assertions
|
196
267
|
|
197
268
|
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
269
|
|
270
|
+
If you have multiple IdPs, the certificate and private key must be in the shared settings in `config/initializers/devise.rb`.
|
271
|
+
|
199
272
|
## Thanks
|
200
273
|
|
201
274
|
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.
|
@@ -5,8 +5,10 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
5
5
|
unloadable if Rails::VERSION::MAJOR < 4
|
6
6
|
if Rails::VERSION::MAJOR < 5
|
7
7
|
skip_before_filter :verify_authenticity_token
|
8
|
+
prepend_before_filter :store_info_for_sp_initiated_logout, only: :destroy
|
8
9
|
else
|
9
10
|
skip_before_action :verify_authenticity_token, raise: false
|
11
|
+
prepend_before_action :store_info_for_sp_initiated_logout, only: :destroy
|
10
12
|
end
|
11
13
|
|
12
14
|
def new
|
@@ -18,8 +20,9 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def metadata
|
23
|
+
idp_entity_id = params[:idp_entity_id]
|
21
24
|
meta = OneLogin::RubySaml::Metadata.new
|
22
|
-
render :xml => meta.generate(saml_config)
|
25
|
+
render :xml => meta.generate(saml_config(idp_entity_id))
|
23
26
|
end
|
24
27
|
|
25
28
|
def idp_sign_out
|
@@ -30,16 +33,16 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
30
33
|
|
31
34
|
redirect_to generate_idp_logout_response(saml_config, logout_request.id)
|
32
35
|
elsif params[:SAMLResponse]
|
33
|
-
#Currently Devise handles the session invalidation when the request is made.
|
34
|
-
#To support a true SP initiated logout response, the request ID would have to be tracked and session invalidated
|
35
|
-
#based on that.
|
36
|
+
# Currently Devise handles the session invalidation when the request is made.
|
37
|
+
# To support a true SP initiated logout response, the request ID would have to be tracked and session invalidated
|
38
|
+
# based on that.
|
36
39
|
if Devise.saml_sign_out_success_url
|
37
40
|
redirect_to Devise.saml_sign_out_success_url
|
38
41
|
else
|
39
42
|
redirect_to action: :new
|
40
43
|
end
|
41
44
|
else
|
42
|
-
head
|
45
|
+
head 500
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
@@ -51,13 +54,38 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
# For non transient name ID, save info to identify user for logout purpose
|
58
|
+
# before that user's session got destroyed. These info are used in the
|
59
|
+
# `after_sign_out_path_for` method below.
|
60
|
+
def store_info_for_sp_initiated_logout
|
61
|
+
return if Devise.saml_config.name_identifier_format == "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
62
|
+
@name_identifier_value_for_sp_initiated_logout = Devise.saml_name_identifier_retriever.call(current_user)
|
63
|
+
@sessionindex_for_sp_initiated_logout = current_user.public_send(Devise.saml_session_index_key) if Devise.saml_session_index_key
|
64
|
+
end
|
65
|
+
|
54
66
|
# Override devise to send user to IdP logout for SLO
|
55
67
|
def after_sign_out_path_for(_)
|
68
|
+
idp_entity_id = get_idp_entity_id(params)
|
56
69
|
request = OneLogin::RubySaml::Logoutrequest.new
|
57
|
-
|
70
|
+
saml_settings = saml_config(idp_entity_id).dup
|
71
|
+
|
72
|
+
# Add attributes to saml_settings which will later be used to create the SP
|
73
|
+
# initiated logout request
|
74
|
+
unless Devise.saml_config.name_identifier_format == 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
|
75
|
+
saml_settings.name_identifier_value = @name_identifier_value_for_sp_initiated_logout
|
76
|
+
saml_settings.sessionindex = @sessionindex_for_sp_initiated_logout
|
77
|
+
end
|
78
|
+
|
79
|
+
request.create(saml_settings)
|
58
80
|
end
|
59
81
|
|
60
82
|
def generate_idp_logout_response(saml_config, logout_request_id)
|
61
|
-
|
83
|
+
|
84
|
+
params = {}
|
85
|
+
if relay_state
|
86
|
+
params[:RelayState] = relay_state
|
87
|
+
end
|
88
|
+
|
89
|
+
OneLogin::RubySaml::SloLogoutresponse.new.create(saml_config, logout_request_id, nil, params)
|
62
90
|
end
|
63
91
|
end
|
@@ -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) }
|
@@ -17,5 +18,5 @@ Gem::Specification.new do |gem|
|
|
17
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
19
|
|
19
20
|
gem.add_dependency("devise","> 2.0.0")
|
20
|
-
gem.add_dependency("ruby-saml","~> 1.
|
21
|
+
gem.add_dependency("ruby-saml","~> 1.7")
|
21
22
|
end
|
@@ -5,6 +5,7 @@ require "devise_saml_authenticatable/exception"
|
|
5
5
|
require "devise_saml_authenticatable/logger"
|
6
6
|
require "devise_saml_authenticatable/routes"
|
7
7
|
require "devise_saml_authenticatable/saml_config"
|
8
|
+
require "devise_saml_authenticatable/default_attribute_map_resolver"
|
8
9
|
require "devise_saml_authenticatable/default_idp_entity_id_reader"
|
9
10
|
|
10
11
|
begin
|
@@ -19,6 +20,10 @@ end
|
|
19
20
|
|
20
21
|
# Get saml information from config/saml.yml now
|
21
22
|
module Devise
|
23
|
+
# Allow route customization to avoid collision
|
24
|
+
mattr_accessor :saml_route_helper_prefix
|
25
|
+
@@saml_route_helper_prefix
|
26
|
+
|
22
27
|
# Allow logging
|
23
28
|
mattr_accessor :saml_logger
|
24
29
|
@@saml_logger = true
|
@@ -62,11 +67,23 @@ module Devise
|
|
62
67
|
mattr_accessor :saml_relay_state
|
63
68
|
@@saml_relay_state
|
64
69
|
|
70
|
+
# Instead of storing the attribute_map in attribute-map.yml, store it in the database, or set it programatically
|
71
|
+
mattr_accessor :saml_attribute_map_resolver
|
72
|
+
@@saml_attribute_map_resolver ||= ::DeviseSamlAuthenticatable::DefaultAttributeMapResolver
|
73
|
+
|
65
74
|
# Implements a #validate method that takes the retrieved resource and response right after retrieval,
|
66
75
|
# and returns true if it's valid. False will cause authentication to fail.
|
76
|
+
# Only one of saml_resource_validator and saml_resource_validator_hook may be used.
|
67
77
|
mattr_accessor :saml_resource_validator
|
68
78
|
@@saml_resource_validator
|
69
79
|
|
80
|
+
# Proc that determines whether a technically correct SAML response is valid per some custom logic.
|
81
|
+
# Receives the user object (or nil, if no match was found), decorated saml_response and
|
82
|
+
# auth_value, inspects the combination for acceptability of login (or create+login, if enabled),
|
83
|
+
# and returns true if it's valid. False will cause authentication to fail.
|
84
|
+
mattr_accessor :saml_resource_validator_hook
|
85
|
+
@@saml_resource_validator_hook
|
86
|
+
|
70
87
|
# Custom value for ruby-saml allowed_clock_drift
|
71
88
|
mattr_accessor :allowed_clock_drift_in_seconds
|
72
89
|
@@allowed_clock_drift_in_seconds
|
@@ -94,7 +111,7 @@ module Devise
|
|
94
111
|
end
|
95
112
|
|
96
113
|
# Proc that is called if Devise.saml_update_user and/or Devise.saml_create_user are true.
|
97
|
-
#
|
114
|
+
# Receives the user object, saml_response and auth_value, and defines how the object's values are
|
98
115
|
# updated with regards to the SAML response. See saml_default_update_resource_hook for an example.
|
99
116
|
mattr_accessor :saml_update_resource_hook
|
100
117
|
@@saml_update_resource_hook = @@saml_default_update_resource_hook
|
@@ -107,11 +124,19 @@ module Devise
|
|
107
124
|
end
|
108
125
|
|
109
126
|
# Proc that is called to resolve the saml_response and auth_value into the correct user object.
|
110
|
-
#
|
127
|
+
# Receives a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
|
111
128
|
# one instance of the provided model that is the matched account, or nil if none exists.
|
112
129
|
# See saml_default_resource_locator above for an example.
|
113
130
|
mattr_accessor :saml_resource_locator
|
114
131
|
@@saml_resource_locator = @@saml_default_resource_locator
|
132
|
+
|
133
|
+
# Proc that is called to resolve the name identifier to use in a LogoutRequest for the current user.
|
134
|
+
# Receives the logged-in user.
|
135
|
+
# Is expected to return the identifier the IdP understands for this user, e.g. email address or username.
|
136
|
+
mattr_accessor :saml_name_identifier_retriever
|
137
|
+
@@saml_name_identifier_retriever = Proc.new do |current_user|
|
138
|
+
current_user.public_send(Devise.saml_default_user_key)
|
139
|
+
end
|
115
140
|
end
|
116
141
|
|
117
142
|
# Add saml_authenticatable strategy to defaults.
|