devise_saml_authenticatable 1.4.0 → 1.6.2
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 +27 -24
- data/Gemfile +2 -2
- data/README.md +99 -30
- data/app/controllers/devise/saml_sessions_controller.rb +34 -7
- data/devise_saml_authenticatable.gemspec +1 -1
- data/lib/devise_saml_authenticatable.rb +25 -0
- data/lib/devise_saml_authenticatable/default_attribute_map_resolver.rb +26 -0
- data/lib/devise_saml_authenticatable/exception.rb +1 -1
- data/lib/devise_saml_authenticatable/model.rb +10 -17
- 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 -1
- data/lib/devise_saml_authenticatable/version.rb +1 -1
- data/spec/controllers/devise/saml_sessions_controller_spec.rb +69 -11
- data/spec/devise_saml_authenticatable/default_attribute_map_resolver_spec.rb +58 -0
- data/spec/devise_saml_authenticatable/model_spec.rb +55 -7
- data/spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb +50 -0
- data/spec/features/saml_authentication_spec.rb +45 -37
- 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 +20 -10
- 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 +23 -12
- data/spec/support/Gemfile.ruby-saml-1.3 +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c0d1e1f1df121795583d9fc25cab40edac01bb61f8adbdb4fac7c0c15bfe4b0c
|
4
|
+
data.tar.gz: 0d7770994b0c119da178a3b19ced6d52a88364d561279c5bd759ce5580fb5fe5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d849dc5dff4bd09d0dd034449ed3e68494f0f1c82c8e31c708b7d6e0d3a366a2fd119fb24704d0e5a946b6fc206dbe072fadbf7218489abffdbe1b3644d41419
|
7
|
+
data.tar.gz: e64b35109ed35b61e804fa5e06d3b3c299210cf75804f706e299147d02a7ddb929246c1a7fdb65aee12f5ceed5348267d3c6e4657544288e3a45741474d5e30d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,49 +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
|
34
47
|
|
35
48
|
before_install:
|
36
|
-
|
37
|
-
- gem install bundler
|
49
|
+
- command -v bundle || gem install bundler -v '~> 1.17.3'
|
38
50
|
|
39
51
|
script:
|
40
52
|
- bundle exec rake
|
41
|
-
|
42
|
-
notifications:
|
43
|
-
hipchat:
|
44
|
-
rooms:
|
45
|
-
secure: cuDak5a6fBeg+sp61COqxQfzdcFEsjwCqtwvCISso0RNh5SR8v+uVYKcA8rlK+GE1l9uR7tLRHeHF3ZmzvFSOat07NvpScvjZXi+OSpWlc6rwQ6Pl6bBP6gu6sREiKVe0eT/uGrvJloyWKZaXIhiiBzQ+ZERx/ssGA9WMmNkhlwy1OgGnPNurNNHZLBjEZn1V6kdyxiXx6QPASNpjNEgN1G8dUh3qzcWUGVQGNZSJk65A6ie1MveNyecTjDhw+ADBU8nS28Ja4y6ohRm4FzofSgespYrvfygIZ5rYF0HPMj5FW1ZDWtM5355ojCk8RLT+ZkuhssCn1OJk7ogaOVjnYcOFRxEfpu3eIbjtMmUz3j4umatFqbgas+6SXMVIPkr5HUoTrP8HNFssIpcEBOnPwAF8QCpx+daHc0r2cc8lGuXhtJfpW0P2F0dmwJNiQ7//nz2y2xs84x4Gb7MV9tEDYp0FqEClMuFBkPNizBljarm04PkiLSrqvR52aMDfQz7YAX2oXAvFjPzI1GC0K8x7xX8TuHT9yuHy7fI+rUSNivZYLKO+IEZqPPDdJpXISUbVwanZoNvmQYk5PZV21MfDSGwQrz8eO/uFiAblj18yIlNbAfb2hdZDVYsm4EvWxELJtfaTxgrj6M3Y3m/KbCbCoDp+2jE307M2rxL0Gum2gk=
|
46
|
-
template:
|
47
|
-
- '%{repository}<a href="%{build_url}">#%{build_number}</a> (%{branch} - <a href="%{compare_url}">%{commit}</a> : %{author}): %{message}'
|
48
|
-
format: html
|
49
|
-
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,6 +101,16 @@ 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
|
|
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
|
+
|
72
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|
|
74
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
|
@@ -79,29 +121,32 @@ In `config/initializers/devise.rb`:
|
|
79
121
|
settings.authn_context = ""
|
80
122
|
settings.idp_slo_target_url = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
|
81
123
|
settings.idp_sso_target_url = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
|
82
|
-
settings.
|
83
|
-
|
84
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
85
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
86
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
87
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
88
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
89
|
-
1111111111111_______IDP_CERTIFICATE________111111111111111111111
|
90
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
91
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
92
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
93
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
94
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
95
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
96
|
-
1111111111111111111111111111111111111111111111111111111111111111
|
97
|
-
111111111111111111
|
98
|
-
-----END CERTIFICATE-----
|
99
|
-
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"
|
100
126
|
end
|
101
127
|
end
|
102
128
|
```
|
103
129
|
|
104
|
-
|
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:
|
105
150
|
|
106
151
|
```yaml
|
107
152
|
# attribute-map.yml
|
@@ -112,15 +157,39 @@ In the config directory, create a YAML file (`attribute-map.yml`) that maps SAML
|
|
112
157
|
"urn:mace:dir:attribute-def:givenName": "name"
|
113
158
|
```
|
114
159
|
|
115
|
-
|
116
|
-
In this example the attributes are given in URN style.
|
117
|
-
Other IdPs might provide them as OID's, or by other means.
|
160
|
+
##### Attribute map initializer
|
118
161
|
|
119
|
-
|
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.
|
120
165
|
|
121
|
-
|
166
|
+
```ruby
|
167
|
+
# config/initializers/devise.rb
|
168
|
+
Devise.setup do |config|
|
169
|
+
...
|
170
|
+
# ==> Configuration for :saml_authenticatable
|
122
171
|
|
123
|
-
|
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
|
+
```
|
124
193
|
|
125
194
|
## Supporting Multiple IdPs
|
126
195
|
|
@@ -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,14 +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(_)
|
56
68
|
idp_entity_id = get_idp_entity_id(params)
|
57
69
|
request = OneLogin::RubySaml::Logoutrequest.new
|
58
|
-
|
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)
|
59
80
|
end
|
60
81
|
|
61
82
|
def generate_idp_logout_response(saml_config, logout_request_id)
|
62
|
-
|
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)
|
63
90
|
end
|
64
91
|
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
|
@@ -112,6 +129,14 @@ module Devise
|
|
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.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DeviseSamlAuthenticatable
|
2
|
+
class DefaultAttributeMapResolver
|
3
|
+
def initialize(saml_response)
|
4
|
+
@saml_response = saml_response
|
5
|
+
end
|
6
|
+
|
7
|
+
def attribute_map
|
8
|
+
return {} unless File.exist?(attribute_map_path)
|
9
|
+
|
10
|
+
attribute_map = YAML.load(File.read(attribute_map_path))
|
11
|
+
if attribute_map.key?(Rails.env)
|
12
|
+
attribute_map[Rails.env]
|
13
|
+
else
|
14
|
+
attribute_map
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :saml_response
|
21
|
+
|
22
|
+
def attribute_map_path
|
23
|
+
Rails.root.join("config", "attribute-map.yml")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|