omniauth-saml 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of omniauth-saml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -2
- data/LICENSE.md +25 -0
- data/README.md +25 -27
- data/lib/omniauth-saml/version.rb +1 -1
- data/lib/omniauth/strategies/saml.rb +40 -16
- data/spec/omniauth/strategies/saml_spec.rb +55 -9
- data/spec/spec_helper.rb +10 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5157e12042f1980c72b6fa603d6cee7d818cf153
|
4
|
+
data.tar.gz: 44f05863e67b9b0463ddc195348174c4869b684c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa3e6fd1d482e5787351d91e65201edfebc63999204f6ba32484a332947661d09d793bb045a5ca24426f7406d7dab706e71fd2d6a1468147eb1c72a9e33b952c
|
7
|
+
data.tar.gz: 6640bee32d302612b03db9b5fe37816026f78c1e7666cb8c0a95525cee0a1728df46335fd15e5932119ccb710401d8cbcd4442837bbb24c585c98edea126aa99
|
data/CHANGELOG.md
CHANGED
@@ -2,9 +2,36 @@
|
|
2
2
|
|
3
3
|
A generic SAML strategy for OmniAuth.
|
4
4
|
|
5
|
-
https://github.com/
|
5
|
+
https://github.com/omniauth/omniauth-saml
|
6
6
|
|
7
|
-
## 1.
|
7
|
+
## 1.5.0 (2016-02-25)
|
8
|
+
|
9
|
+
* Initialize OneLogin::RubySaml::Response instance with settings
|
10
|
+
* Adding "settings" to Response Class at initialization to handle signing verification
|
11
|
+
* Support custom attributes
|
12
|
+
* change URL from PracticallyGreen to omniauth
|
13
|
+
* Add specs for ACS fallback URL behavior
|
14
|
+
* Call validation earlier to get real error instead of 'response missing name_id'
|
15
|
+
* Avoid mutation of the options hash during requests and callbacks
|
16
|
+
|
17
|
+
## 1.4.2 (2016-02-09)
|
18
|
+
|
19
|
+
* update ruby-saml to 1.1
|
20
|
+
|
21
|
+
## 1.4.1 (2015-08-09)
|
22
|
+
|
23
|
+
* Configurable attribute_consuming_service
|
24
|
+
|
25
|
+
## 1.4.0 (2015-07-23)
|
26
|
+
|
27
|
+
* update ruby-saml to 1.0.0
|
28
|
+
|
29
|
+
## 1.3.1 (2015-02-26)
|
30
|
+
|
31
|
+
* Added missing fingerprint key check
|
32
|
+
* Expose fingerprint on the auth_hash
|
33
|
+
|
34
|
+
## 1.3.0 (2015-01-23)
|
8
35
|
|
9
36
|
* add `idp_cert_fingerprint_validator` option
|
10
37
|
|
data/LICENSE.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# License
|
2
|
+
|
3
|
+
Copyright © 2016 Omniauth-SAML maintainers
|
4
|
+
|
5
|
+
Copyright © 2011-2014 [Practically Green, Inc.](http://www.practicallygreen.com/).
|
6
|
+
|
7
|
+
All rights reserved. Released under the MIT license.
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in
|
17
|
+
all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
# OmniAuth SAML
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](http://img.shields.io/gem/v/omniauth-saml.svg)][gem]
|
4
|
+
[![Build Status](http://img.shields.io/travis/omniauth/omniauth-saml.svg)][travis]
|
5
|
+
[![Dependency Status](http://img.shields.io/gemnasium/omniauth/omniauth-saml.svg)][gemnasium]
|
6
|
+
[![Code Climate](http://img.shields.io/codeclimate/github/omniauth/omniauth-saml.svg)][codeclimate]
|
7
|
+
[![Coverage Status](http://img.shields.io/coveralls/omniauth/omniauth-saml.svg)][coveralls]
|
4
8
|
|
5
|
-
https://
|
9
|
+
[gem]: https://rubygems.org/gems/omniauth-saml
|
10
|
+
[travis]: http://travis-ci.org/omniauth/omniauth-saml
|
11
|
+
[gemnasium]: https://gemnasium.com/omniauth/omniauth-saml
|
12
|
+
[codeclimate]: https://codeclimate.com/github/omniauth/omniauth-saml
|
13
|
+
[coveralls]: https://coveralls.io/r/omniauth/omniauth-saml
|
14
|
+
|
15
|
+
A generic SAML strategy for OmniAuth available under the [MIT License](LICENSE.md)
|
16
|
+
|
17
|
+
https://github.com/omniauth/omniauth-saml
|
6
18
|
|
7
19
|
## Requirements
|
8
20
|
|
9
|
-
* [OmniAuth](http://www.omniauth.org/) 1.
|
10
|
-
* Ruby 1.9.x or Ruby 2.1.x
|
21
|
+
* [OmniAuth](http://www.omniauth.org/) 1.3+
|
22
|
+
* Ruby 1.9.x or Ruby 2.1.x+
|
11
23
|
|
12
24
|
## Usage
|
13
25
|
|
@@ -100,6 +112,15 @@ The service provider metadata used to ease configuration of the SAML SP in the I
|
|
100
112
|
|
101
113
|
* `:attribute_service_name` - Name for the attribute service. Defaults to `Required attributes`.
|
102
114
|
|
115
|
+
* `:attribute_statements` - Used to map Attribute Names in a SAMLResponse to
|
116
|
+
entries in the OmniAuth [info hash](https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later).
|
117
|
+
For example, if your SAMLResponse contains an Attribute called 'EmailAddress',
|
118
|
+
specify `{:email => ['EmailAddress']}` to map the Attribute to the
|
119
|
+
corresponding key in the info hash. URI-named Attributes are also supported, e.g.
|
120
|
+
`{:email => ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']}`.
|
121
|
+
*Note*: All attributes can also be found in an array under `auth_hash[:extra][:raw_info]`,
|
122
|
+
so this setting should only be used to map attributes that are part of the OmniAuth info hash schema.
|
123
|
+
|
103
124
|
* See the `OneLogin::RubySaml::Settings` class in the [Ruby SAML gem](https://github.com/onelogin/ruby-saml) for additional supported options.
|
104
125
|
|
105
126
|
## Devise Integration
|
@@ -121,26 +142,3 @@ Then follow Devise's general [OmniAuth tutorial](https://github.com/plataformate
|
|
121
142
|
## Authors
|
122
143
|
|
123
144
|
Authored by [Rajiv Aaron Manglani](http://www.rajivmanglani.com/), Raecoo Cao, Todd W Saxton, Ryan Wilcox, Steven Anderson, Nikos Dimitrakopoulos, Rudolf Vriend and [Bruno Pedro](http://brunopedro.com/).
|
124
|
-
|
125
|
-
## License
|
126
|
-
|
127
|
-
Copyright (c) 2011-2014 [Practically Green, Inc.](http://www.practicallygreen.com/).
|
128
|
-
All rights reserved. Released under the MIT license.
|
129
|
-
|
130
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
131
|
-
of this software and associated documentation files (the "Software"), to deal
|
132
|
-
in the Software without restriction, including without limitation the rights
|
133
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
134
|
-
copies of the Software, and to permit persons to whom the Software is
|
135
|
-
furnished to do so, subject to the following conditions:
|
136
|
-
|
137
|
-
The above copyright notice and this permission notice shall be included in
|
138
|
-
all copies or substantial portions of the Software.
|
139
|
-
|
140
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
141
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
142
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
143
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
144
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
145
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
146
|
-
THE SOFTWARE.
|
@@ -6,15 +6,23 @@ module OmniAuth
|
|
6
6
|
class SAML
|
7
7
|
include OmniAuth::Strategy
|
8
8
|
|
9
|
+
OTHER_REQUEST_OPTIONS = [:skip_conditions, :allowed_clock_drift, :matches_request_id, :skip_subject_confirmation].freeze
|
10
|
+
|
9
11
|
option :name_identifier_format, nil
|
10
12
|
option :idp_sso_target_url_runtime_params, {}
|
11
13
|
option :request_attributes, [
|
12
|
-
{ name
|
13
|
-
{ name
|
14
|
-
{ name
|
15
|
-
{ name
|
14
|
+
{ :name => 'email', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Email address' },
|
15
|
+
{ :name => 'name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Full name' },
|
16
|
+
{ :name => 'first_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Given name' },
|
17
|
+
{ :name => 'last_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Family name' }
|
16
18
|
]
|
17
19
|
option :attribute_service_name, 'Required attributes'
|
20
|
+
option :attribute_statements, {
|
21
|
+
name: ["name"],
|
22
|
+
email: ["email", "mail"],
|
23
|
+
first_name: ["first_name", "firstname", "firstName"],
|
24
|
+
last_name: ["last_name", "lastname", "lastName"]
|
25
|
+
}
|
18
26
|
|
19
27
|
def request_phase
|
20
28
|
options[:assertion_consumer_service_url] ||= callback_url
|
@@ -46,10 +54,22 @@ module OmniAuth
|
|
46
54
|
options.idp_cert_fingerprint = fingerprint_exists
|
47
55
|
end
|
48
56
|
|
49
|
-
|
50
|
-
|
57
|
+
settings = OneLogin::RubySaml::Settings.new(options)
|
58
|
+
# filter options to select only extra parameters
|
59
|
+
opts = options.select {|k,_| OTHER_REQUEST_OPTIONS.include?(k.to_sym)}
|
60
|
+
# symbolize keys without activeSupport/symbolize_keys (ruby-saml use symbols)
|
61
|
+
opts =
|
62
|
+
opts.inject({}) do |new_hash, (key, value)|
|
63
|
+
new_hash[key.to_sym] = value
|
64
|
+
new_hash
|
65
|
+
end
|
66
|
+
response = OneLogin::RubySaml::Response.new(request.params['SAMLResponse'], opts.merge(settings: settings))
|
51
67
|
response.attributes['fingerprint'] = options.idp_cert_fingerprint
|
52
68
|
|
69
|
+
# will raise an error since we are not in soft mode
|
70
|
+
response.soft = false
|
71
|
+
response.is_valid?
|
72
|
+
|
53
73
|
@name_id = response.name_id
|
54
74
|
@attributes = response.attributes
|
55
75
|
|
@@ -57,10 +77,6 @@ module OmniAuth
|
|
57
77
|
raise OmniAuth::Strategies::SAML::ValidationError.new("SAML response missing 'name_id'")
|
58
78
|
end
|
59
79
|
|
60
|
-
# will raise an error since we are not in soft mode
|
61
|
-
response.soft = false
|
62
|
-
response.is_valid?
|
63
|
-
|
64
80
|
super
|
65
81
|
rescue OmniAuth::Strategies::SAML::ValidationError
|
66
82
|
fail!(:invalid_ticket, $!)
|
@@ -103,15 +119,23 @@ module OmniAuth
|
|
103
119
|
uid { @name_id }
|
104
120
|
|
105
121
|
info do
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
122
|
+
found_attributes = options.attribute_statements.map do |key, values|
|
123
|
+
attribute = find_attribute_by(values)
|
124
|
+
[key, attribute]
|
125
|
+
end
|
126
|
+
|
127
|
+
Hash[found_attributes]
|
112
128
|
end
|
113
129
|
|
114
130
|
extra { { :raw_info => @attributes } }
|
131
|
+
|
132
|
+
def find_attribute_by(keys)
|
133
|
+
keys.each do |key|
|
134
|
+
return @attributes[key] if @attributes[key]
|
135
|
+
end
|
136
|
+
|
137
|
+
nil
|
138
|
+
end
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
@@ -16,16 +16,16 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
16
16
|
let(:auth_hash){ last_request.env['omniauth.auth'] }
|
17
17
|
let(:saml_options) do
|
18
18
|
{
|
19
|
-
:assertion_consumer_service_url => "http://localhost:
|
20
|
-
:idp_sso_target_url => "https://idp.sso.
|
19
|
+
:assertion_consumer_service_url => "http://localhost:9080/auth/saml/callback",
|
20
|
+
:idp_sso_target_url => "https://idp.sso.example.com/signon/29490",
|
21
21
|
:idp_cert_fingerprint => "C1:59:74:2B:E8:0C:6C:A9:41:0F:6E:83:F6:D1:52:25:45:58:89:FB",
|
22
22
|
:idp_sso_target_url_runtime_params => {:original_param_key => :mapped_param_key},
|
23
23
|
:name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
24
24
|
:request_attributes => [
|
25
|
-
{ name
|
26
|
-
{ name
|
27
|
-
{ name
|
28
|
-
{ name
|
25
|
+
{ :name => 'email', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Email address' },
|
26
|
+
{ :name => 'name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Full name' },
|
27
|
+
{ :name => 'first_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Given name' },
|
28
|
+
{ :name => 'last_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Family name' }
|
29
29
|
],
|
30
30
|
:attribute_service_name => 'Required attributes'
|
31
31
|
}
|
@@ -40,7 +40,7 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
40
40
|
|
41
41
|
it 'should get authentication page' do
|
42
42
|
last_response.should be_redirect
|
43
|
-
last_response.location.should match /https:\/\/idp.sso.
|
43
|
+
last_response.location.should match /https:\/\/idp.sso.example.com\/signon\/29490/
|
44
44
|
last_response.location.should match /\?SAMLRequest=/
|
45
45
|
last_response.location.should_not match /mapped_param_key/
|
46
46
|
last_response.location.should_not match /original_param_key/
|
@@ -54,12 +54,37 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
54
54
|
|
55
55
|
it 'should get authentication page' do
|
56
56
|
last_response.should be_redirect
|
57
|
-
last_response.location.should match /https:\/\/idp.sso.
|
57
|
+
last_response.location.should match /https:\/\/idp.sso.example.com\/signon\/29490/
|
58
58
|
last_response.location.should match /\?SAMLRequest=/
|
59
59
|
last_response.location.should match /\&mapped_param_key=original_param_value/
|
60
60
|
last_response.location.should_not match /original_param_key/
|
61
61
|
end
|
62
62
|
end
|
63
|
+
|
64
|
+
context "when the assertion_consumer_service_url is the default" do
|
65
|
+
before :each do
|
66
|
+
saml_options[:compress_request] = false
|
67
|
+
saml_options.delete(:assertion_consumer_service_url)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should send the current callback_url as the assertion_consumer_service_url' do
|
71
|
+
%w(foo.example.com bar.example.com).each do |host|
|
72
|
+
get "https://#{host}/auth/saml"
|
73
|
+
|
74
|
+
last_response.should be_redirect
|
75
|
+
|
76
|
+
location = URI.parse(last_response.location)
|
77
|
+
query = Rack::Utils.parse_query location.query
|
78
|
+
query.should have_key('SAMLRequest')
|
79
|
+
|
80
|
+
request = REXML::Document.new(Base64.decode64(query['SAMLRequest']))
|
81
|
+
request.root.should_not be_nil
|
82
|
+
|
83
|
+
acs = request.root.attributes.get_attribute('AssertionConsumerServiceURL')
|
84
|
+
acs.to_s.should == "https://#{host}/auth/saml/callback"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
63
88
|
end
|
64
89
|
|
65
90
|
describe 'POST /auth/saml/callback' do
|
@@ -68,7 +93,7 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
68
93
|
let(:xml) { :example_response }
|
69
94
|
|
70
95
|
before :each do
|
71
|
-
Time.stub(:now).and_return(Time.
|
96
|
+
Time.stub(:now).and_return(Time.utc(2012, 11, 8, 20, 40, 00))
|
72
97
|
end
|
73
98
|
|
74
99
|
context "when the response is valid" do
|
@@ -153,6 +178,27 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
153
178
|
|
154
179
|
it { should fail_with(:invalid_ticket) }
|
155
180
|
end
|
181
|
+
|
182
|
+
context "when response has custom attributes" do
|
183
|
+
before :each do
|
184
|
+
saml_options[:idp_cert_fingerprint] = "3B:82:F1:F5:54:FC:A8:FF:12:B8:4B:B8:16:61:1D:E4:8E:9B:E2:3C"
|
185
|
+
saml_options[:attribute_statements] = {
|
186
|
+
email: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
|
187
|
+
first_name: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],
|
188
|
+
last_name: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"]
|
189
|
+
}
|
190
|
+
post_xml :custom_attributes
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should obey attribute statements mapping" do
|
194
|
+
auth_hash[:info].should == {
|
195
|
+
'first_name' => 'Rajiv',
|
196
|
+
'last_name' => 'Manglani',
|
197
|
+
'email' => 'user@example.com',
|
198
|
+
'name' => nil
|
199
|
+
}
|
200
|
+
end
|
201
|
+
end
|
156
202
|
end
|
157
203
|
|
158
204
|
describe 'GET /auth/saml/metadata' do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniauth-saml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Raecoo Cao
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2016-02-
|
17
|
+
date: 2016-02-25 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: omniauth
|
@@ -22,14 +22,14 @@ dependencies:
|
|
22
22
|
requirements:
|
23
23
|
- - "~>"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: '1.
|
25
|
+
version: '1.3'
|
26
26
|
type: :runtime
|
27
27
|
prerelease: false
|
28
28
|
version_requirements: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '1.
|
32
|
+
version: '1.3'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: ruby-saml
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,6 +99,7 @@ extensions: []
|
|
99
99
|
extra_rdoc_files: []
|
100
100
|
files:
|
101
101
|
- CHANGELOG.md
|
102
|
+
- LICENSE.md
|
102
103
|
- README.md
|
103
104
|
- lib/omniauth-saml.rb
|
104
105
|
- lib/omniauth-saml/version.rb
|
@@ -106,7 +107,7 @@ files:
|
|
106
107
|
- lib/omniauth/strategies/saml/validation_error.rb
|
107
108
|
- spec/omniauth/strategies/saml_spec.rb
|
108
109
|
- spec/spec_helper.rb
|
109
|
-
homepage: https://github.com/
|
110
|
+
homepage: https://github.com/omniauth/omniauth-saml
|
110
111
|
licenses:
|
111
112
|
- MIT
|
112
113
|
metadata: {}
|
@@ -126,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
127
|
version: '0'
|
127
128
|
requirements: []
|
128
129
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.
|
130
|
+
rubygems_version: 2.5.1
|
130
131
|
signing_key:
|
131
132
|
specification_version: 4
|
132
133
|
summary: A generic SAML strategy for OmniAuth.
|