Skip to content
This repository was archived by the owner on Mar 12, 2026. It is now read-only.

Commit 3c2336d

Browse files
committed
merge v0.9.2
2 parents 1f8575b + 54c6349 commit 3c2336d

32 files changed

Lines changed: 673 additions & 260 deletions

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,14 @@ rvm:
44
- 1.9.3
55
- 2.0.0
66
- 2.1.5
7+
- 2.2.0
78
- ree
9+
gemfile:
10+
- Gemfile
11+
- gemfiles/nokogiri-1.5.gemfile
12+
matrix:
13+
exclude:
14+
- rvm: 1.8.7
15+
gemfile: Gemfile
16+
- rvm: ree
17+
gemfile: Gemfile

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#
22
# Please keep this file alphabetized and organized
33
#
4-
source 'http://rubygems.org'
4+
source 'https://rubygems.org'
55

66
gemspec

README.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ We created a demo project for Rails4 that uses the latest version of this librar
1818
* 1.8.7
1919
* 1.9.x
2020
* 2.1.x
21-
* 2.2 (not yet officially supported)
21+
* 2.2.0
2222

2323
## Adding Features, Pull Requests
2424
* Fork the repository
@@ -41,7 +41,7 @@ gem 'ruby-saml', '~> 0.9.1'
4141
gem 'ruby-saml', :github => 'onelogin/ruby-saml'
4242
```
4343

44-
Using Bundler
44+
Using RubyGems
4545

4646
```sh
4747
gem install ruby-saml
@@ -58,6 +58,22 @@ or just the required components individually:
5858
require 'onelogin/ruby-saml/authrequest'
5959
```
6060

61+
### Installation on Ruby 1.8.7
62+
63+
This gem has a dependency on Nokogiri, which dropped support for Ruby 1.8.x in Nokogiri 1.6. When installing this gem on Ruby 1.8.7, you will need to make sure a version of Nokogiri prior to 1.6 is installed or specified if it hasn't been already.
64+
65+
Using `Gemfile`
66+
67+
```ruby
68+
gem 'nokogiri', '~> 1.5.10'
69+
```
70+
71+
Using RubyGems
72+
73+
```sh
74+
gem install nokogiri --version '~> 1.5.10'
75+
````
76+
6177
## The Initialization Phase
6278

6379
This is the first request you will get from the identity provider. It will hit your application at a specific URL (that you've announced as being your SAML initialization point). The response to this initialization, is a redirect back to the identity provider, which can look something like this (ignore the saml_settings method call for now):
@@ -100,6 +116,7 @@ def saml_settings
100116
settings.idp_sso_target_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
101117
settings.idp_slo_target_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
102118
settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
119+
settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
103120
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
104121
105122
# Optional for most SAML IdPs
@@ -192,7 +209,7 @@ The following attributes are set:
192209
* idp_slo_target_url
193210
* id_cert_fingerpint
194211
195-
If are using saml:AttributeStatement to transfer metadata, like the user name, you can access all the attributes through response.attributes. It contains all the saml:AttributeStatement with its 'Name' as a indifferent key the one/more saml:AttributeValue as value. The value returned depends on the value of the
212+
If you are using saml:AttributeStatement to transfer metadata, like the user name, you can access all the attributes through response.attributes. It contains all the saml:AttributeStatement with its 'Name' as a indifferent key the one/more saml:AttributeValue as value. The value returned depends on the value of the
196213
`single_value_compatibility` (when activate, only one value returned, the first one)
197214
198215
```ruby
@@ -320,16 +337,23 @@ In order to be able to sign we need first to define the private key and the publ
320337
The settings related to sign are stored in the `security` attribute of the settings:
321338
322339
```ruby
323-
settings.security[:authn_requests_signed] = true # Enable or not signature on AuthNRequest
324-
settings.security[:logout_requests_signed] = true # Enable or not signature on Logout Request
340+
settings.security[:authn_requests_signed] = true # Enable or not signature on AuthNRequest
341+
settings.security[:logout_requests_signed] = true # Enable or not signature on Logout Request
325342
settings.security[:logout_responses_signed] = true # Enable or not signature on Logout Response
343+
settings.security[:metadata_signed] = true # Enable or not signature on Metadata
326344
327345
settings.security[:digest_method] = XMLSecurity::Document::SHA1
328-
settings.security[:signature_method] = XMLSecurity::Document::SHA1
346+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
329347
330-
settings.security[:embed_sign] = false # Embeded signature or HTTP GET parameter Signature
348+
# Embeded signature or HTTP GET parameter signature
349+
# Note that metadata signature is always embedded regardless of this value.
350+
settings.security[:embed_sign] = false
331351
```
332352
353+
Notice that the RelayState parameter is used when creating the Signature on the HTTP-Redirect Binding,
354+
remember to provide it to the Signature builder if you are sending a GET RelayState parameter or
355+
Signature validation process will fail at the Identity Provider.
356+
333357
334358
## Single Log Out
335359

changelog.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
# RubySaml Changelog
2+
### 0.9.2 (Apr 28, 2015)
3+
* [#216](https://github.com/onelogin/ruby-saml/pull/216) Add fingerprint algorithm support
4+
* [#218](https://github.com/onelogin/ruby-saml/pull/218) Update README.md
5+
* [#214](https://github.com/onelogin/ruby-saml/pull/214) Cleanup `SamlMessage` class
6+
* [#213](https://github.com/onelogin/ruby-saml/pull/213) Add ability to sign metadata. (Improved)
7+
* [#212](https://github.com/onelogin/ruby-saml/pull/212) Rename library entry point
8+
* [#210](https://github.com/onelogin/ruby-saml/pull/210) Call assert in tests
9+
* [#208](https://github.com/onelogin/ruby-saml/pull/208) Update tests and CI for Ruby 2.2.0
10+
* [#205](https://github.com/onelogin/ruby-saml/pull/205) Allow requirement of single files
11+
* [#204](https://github.com/onelogin/ruby-saml/pull/204) Require ‘net/http’ library
12+
* [#201](https://github.com/onelogin/ruby-saml/pull/201) Freeze and duplicate default security settings hash so that it doesn't get modified.
13+
* [#200](https://github.com/onelogin/ruby-saml/pull/200) Set default SSL certificate store in Ruby 1.8.
14+
* [#199](https://github.com/onelogin/ruby-saml/pull/199) Change Nokogiri's runtime dependency to fix support for Ruby 1.8.7.
15+
* [#179](https://github.com/onelogin/ruby-saml/pull/179) Add support for setting the entity ID and name ID format when parsing metadata
16+
* [#175](https://github.com/onelogin/ruby-saml/pull/175) Introduce thread safety to SAML schema validation
17+
* [#171](https://github.com/onelogin/ruby-saml/pull/171) Fix inconsistent results with using regex matches in decode_raw_saml
18+
*
19+
220
### 0.9.1 (Feb 10, 2015)
321
* [#194](https://github.com/onelogin/ruby-saml/pull/194) Relax nokogiri gem requirements
422
* [#191](https://github.com/onelogin/ruby-saml/pull/191) Use Minitest instead of Test::Unit

gemfiles/nokogiri-1.5.gemfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
source 'https://rubygems.org'
2+
3+
gem "nokogiri", "~> 1.5.10"
4+
5+
gemspec :path => "../"

lib/onelogin/ruby-saml.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
require 'onelogin/ruby-saml/logging'
2+
require 'onelogin/ruby-saml/saml_message'
3+
require 'onelogin/ruby-saml/authrequest'
4+
require 'onelogin/ruby-saml/logoutrequest'
5+
require 'onelogin/ruby-saml/logoutresponse'
6+
require 'onelogin/ruby-saml/attributes'
7+
require 'onelogin/ruby-saml/slo_logoutrequest'
8+
require 'onelogin/ruby-saml/slo_logoutresponse'
9+
require 'onelogin/ruby-saml/response'
10+
require 'onelogin/ruby-saml/settings'
11+
require 'onelogin/ruby-saml/attribute_service'
12+
require 'onelogin/ruby-saml/validation_error'
13+
require 'onelogin/ruby-saml/metadata'
14+
require 'onelogin/ruby-saml/idp_metadata_parser'
15+
require 'onelogin/ruby-saml/utils'
16+
require 'onelogin/ruby-saml/version'

lib/onelogin/ruby-saml/authrequest.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
require "uuid"
2+
require "rexml/document"
23

34
require "onelogin/ruby-saml/logging"
5+
require "onelogin/ruby-saml/saml_message"
46

57
module OneLogin
68
module RubySaml
@@ -25,7 +27,10 @@ def create(settings, params = {})
2527
end
2628

2729
def create_params(settings, params={})
28-
params = {} if params.nil?
30+
# The method expects :RelayState but sometimes we get 'RelayState' instead.
31+
# Based on the HashWithIndifferentAccess value in Rails we could experience
32+
# conflicts so this line will solve them.
33+
relay_state = params[:RelayState] || params['RelayState']
2934

3035
request_doc = create_authentication_xml_doc(settings)
3136
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
@@ -40,10 +45,10 @@ def create_params(settings, params={})
4045
request_params = {"SAMLRequest" => base64_request}
4146

4247
if settings.security[:authn_requests_signed] && !settings.security[:embed_sign] && settings.private_key
43-
params['SigAlg'] = XMLSecurity::Document::SHA1
48+
params['SigAlg'] = settings.security[:signature_method]
4449
url_string = "SAMLRequest=#{CGI.escape(base64_request)}"
45-
url_string += "&RelayState=#{CGI.escape(params['RelayState'])}" if params['RelayState']
46-
url_string += "&SigAlg=#{CGI.escape(params['SigAlg'])}"
50+
url_string << "&RelayState=#{CGI.escape(relay_state)}" if relay_state
51+
url_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
4752
private_key = settings.get_sp_key()
4853
signature = private_key.sign(XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method]).new, url_string)
4954
params['Signature'] = encode(signature)
@@ -123,7 +128,7 @@ def create_authentication_xml_doc(settings)
123128
end
124129
end
125130

126-
# embebed sign
131+
# embed signature
127132
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
128133
private_key = settings.get_sp_key()
129134
cert = settings.get_sp_cert()

lib/onelogin/ruby-saml/idp_metadata_parser.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
require "uuid"
33
require "zlib"
44
require "cgi"
5+
require "net/http"
6+
require "net/https"
57
require "rexml/document"
68
require "rexml/xpath"
79

@@ -25,7 +27,8 @@ def parse(idp_metadata)
2527
@document = REXML::Document.new(idp_metadata)
2628

2729
OneLogin::RubySaml::Settings.new.tap do |settings|
28-
30+
settings.idp_entity_id = idp_entity_id
31+
settings.name_identifier_format = idp_name_id_format
2932
settings.idp_sso_target_url = single_signon_service_url
3033
settings.idp_slo_target_url = single_logout_service_url
3134
settings.idp_cert_fingerprint = fingerprint
@@ -47,6 +50,12 @@ def get_idp_metadata(url, validate_cert)
4750
# Most IdPs will probably use self signed certs
4851
if validate_cert
4952
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
53+
54+
# Net::HTTP in Ruby 1.8 did not set the default certificate store
55+
# automatically when VERIFY_PEER was specified.
56+
if RUBY_VERSION < '1.9' && !http.ca_file && !http.ca_path && !http.cert_store
57+
http.cert_store = OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
58+
end
5059
else
5160
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
5261
end
@@ -57,6 +66,16 @@ def get_idp_metadata(url, validate_cert)
5766
meta_text
5867
end
5968

69+
def idp_entity_id
70+
node = REXML::XPath.first(document, "/md:EntityDescriptor/@entityID", { "md" => METADATA })
71+
node.value if node
72+
end
73+
74+
def idp_name_id_format
75+
node = REXML::XPath.first(document, "/md:EntityDescriptor/md:IDPSSODescriptor/md:NameIDFormat", { "md" => METADATA })
76+
node.text if node
77+
end
78+
6079
def single_signon_service_url
6180
node = REXML::XPath.first(document, "/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleSignOnService/@Location", { "md" => METADATA })
6281
node.value if node

lib/onelogin/ruby-saml/logoutrequest.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require "uuid"
22

33
require "onelogin/ruby-saml/logging"
4+
require "onelogin/ruby-saml/saml_message"
45

56
module OneLogin
67
module RubySaml
@@ -24,7 +25,10 @@ def create(settings, params={})
2425
end
2526

2627
def create_params(settings, params={})
27-
params = {} if params.nil?
28+
# The method expects :RelayState but sometimes we get 'RelayState' instead.
29+
# Based on the HashWithIndifferentAccess value in Rails we could experience
30+
# conflicts so this line will solve them.
31+
relay_state = params[:RelayState] || params['RelayState']
2832

2933
request_doc = create_logout_request_xml_doc(settings)
3034
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
@@ -39,10 +43,10 @@ def create_params(settings, params={})
3943
request_params = {"SAMLRequest" => base64_request}
4044

4145
if settings.security[:logout_requests_signed] && !settings.security[:embed_sign] && settings.private_key
42-
params['SigAlg'] = XMLSecurity::Document::SHA1
46+
params['SigAlg'] = settings.security[:signature_method]
4347
url_string = "SAMLRequest=#{CGI.escape(base64_request)}"
44-
url_string += "&RelayState=#{CGI.escape(params['RelayState'])}" if params['RelayState']
45-
url_string += "&SigAlg=#{CGI.escape(params['SigAlg'])}"
48+
url_string << "&RelayState=#{CGI.escape(relay_state)}" if relay_state
49+
url_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
4650
private_key = settings.get_sp_key()
4751
signature = private_key.sign(XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method]).new, url_string)
4852
params['Signature'] = encode(signature)
@@ -88,7 +92,7 @@ def create_logout_request_xml_doc(settings)
8892
sessionindex.text = settings.sessionindex
8993
end
9094

91-
# embebed sign
95+
# embed signature
9296
if settings.security[:logout_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
9397
private_key = settings.get_sp_key()
9498
cert = settings.get_sp_cert()

lib/onelogin/ruby-saml/logoutresponse.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
require "xml_security"
2+
require "onelogin/ruby-saml/saml_message"
3+
24
require "time"
35

46
module OneLogin

0 commit comments

Comments
 (0)