Upgrade ruby-saml to 1.15.0.
This commit is contained in:
parent
e7ebebcd2e
commit
0d6c29d6d2
|
@ -0,0 +1,43 @@
|
||||||
|
name: ruby-saml CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Unit test
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-20.04, macos-latest]
|
||||||
|
ruby-version: [2.1.9, 2.2.10, 2.3.8, 2.4.6, 2.5.8, 2.6.6, 2.7.2, 3.0.1, 3.1, 3.2, jruby-9.1.17.0, jruby-9.2.17.0, jruby-9.3.2.0, jruby-9.4.0.0, truffleruby]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ matrix.ruby-version }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bundle install
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: bundle exec rake
|
||||||
|
|
||||||
|
- name: Coveralls
|
||||||
|
uses: coverallsapp/github-action@master
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.github_token }}
|
||||||
|
parallel: true
|
||||||
|
flag-name: run-${{ matrix.ruby-version }}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
needs: test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Coveralls Finished
|
||||||
|
uses: coverallsapp/github-action@master
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.github_token }}
|
||||||
|
flag-name: run-${{ matrix.ruby-version }}
|
||||||
|
parallel-finished: true
|
|
@ -1,4 +1,12 @@
|
||||||
# Ruby SAML Changelog
|
# Ruby SAML Changelog
|
||||||
|
### 1.15.0 (Jan 04, 2023)
|
||||||
|
* [#650](https://github.com/SAML-Toolkits/ruby-saml/pull/650) Replace strip! by strip on compute_digest method
|
||||||
|
* [#638](https://github.com/SAML-Toolkits/ruby-saml/pull/638) Fix dateTime format for the validUntil attribute of the generated metadata
|
||||||
|
* [#576](https://github.com/SAML-Toolkits/ruby-saml/pull/576) Support idp cert multi with string keys
|
||||||
|
* [#567](https://github.com/SAML-Toolkits/ruby-saml/pull/567) Improve Code quality
|
||||||
|
* Add info about new repo, new maintainer, new security contact
|
||||||
|
* Fix tests, Adjust dependencies, Add ruby 3.2 and new jruby versions tests to the CI. Add coveralls support
|
||||||
|
|
||||||
### 1.14.0 (Feb 01, 2022)
|
### 1.14.0 (Feb 01, 2022)
|
||||||
* [#627](https://github.com/onelogin/ruby-saml/pull/627) Support escape downcasing for validating SLO Signatures of ADFS/Azure
|
* [#627](https://github.com/onelogin/ruby-saml/pull/627) Support escape downcasing for validating SLO Signatures of ADFS/Azure
|
||||||
* [#633](https://github.com/onelogin/ruby-saml/pull/633) Support ability to change ID prefix
|
* [#633](https://github.com/onelogin/ruby-saml/pull/633) Support ability to change ID prefix
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
Copyright (c) 2010-2016 OneLogin, Inc.
|
Copyright (c) 2010-2022 OneLogin, Inc.
|
||||||
|
Copyright (c) 2023 IAM Digital Services, SL.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Ruby SAML
|
# Ruby SAML
|
||||||
[![Build Status](https://github.com/onelogin/ruby-saml/actions/workflows/test.yml/badge.svg?query=branch%3Amaster)](https://github.com/onelogin/ruby-saml/actions/workflows/test.yml?query=branch%3Amaster)
|
[![ruby-saml CI](https://github.com/SAML-Toolkits/ruby-saml/actions/workflows/test.yml/badge.svg)](https://github.com/SAML-Toolkits/ruby-saml/actions/workflows/test.yml)
|
||||||
[![Coverage Status](https://coveralls.io/repos/onelogin/ruby-saml/badge.svg?branch=master)](https://coveralls.io/r/onelogin/ruby-saml?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/github/SAML-Toolkits/ruby-saml/badge.svg?branch=master)](https://coveralls.io/github/SAML-Toolkits/ruby-saml?branch=master)
|
||||||
|
[![Rubygem Version](https://badge.fury.io/rb/ruby-saml.svg)](https://badge.fury.io/rb/ruby-saml)
|
||||||
|
[![GitHub version](https://badge.fury.io/gh/SAML-Toolkits%2Fruby-saml.svg)](https://badge.fury.io/gh/SAML-Toolkits%2Fruby-saml) ![GitHub](https://img.shields.io/github/license/SAML-Toolkits/ruby-saml) ![Gem](https://img.shields.io/gem/dtv/ruby-saml?label=gem%20downloads%20latest) ![Gem](https://img.shields.io/gem/dt/ruby-saml?label=gem%20total%20downloads)
|
||||||
|
|
||||||
Ruby SAML minor and tiny versions may introduce breaking changes. Please read
|
Ruby SAML minor and tiny versions may introduce breaking changes. Please read
|
||||||
[UPGRADING.md](UPGRADING.md) for guidance on upgrading to new Ruby SAML versions.
|
[UPGRADING.md](UPGRADING.md) for guidance on upgrading to new Ruby SAML versions.
|
||||||
|
@ -14,7 +16,7 @@ requests from identity providers.
|
||||||
SAML authorization is a two step process and you are expected to implement support for both.
|
SAML authorization is a two step process and you are expected to implement support for both.
|
||||||
|
|
||||||
We created a demo project for Rails 4 that uses the latest version of this library:
|
We created a demo project for Rails 4 that uses the latest version of this library:
|
||||||
[ruby-saml-example](https://github.com/onelogin/ruby-saml-example)
|
[ruby-saml-example](https://github.com/saml-toolkits/ruby-saml-example)
|
||||||
|
|
||||||
### Supported Ruby Versions
|
### Supported Ruby Versions
|
||||||
|
|
||||||
|
@ -28,8 +30,12 @@ The following Ruby versions are covered by CI testing:
|
||||||
* 2.6.x
|
* 2.6.x
|
||||||
* 2.7.x
|
* 2.7.x
|
||||||
* 3.0.x
|
* 3.0.x
|
||||||
|
* 3.1
|
||||||
|
* 3.2
|
||||||
* JRuby 9.1.x
|
* JRuby 9.1.x
|
||||||
* JRuby 9.2.x
|
* JRuby 9.2.x
|
||||||
|
* JRuby 9.3.X
|
||||||
|
* JRuby 9.4.0
|
||||||
* TruffleRuby (latest)
|
* TruffleRuby (latest)
|
||||||
|
|
||||||
In addition, the following may work but are untested:
|
In addition, the following may work but are untested:
|
||||||
|
@ -52,8 +58,7 @@ In addition, the following may work but are untested:
|
||||||
## Security Guidelines
|
## Security Guidelines
|
||||||
|
|
||||||
If you believe you have discovered a security vulnerability in this gem, please report it
|
If you believe you have discovered a security vulnerability in this gem, please report it
|
||||||
at https://www.onelogin.com/security with a description. We follow responsible disclosure
|
by mail to the maintainer: sixto.martin.garcia+security@gmail.com
|
||||||
guidelines, and will work with you to quickly find a resolution.
|
|
||||||
|
|
||||||
### Security Warning
|
### Security Warning
|
||||||
|
|
||||||
|
@ -87,7 +92,7 @@ Using `Gemfile`
|
||||||
gem 'ruby-saml', '~> 1.11.0'
|
gem 'ruby-saml', '~> 1.11.0'
|
||||||
|
|
||||||
# or track master for bleeding-edge
|
# or track master for bleeding-edge
|
||||||
gem 'ruby-saml', :github => 'onelogin/ruby-saml'
|
gem 'ruby-saml', :github => 'saml-toolkit/ruby-saml'
|
||||||
```
|
```
|
||||||
|
|
||||||
Using RubyGems
|
Using RubyGems
|
||||||
|
@ -392,6 +397,51 @@ The `OneLogin::RubySaml::IdpMetadataParser` also provides the methods `#parse_to
|
||||||
Those return an Hash instead of a `Settings` object, which may be useful for configuring
|
Those return an Hash instead of a `Settings` object, which may be useful for configuring
|
||||||
[omniauth-saml](https://github.com/omniauth/omniauth-saml), for instance.
|
[omniauth-saml](https://github.com/omniauth/omniauth-saml), for instance.
|
||||||
|
|
||||||
|
|
||||||
|
### Validating Signature of Metadata and retrieve settings
|
||||||
|
|
||||||
|
Right now there is no method at ruby_saml to validate the signature of the metadata that gonna be parsed,
|
||||||
|
but it can be done as follows:
|
||||||
|
* Download the XML.
|
||||||
|
* Validate the Signature, providing the cert.
|
||||||
|
* Provide the XML to the parse method if the signature was validated
|
||||||
|
|
||||||
|
```
|
||||||
|
require "xml_security"
|
||||||
|
require "onelogin/ruby-saml/utils"
|
||||||
|
require "onelogin/ruby-saml/idp_metadata_parser"
|
||||||
|
|
||||||
|
url = "<url_to_the_metadata>"
|
||||||
|
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
||||||
|
|
||||||
|
uri = URI.parse(url)
|
||||||
|
raise ArgumentError.new("url must begin with http or https") unless /^https?/ =~ uri.scheme
|
||||||
|
http = Net::HTTP.new(uri.host, uri.port)
|
||||||
|
if uri.scheme == "https"
|
||||||
|
http.use_ssl = true
|
||||||
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||||
|
end
|
||||||
|
|
||||||
|
get = Net::HTTP::Get.new(uri.request_uri)
|
||||||
|
get.basic_auth uri.user, uri.password if uri.user
|
||||||
|
response = http.request(get)
|
||||||
|
xml = response.body
|
||||||
|
errors = []
|
||||||
|
doc = XMLSecurity::SignedDocument.new(xml, errors)
|
||||||
|
cert_str = "<include_cert_here>"
|
||||||
|
cert = OneLogin::RubySaml::Utils.format_cert("cert_str")
|
||||||
|
metadata_sign_cert = OpenSSL::X509::Certificate.new(cert)
|
||||||
|
valid = doc.validate_document_with_cert(metadata_sign_cert, true)
|
||||||
|
if valid
|
||||||
|
settings = idp_metadata_parser.parse(
|
||||||
|
xml,
|
||||||
|
entity_id: "<entity_id_of_the_entity_to_be_retrieved>"
|
||||||
|
)
|
||||||
|
else
|
||||||
|
print "Metadata Signarture failed to be verified with the cert provided"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
## Retrieving Attributes
|
## Retrieving Attributes
|
||||||
|
|
||||||
If you are using `saml:AttributeStatement` to transfer data like the username, you can access all the attributes through `response.attributes`. It contains all the `saml:AttributeStatement`s with its 'Name' as an indifferent key and one or more `saml:AttributeValue`s as values. The value returned depends on the value of the
|
If you are using `saml:AttributeStatement` to transfer data like the username, you can access all the attributes through `response.attributes`. It contains all the `saml:AttributeStatement`s with its 'Name' as an indifferent key and one or more `saml:AttributeValue`s as values. The value returned depends on the value of the
|
||||||
|
|
|
@ -39,7 +39,7 @@ module OneLogin
|
||||||
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
||||||
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
||||||
params.each_pair do |key, value|
|
params.each_pair do |key, value|
|
||||||
request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
request_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
||||||
end
|
end
|
||||||
raise SettingError.new "Invalid settings, idp_sso_service_url is not set!" if settings.idp_sso_service_url.nil? or settings.idp_sso_service_url.empty?
|
raise SettingError.new "Invalid settings, idp_sso_service_url is not set!" if settings.idp_sso_service_url.nil? or settings.idp_sso_service_url.empty?
|
||||||
@login_url = settings.idp_sso_service_url + request_params
|
@login_url = settings.idp_sso_service_url + request_params
|
||||||
|
|
|
@ -36,7 +36,7 @@ module OneLogin
|
||||||
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
||||||
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
||||||
params.each_pair do |key, value|
|
params.each_pair do |key, value|
|
||||||
request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
request_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
||||||
end
|
end
|
||||||
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if settings.idp_slo_service_url.nil? or settings.idp_slo_service_url.empty?
|
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if settings.idp_slo_service_url.nil? or settings.idp_slo_service_url.empty?
|
||||||
@logout_url = settings.idp_slo_service_url + request_params
|
@logout_url = settings.idp_slo_service_url + request_params
|
||||||
|
|
|
@ -49,7 +49,7 @@ module OneLogin
|
||||||
root = meta_doc.add_element("md:EntityDescriptor", namespaces)
|
root = meta_doc.add_element("md:EntityDescriptor", namespaces)
|
||||||
root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
|
root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
|
||||||
root.attributes["entityID"] = settings.sp_entity_id if settings.sp_entity_id
|
root.attributes["entityID"] = settings.sp_entity_id if settings.sp_entity_id
|
||||||
root.attributes["validUntil"] = valid_until.strftime('%Y-%m-%dT%H:%M:%S%z') if valid_until
|
root.attributes["validUntil"] = valid_until.utc.strftime('%Y-%m-%dT%H:%M:%SZ') if valid_until
|
||||||
root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S" if cache_duration
|
root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S" if cache_duration
|
||||||
root
|
root
|
||||||
end
|
end
|
||||||
|
|
|
@ -741,7 +741,7 @@ module OneLogin
|
||||||
# @return [Boolean] True if the SessionNotOnOrAfter of the AuthnStatement is valid, otherwise (when expired) False if soft=True
|
# @return [Boolean] True if the SessionNotOnOrAfter of the AuthnStatement is valid, otherwise (when expired) False if soft=True
|
||||||
# @raise [ValidationError] if soft == false and validation fails
|
# @raise [ValidationError] if soft == false and validation fails
|
||||||
#
|
#
|
||||||
def validate_session_expiration(soft = true)
|
def validate_session_expiration
|
||||||
return true if session_expires_at.nil?
|
return true if session_expires_at.nil?
|
||||||
|
|
||||||
now = Time.now.utc
|
now = Time.now.utc
|
||||||
|
|
|
@ -4,7 +4,6 @@ require 'base64'
|
||||||
require 'nokogiri'
|
require 'nokogiri'
|
||||||
require 'rexml/document'
|
require 'rexml/document'
|
||||||
require 'rexml/xpath'
|
require 'rexml/xpath'
|
||||||
require 'thread'
|
|
||||||
require "onelogin/ruby-saml/error_handling"
|
require "onelogin/ruby-saml/error_handling"
|
||||||
|
|
||||||
# Only supports SAML 2.0
|
# Only supports SAML 2.0
|
||||||
|
@ -69,14 +68,14 @@ module OneLogin
|
||||||
xml = Nokogiri::XML(document.to_s) do |config|
|
xml = Nokogiri::XML(document.to_s) do |config|
|
||||||
config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
|
config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
|
||||||
end
|
end
|
||||||
rescue Exception => error
|
rescue StandardError => error
|
||||||
return false if soft
|
return false if soft
|
||||||
raise ValidationError.new("XML load failed: #{error.message}")
|
raise ValidationError.new("XML load failed: #{error.message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
SamlMessage.schema.validate(xml).map do |schema_error|
|
SamlMessage.schema.validate(xml).map do |schema_error|
|
||||||
return false if soft
|
return false if soft
|
||||||
raise ValidationError.new("#{schema_error.message}\n\n#{xml.to_s}")
|
raise ValidationError.new("#{schema_error.message}\n\n#{xml}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ module OneLogin
|
||||||
end
|
end
|
||||||
|
|
||||||
config.each do |k,v|
|
config.each do |k,v|
|
||||||
acc = "#{k.to_s}=".to_sym
|
acc = "#{k}=".to_sym
|
||||||
if respond_to? acc
|
if respond_to? acc
|
||||||
value = v.is_a?(Hash) ? v.dup : v
|
value = v.is_a?(Hash) ? v.dup : v
|
||||||
send(acc, value)
|
send(acc, value)
|
||||||
|
@ -195,17 +195,13 @@ module OneLogin
|
||||||
|
|
||||||
certs = {:signing => [], :encryption => [] }
|
certs = {:signing => [], :encryption => [] }
|
||||||
|
|
||||||
if idp_cert_multi.key?(:signing) and not idp_cert_multi[:signing].empty?
|
[:signing, :encryption].each do |type|
|
||||||
idp_cert_multi[:signing].each do |idp_cert|
|
certs_for_type = idp_cert_multi[type] || idp_cert_multi[type.to_s]
|
||||||
formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
|
next if !certs_for_type || certs_for_type.empty?
|
||||||
certs[:signing].push(OpenSSL::X509::Certificate.new(formatted_cert))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if idp_cert_multi.key?(:encryption) and not idp_cert_multi[:encryption].empty?
|
certs_for_type.each do |idp_cert|
|
||||||
idp_cert_multi[:encryption].each do |idp_cert|
|
|
||||||
formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
|
formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
|
||||||
certs[:encryption].push(OpenSSL::X509::Certificate.new(formatted_cert))
|
certs[type].push(OpenSSL::X509::Certificate.new(formatted_cert))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -247,7 +243,6 @@ module OneLogin
|
||||||
OpenSSL::PKey::RSA.new(formatted_private_key)
|
OpenSSL::PKey::RSA.new(formatted_private_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def idp_binding_from_embed_sign
|
def idp_binding_from_embed_sign
|
||||||
security[:embed_sign] ? Utils::BINDINGS[:post] : Utils::BINDINGS[:redirect]
|
security[:embed_sign] ? Utils::BINDINGS[:post] : Utils::BINDINGS[:redirect]
|
||||||
|
|
|
@ -41,7 +41,7 @@ module OneLogin
|
||||||
saml_response = CGI.escape(params.delete("SAMLResponse"))
|
saml_response = CGI.escape(params.delete("SAMLResponse"))
|
||||||
response_params = "#{params_prefix}SAMLResponse=#{saml_response}"
|
response_params = "#{params_prefix}SAMLResponse=#{saml_response}"
|
||||||
params.each_pair do |key, value|
|
params.each_pair do |key, value|
|
||||||
response_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
|
response_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if url.nil? or url.empty?
|
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if url.nil? or url.empty?
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module OneLogin
|
module OneLogin
|
||||||
module RubySaml
|
module RubySaml
|
||||||
VERSION = '1.14.0'
|
VERSION = '1.15.0'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -177,7 +177,7 @@ module XMLSecurity
|
||||||
|
|
||||||
def compute_digest(document, digest_algorithm)
|
def compute_digest(document, digest_algorithm)
|
||||||
digest = digest_algorithm.digest(document)
|
digest = digest_algorithm.digest(document)
|
||||||
Base64.encode64(digest).strip!
|
Base64.encode64(digest).strip
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -216,7 +216,7 @@ module XMLSecurity
|
||||||
if options[:fingerprint_alg]
|
if options[:fingerprint_alg]
|
||||||
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
|
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
|
||||||
else
|
else
|
||||||
fingerprint_alg = OpenSSL::Digest::SHA1.new
|
fingerprint_alg = OpenSSL::Digest.new('SHA1')
|
||||||
end
|
end
|
||||||
fingerprint = fingerprint_alg.hexdigest(cert.to_der)
|
fingerprint = fingerprint_alg.hexdigest(cert.to_der)
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,17 @@ Gem::Specification.new do |s|
|
||||||
s.version = OneLogin::RubySaml::VERSION
|
s.version = OneLogin::RubySaml::VERSION
|
||||||
|
|
||||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
s.authors = ["OneLogin LLC"]
|
s.authors = ["SAML Toolkit", "Sixto Martin"]
|
||||||
|
s.email = ['contact@iamdigitalservices.com', 'sixto.martin.garcia@gmail.com']
|
||||||
s.date = Time.now.strftime("%Y-%m-%d")
|
s.date = Time.now.strftime("%Y-%m-%d")
|
||||||
s.description = %q{SAML toolkit for Ruby on Rails}
|
s.description = %q{SAML Ruby toolkit. Add SAML support to your Ruby software using this library}
|
||||||
s.email = %q{support@onelogin.com}
|
|
||||||
s.license = 'MIT'
|
s.license = 'MIT'
|
||||||
s.extra_rdoc_files = [
|
s.extra_rdoc_files = [
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"README.md"
|
"README.md"
|
||||||
]
|
]
|
||||||
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
||||||
s.homepage = %q{https://github.com/onelogin/ruby-saml}
|
s.homepage = %q{https://github.com/saml-toolkits/ruby-saml}
|
||||||
s.rdoc_options = ["--charset=UTF-8"]
|
s.rdoc_options = ["--charset=UTF-8"]
|
||||||
s.require_paths = ["lib"]
|
s.require_paths = ["lib"]
|
||||||
s.rubygems_version = %q{1.3.7}
|
s.rubygems_version = %q{1.3.7}
|
||||||
|
@ -27,12 +27,18 @@ Gem::Specification.new do |s|
|
||||||
# Nokogiri's version dependent on the Ruby version, even though we would
|
# Nokogiri's version dependent on the Ruby version, even though we would
|
||||||
# have liked to constrain Ruby 1.8.7 to install only the 1.5.x versions.
|
# have liked to constrain Ruby 1.8.7 to install only the 1.5.x versions.
|
||||||
if defined?(JRUBY_VERSION)
|
if defined?(JRUBY_VERSION)
|
||||||
if JRUBY_VERSION < '9.2.0.0'
|
if JRUBY_VERSION < '9.1.7.0'
|
||||||
s.add_runtime_dependency('nokogiri', '>= 1.8.2', '<= 1.8.5')
|
s.add_runtime_dependency('nokogiri', '>= 1.8.2', '<= 1.8.5')
|
||||||
s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
|
s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
|
||||||
s.add_runtime_dependency('json', '< 2.3.0')
|
s.add_runtime_dependency('json', '< 2.3.0')
|
||||||
|
elsif JRUBY_VERSION < '9.2.0.0'
|
||||||
|
s.add_runtime_dependency('nokogiri', '>= 1.9.1', '< 1.10.0')
|
||||||
|
elsif JRUBY_VERSION < '9.3.2.0'
|
||||||
|
s.add_runtime_dependency('nokogiri', '>= 1.11.4')
|
||||||
|
s.add_runtime_dependency('rexml')
|
||||||
else
|
else
|
||||||
s.add_runtime_dependency('nokogiri', '>= 1.8.2')
|
s.add_runtime_dependency('nokogiri', '>= 1.13.10')
|
||||||
|
s.add_runtime_dependency('rexml')
|
||||||
end
|
end
|
||||||
elsif RUBY_VERSION < '1.9'
|
elsif RUBY_VERSION < '1.9'
|
||||||
s.add_runtime_dependency('uuid')
|
s.add_runtime_dependency('uuid')
|
||||||
|
@ -41,18 +47,35 @@ Gem::Specification.new do |s|
|
||||||
s.add_runtime_dependency('nokogiri', '>= 1.5.10', '<= 1.6.8.1')
|
s.add_runtime_dependency('nokogiri', '>= 1.5.10', '<= 1.6.8.1')
|
||||||
s.add_runtime_dependency('json', '< 2.3.0')
|
s.add_runtime_dependency('json', '< 2.3.0')
|
||||||
elsif RUBY_VERSION < '2.3'
|
elsif RUBY_VERSION < '2.3'
|
||||||
s.add_runtime_dependency('nokogiri', '>= 1.7', '< 1.10.0')
|
s.add_runtime_dependency('nokogiri', '~> 1.8.5')
|
||||||
|
elsif RUBY_VERSION < '2.5'
|
||||||
|
s.add_runtime_dependency('nokogiri', '~> 1.8.5')
|
||||||
|
s.add_runtime_dependency('rexml')
|
||||||
|
elsif RUBY_VERSION < '2.6'
|
||||||
|
s.add_runtime_dependency('nokogiri', '~> 1.8.5')
|
||||||
|
s.add_runtime_dependency('rexml')
|
||||||
else
|
else
|
||||||
s.add_runtime_dependency('nokogiri', '>= 1.10.5')
|
s.add_runtime_dependency('nokogiri', '~> 1.8.5')
|
||||||
s.add_runtime_dependency('rexml')
|
s.add_runtime_dependency('rexml')
|
||||||
end
|
end
|
||||||
|
|
||||||
s.add_development_dependency('coveralls')
|
s.add_development_dependency('simplecov', '<0.22.0')
|
||||||
|
if RUBY_VERSION < '2.4.1'
|
||||||
|
s.add_development_dependency('simplecov-lcov', '<0.8.0')
|
||||||
|
else
|
||||||
|
s.add_development_dependency('simplecov-lcov', '>0.7.0')
|
||||||
|
end
|
||||||
|
|
||||||
s.add_development_dependency('minitest', '~> 5.5')
|
s.add_development_dependency('minitest', '~> 5.5')
|
||||||
s.add_development_dependency('mocha', '~> 0.14')
|
s.add_development_dependency('mocha', '~> 0.14')
|
||||||
|
|
||||||
|
if RUBY_VERSION < '2.0'
|
||||||
s.add_development_dependency('rake', '~> 10')
|
s.add_development_dependency('rake', '~> 10')
|
||||||
|
else
|
||||||
|
s.add_development_dependency('rake', '>= 12.3.3')
|
||||||
|
end
|
||||||
|
|
||||||
s.add_development_dependency('shoulda', '~> 2.11')
|
s.add_development_dependency('shoulda', '~> 2.11')
|
||||||
s.add_development_dependency('simplecov')
|
|
||||||
s.add_development_dependency('systemu', '~> 2')
|
s.add_development_dependency('systemu', '~> 2')
|
||||||
|
|
||||||
if RUBY_VERSION < '2.1'
|
if RUBY_VERSION < '2.1'
|
||||||
|
|
|
@ -14,18 +14,18 @@ class RequestTest < Minitest::Test
|
||||||
|
|
||||||
it "create the deflated SAMLRequest URL parameter" do
|
it "create the deflated SAMLRequest URL parameter" do
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/unauth\.com\/logout\?SAMLRequest=/, unauth_url
|
assert_match(/^http:\/\/unauth\.com\/logout\?SAMLRequest=/, unauth_url)
|
||||||
|
|
||||||
inflated = decode_saml_request_payload(unauth_url)
|
inflated = decode_saml_request_payload(unauth_url)
|
||||||
assert_match /^<samlp:LogoutRequest/, inflated
|
assert_match(/^<samlp:LogoutRequest/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "support additional params" do
|
it "support additional params" do
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
|
||||||
assert_match /&hello=$/, unauth_url
|
assert_match(/&hello=$/, unauth_url)
|
||||||
|
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :foo => "bar" })
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :foo => "bar" })
|
||||||
assert_match /&foo=bar$/, unauth_url
|
assert_match(/&foo=bar$/, unauth_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "RelayState cases" do
|
it "RelayState cases" do
|
||||||
|
@ -50,7 +50,7 @@ class RequestTest < Minitest::Test
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
||||||
inflated = decode_saml_request_payload(unauth_url)
|
inflated = decode_saml_request_payload(unauth_url)
|
||||||
|
|
||||||
assert_match /<samlp:SessionIndex/, inflated
|
assert_match(/<samlp:SessionIndex/, inflated)
|
||||||
assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
|
assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -62,14 +62,14 @@ class RequestTest < Minitest::Test
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })
|
||||||
inflated = decode_saml_request_payload(unauth_url)
|
inflated = decode_saml_request_payload(unauth_url)
|
||||||
|
|
||||||
assert_match /<saml:NameID/, inflated
|
assert_match(/<saml:NameID/, inflated)
|
||||||
assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
|
assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when the target url doesn't contain a query string" do
|
describe "when the target url doesn't contain a query string" do
|
||||||
it "create the SAMLRequest parameter correctly" do
|
it "create the SAMLRequest parameter correctly" do
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/unauth.com\/logout\?SAMLRequest/, unauth_url
|
assert_match(/^http:\/\/unauth.com\/logout\?SAMLRequest/, unauth_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ class RequestTest < Minitest::Test
|
||||||
settings.idp_slo_service_url = "http://example.com?field=value"
|
settings.idp_slo_service_url = "http://example.com?field=value"
|
||||||
|
|
||||||
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example.com\?field=value&SAMLRequest/, unauth_url
|
assert_match(/^http:\/\/example.com\?field=value&SAMLRequest/, unauth_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,13 +98,13 @@ class RequestTest < Minitest::Test
|
||||||
it "creates request with ID prefixed with default '_'" do
|
it "creates request with ID prefixed with default '_'" do
|
||||||
request = OneLogin::RubySaml::Logoutrequest.new
|
request = OneLogin::RubySaml::Logoutrequest.new
|
||||||
|
|
||||||
assert_match /^_/, request.uuid
|
assert_match(/^_/, request.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
||||||
OneLogin::RubySaml::Utils::set_prefix("test")
|
OneLogin::RubySaml::Utils::set_prefix("test")
|
||||||
request = OneLogin::RubySaml::Logoutrequest.new
|
request = OneLogin::RubySaml::Logoutrequest.new
|
||||||
assert_match /^test/, request.uuid
|
assert_match(/^test/, request.uuid)
|
||||||
OneLogin::RubySaml::Utils::set_prefix("_")
|
OneLogin::RubySaml::Utils::set_prefix("_")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -83,7 +83,7 @@ class MetadataTest < Minitest::Test
|
||||||
assert_equal xml_metadata[0..start.length-1],start
|
assert_equal xml_metadata[0..start.length-1],start
|
||||||
|
|
||||||
doc_metadata = REXML::Document.new(xml_metadata)
|
doc_metadata = REXML::Document.new(xml_metadata)
|
||||||
assert_equal valid_until.strftime('%Y-%m-%dT%H:%M:%S%z'), REXML::XPath.first(doc_metadata, "//md:EntityDescriptor").attribute("validUntil").value
|
assert_equal valid_until.strftime('%Y-%m-%dT%H:%M:%SZ'), REXML::XPath.first(doc_metadata, "//md:EntityDescriptor").attribute("validUntil").value
|
||||||
assert_equal "PT604800S", REXML::XPath.first(doc_metadata, "//md:EntityDescriptor").attribute("cacheDuration").value
|
assert_equal "PT604800S", REXML::XPath.first(doc_metadata, "//md:EntityDescriptor").attribute("cacheDuration").value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ class RequestTest < Minitest::Test
|
||||||
|
|
||||||
it "create the deflated SAMLRequest URL parameter" do
|
it "create the deflated SAMLRequest URL parameter" do
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class RequestTest < Minitest::Test
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
|
|
||||||
assert_match /^<samlp:AuthnRequest/, inflated
|
assert_match(/^<samlp:AuthnRequest/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the deflated SAMLRequest URL parameter including the Destination" do
|
it "create the deflated SAMLRequest URL parameter including the Destination" do
|
||||||
|
@ -36,23 +36,23 @@ class RequestTest < Minitest::Test
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
|
|
||||||
assert_match /<samlp:AuthnRequest[^<]* Destination='http:\/\/example.com'/, inflated
|
assert_match(/<samlp:AuthnRequest[^<]* Destination='http:\/\/example.com'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter without deflating" do
|
it "create the SAMLRequest URL parameter without deflating" do
|
||||||
settings.compress_request = false
|
settings.compress_request = false
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
assert_match /^<samlp:AuthnRequest/, decoded
|
assert_match(/^<samlp:AuthnRequest/, decoded)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with IsPassive" do
|
it "create the SAMLRequest URL parameter with IsPassive" do
|
||||||
settings.passive = true
|
settings.passive = true
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ class RequestTest < Minitest::Test
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
|
|
||||||
assert_match /<samlp:AuthnRequest[^<]* IsPassive='true'/, inflated
|
assert_match(/<samlp:AuthnRequest[^<]* IsPassive='true'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with ProtocolBinding" do
|
it "create the SAMLRequest URL parameter with ProtocolBinding" do
|
||||||
settings.protocol_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
settings.protocol_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
|
@ -76,13 +76,13 @@ class RequestTest < Minitest::Test
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
|
|
||||||
assert_match /<samlp:AuthnRequest[^<]* ProtocolBinding='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'/, inflated
|
assert_match(/<samlp:AuthnRequest[^<]* ProtocolBinding='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with AttributeConsumingServiceIndex" do
|
it "create the SAMLRequest URL parameter with AttributeConsumingServiceIndex" do
|
||||||
settings.attributes_index = 30
|
settings.attributes_index = 30
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
|
@ -90,13 +90,13 @@ class RequestTest < Minitest::Test
|
||||||
inflated = zstream.inflate(decoded)
|
inflated = zstream.inflate(decoded)
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
assert_match /<samlp:AuthnRequest[^<]* AttributeConsumingServiceIndex='30'/, inflated
|
assert_match(/<samlp:AuthnRequest[^<]* AttributeConsumingServiceIndex='30'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with ForceAuthn" do
|
it "create the SAMLRequest URL parameter with ForceAuthn" do
|
||||||
settings.force_authn = true
|
settings.force_authn = true
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
|
|
||||||
|
@ -104,13 +104,13 @@ class RequestTest < Minitest::Test
|
||||||
inflated = zstream.inflate(decoded)
|
inflated = zstream.inflate(decoded)
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
assert_match /<samlp:AuthnRequest[^<]* ForceAuthn='true'/, inflated
|
assert_match(/<samlp:AuthnRequest[^<]* ForceAuthn='true'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with NameID Format" do
|
it "create the SAMLRequest URL parameter with NameID Format" do
|
||||||
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
||||||
|
@ -118,15 +118,15 @@ class RequestTest < Minitest::Test
|
||||||
zstream.finish
|
zstream.finish
|
||||||
zstream.close
|
zstream.close
|
||||||
|
|
||||||
assert_match /<samlp:NameIDPolicy[^<]* AllowCreate='true'/, inflated
|
assert_match(/<samlp:NameIDPolicy[^<]* AllowCreate='true'/, inflated)
|
||||||
assert_match /<samlp:NameIDPolicy[^<]* Format='urn:oasis:names:tc:SAML:2.0:nameid-format:transient'/, inflated
|
assert_match(/<samlp:NameIDPolicy[^<]* Format='urn:oasis:names:tc:SAML:2.0:nameid-format:transient'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the SAMLRequest URL parameter with Subject" do
|
it "create the SAMLRequest URL parameter with Subject" do
|
||||||
settings.name_identifier_value_requested = "testuser@example.com"
|
settings.name_identifier_value_requested = "testuser@example.com"
|
||||||
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
|
assert_match(/^http:\/\/example\.com\?SAMLRequest=/, auth_url)
|
||||||
payload = CGI.unescape(auth_url.split("=").last)
|
payload = CGI.unescape(auth_url.split("=").last)
|
||||||
decoded = Base64.decode64(payload)
|
decoded = Base64.decode64(payload)
|
||||||
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
||||||
|
@ -141,10 +141,10 @@ class RequestTest < Minitest::Test
|
||||||
|
|
||||||
it "accept extra parameters" do
|
it "accept extra parameters" do
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => "there" })
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => "there" })
|
||||||
assert_match /&hello=there$/, auth_url
|
assert_match(/&hello=there$/, auth_url)
|
||||||
|
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => nil })
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => nil })
|
||||||
assert_match /&hello=$/, auth_url
|
assert_match(/&hello=$/, auth_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "RelayState cases" do
|
it "RelayState cases" do
|
||||||
|
@ -164,13 +164,13 @@ class RequestTest < Minitest::Test
|
||||||
it "creates request with ID prefixed with default '_'" do
|
it "creates request with ID prefixed with default '_'" do
|
||||||
request = OneLogin::RubySaml::Authrequest.new
|
request = OneLogin::RubySaml::Authrequest.new
|
||||||
|
|
||||||
assert_match /^_/, request.uuid
|
assert_match(/^_/, request.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
||||||
OneLogin::RubySaml::Utils::set_prefix("test")
|
OneLogin::RubySaml::Utils::set_prefix("test")
|
||||||
request = OneLogin::RubySaml::Authrequest.new
|
request = OneLogin::RubySaml::Authrequest.new
|
||||||
assert_match /^test/, request.uuid
|
assert_match(/^test/, request.uuid)
|
||||||
OneLogin::RubySaml::Utils::set_prefix("_")
|
OneLogin::RubySaml::Utils::set_prefix("_")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ class RequestTest < Minitest::Test
|
||||||
err = assert_raises OneLogin::RubySaml::SettingError do
|
err = assert_raises OneLogin::RubySaml::SettingError do
|
||||||
OneLogin::RubySaml::Authrequest.new.create(settings)
|
OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
end
|
end
|
||||||
assert_match /idp_sso_service_url is not set/, err.message
|
assert_match(/idp_sso_service_url is not set/, err.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ class RequestTest < Minitest::Test
|
||||||
it "create the SAMLRequest parameter correctly" do
|
it "create the SAMLRequest parameter correctly" do
|
||||||
|
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example.com\?SAMLRequest/, auth_url
|
assert_match(/^http:\/\/example.com\?SAMLRequest/, auth_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -200,42 +200,42 @@ class RequestTest < Minitest::Test
|
||||||
settings.idp_sso_service_url = "http://example.com?field=value"
|
settings.idp_sso_service_url = "http://example.com?field=value"
|
||||||
|
|
||||||
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
|
||||||
assert_match /^http:\/\/example.com\?field=value&SAMLRequest/, auth_url
|
assert_match(/^http:\/\/example.com\?field=value&SAMLRequest/, auth_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the saml:AuthnContextClassRef element correctly" do
|
it "create the saml:AuthnContextClassRef element correctly" do
|
||||||
settings.authn_context = 'secure/name/password/uri'
|
settings.authn_context = 'secure/name/password/uri'
|
||||||
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
||||||
assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create multiple saml:AuthnContextClassRef elements correctly" do
|
it "create multiple saml:AuthnContextClassRef elements correctly" do
|
||||||
settings.authn_context = ['secure/name/password/uri', 'secure/email/password/uri']
|
settings.authn_context = ['secure/name/password/uri', 'secure/email/password/uri']
|
||||||
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
||||||
assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s)
|
||||||
assert_match /<saml:AuthnContextClassRef>secure\/email\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextClassRef>secure\/email\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the saml:AuthnContextClassRef with comparison exact" do
|
it "create the saml:AuthnContextClassRef with comparison exact" do
|
||||||
settings.authn_context = 'secure/name/password/uri'
|
settings.authn_context = 'secure/name/password/uri'
|
||||||
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
||||||
assert_match /<samlp:RequestedAuthnContext[\S ]+Comparison='exact'/, auth_doc.to_s
|
assert_match(/<samlp:RequestedAuthnContext[\S ]+Comparison='exact'/, auth_doc.to_s)
|
||||||
assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the saml:AuthnContextClassRef with comparison minimun" do
|
it "create the saml:AuthnContextClassRef with comparison minimun" do
|
||||||
settings.authn_context = 'secure/name/password/uri'
|
settings.authn_context = 'secure/name/password/uri'
|
||||||
settings.authn_context_comparison = 'minimun'
|
settings.authn_context_comparison = 'minimun'
|
||||||
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
||||||
assert_match /<samlp:RequestedAuthnContext[\S ]+Comparison='minimun'/, auth_doc.to_s
|
assert_match(/<samlp:RequestedAuthnContext[\S ]+Comparison='minimun'/, auth_doc.to_s)
|
||||||
assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create the saml:AuthnContextDeclRef element correctly" do
|
it "create the saml:AuthnContextDeclRef element correctly" do
|
||||||
settings.authn_context_decl_ref = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
|
settings.authn_context_decl_ref = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
|
||||||
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
|
||||||
assert_match /<saml:AuthnContextDeclRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport<\/saml:AuthnContextDeclRef>/, auth_doc.to_s
|
assert_match(/<saml:AuthnContextDeclRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport<\/saml:AuthnContextDeclRef>/, auth_doc.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#create_params signing with HTTP-POST binding" do
|
describe "#create_params signing with HTTP-POST binding" do
|
||||||
|
|
|
@ -411,7 +411,7 @@ class RubySamlTest < Minitest::Test
|
||||||
response.settings = settings
|
response.settings = settings
|
||||||
error_msg = "Current time is on or after NotOnOrAfter condition"
|
error_msg = "Current time is on or after NotOnOrAfter condition"
|
||||||
assert !response.is_valid?
|
assert !response.is_valid?
|
||||||
assert_includes response.errors[0], "Current time is on or after NotOnOrAfter condition"
|
assert_includes response.errors[0], error_msg
|
||||||
end
|
end
|
||||||
|
|
||||||
it "return false when encountering a SAML Response with bad formatted" do
|
it "return false when encountering a SAML Response with bad formatted" do
|
||||||
|
@ -457,7 +457,7 @@ class RubySamlTest < Minitest::Test
|
||||||
response_no_version.soft = true
|
response_no_version.soft = true
|
||||||
error_msg = "Unsupported SAML version"
|
error_msg = "Unsupported SAML version"
|
||||||
response_no_version.is_valid?
|
response_no_version.is_valid?
|
||||||
assert_includes response_no_version.errors, "Unsupported SAML version"
|
assert_includes response_no_version.errors, error_msg
|
||||||
end
|
end
|
||||||
|
|
||||||
it "return true when a nil URI is given in the ds:Reference" do
|
it "return true when a nil URI is given in the ds:Reference" do
|
||||||
|
@ -976,7 +976,17 @@ class RubySamlTest < Minitest::Test
|
||||||
:encryption => []
|
:encryption => []
|
||||||
}
|
}
|
||||||
response_valid_signed.settings = settings
|
response_valid_signed.settings = settings
|
||||||
res = response_valid_signed.send(:validate_signature)
|
response_valid_signed.send(:validate_signature)
|
||||||
|
assert_empty response_valid_signed.errors
|
||||||
|
end
|
||||||
|
|
||||||
|
it "return true when at least a cert on idp_cert_multi is valid and keys are strings" do
|
||||||
|
settings.idp_cert_multi = {
|
||||||
|
"signing" => [ruby_saml_cert_text2, ruby_saml_cert_text],
|
||||||
|
"encryption" => []
|
||||||
|
}
|
||||||
|
response_valid_signed.settings = settings
|
||||||
|
assert response_valid_signed.send(:validate_signature)
|
||||||
assert_empty response_valid_signed.errors
|
assert_empty response_valid_signed.errors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1217,7 +1227,7 @@ class RubySamlTest < Minitest::Test
|
||||||
settings.private_key = nil
|
settings.private_key = nil
|
||||||
response_encrypted_attrs.settings = settings
|
response_encrypted_attrs.settings = settings
|
||||||
assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedAttribute found and no SP private key found on the settings to decrypt it") do
|
assert_raises(OneLogin::RubySaml::ValidationError, "An EncryptedAttribute found and no SP private key found on the settings to decrypt it") do
|
||||||
attrs = response_encrypted_attrs.attributes
|
response_encrypted_attrs.attributes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1355,6 +1365,7 @@ class RubySamlTest < Minitest::Test
|
||||||
|
|
||||||
describe '#xpath_first_from_signed_assertion' do
|
describe '#xpath_first_from_signed_assertion' do
|
||||||
it 'not allow arbitrary code execution' do
|
it 'not allow arbitrary code execution' do
|
||||||
|
$evalled = nil
|
||||||
malicious_response_document = fixture('response_eval', false)
|
malicious_response_document = fixture('response_eval', false)
|
||||||
malicious_response = OneLogin::RubySaml::Response.new(malicious_response_document)
|
malicious_response = OneLogin::RubySaml::Response.new(malicious_response_document)
|
||||||
malicious_response.send(:xpath_first_from_signed_assertion)
|
malicious_response.send(:xpath_first_from_signed_assertion)
|
||||||
|
@ -1437,11 +1448,11 @@ class RubySamlTest < Minitest::Test
|
||||||
error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it. Be sure you provided the :settings parameter at the initialize method"
|
error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it. Be sure you provided the :settings parameter at the initialize method"
|
||||||
|
|
||||||
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
||||||
response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion)
|
OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
||||||
response2 = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
|
OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
settings.certificate = ruby_saml_cert_text
|
settings.certificate = ruby_saml_cert_text
|
||||||
|
@ -1459,7 +1470,7 @@ class RubySamlTest < Minitest::Test
|
||||||
|
|
||||||
error_msg = "Neither PUB key nor PRIV key: nested asn1 error"
|
error_msg = "Neither PUB key nor PRIV key: nested asn1 error"
|
||||||
assert_raises(OpenSSL::PKey::RSAError, error_msg) do
|
assert_raises(OpenSSL::PKey::RSAError, error_msg) do
|
||||||
response = OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
|
OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1553,7 +1564,7 @@ class RubySamlTest < Minitest::Test
|
||||||
|
|
||||||
error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it"
|
error_msg = "An EncryptedAssertion found and no SP private key found on the settings to decrypt it"
|
||||||
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
|
||||||
decrypted = response.send(:decrypt_assertion, encrypted_assertion_node)
|
response.send(:decrypt_assertion, encrypted_assertion_node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -257,11 +257,54 @@ class SettingsTest < Minitest::Test
|
||||||
assert_equal empty_multi, @settings.get_idp_cert_multi
|
assert_equal empty_multi, @settings.get_idp_cert_multi
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the hash with certificates when values were valid" do
|
it "returns partial hash when contains some values with string keys" do
|
||||||
certificates = ruby_saml_cert_text
|
empty_multi = {
|
||||||
|
:signing => [],
|
||||||
|
:encryption => []
|
||||||
|
}
|
||||||
|
|
||||||
@settings.idp_cert_multi = {
|
@settings.idp_cert_multi = {
|
||||||
:signing => [ruby_saml_cert_text],
|
"signing" => []
|
||||||
:encryption => [ruby_saml_cert_text],
|
}
|
||||||
|
assert_equal empty_multi, @settings.get_idp_cert_multi
|
||||||
|
|
||||||
|
@settings.idp_cert_multi = {
|
||||||
|
"encryption" => []
|
||||||
|
}
|
||||||
|
assert_equal empty_multi, @settings.get_idp_cert_multi
|
||||||
|
|
||||||
|
@settings.idp_cert_multi = {
|
||||||
|
"signing" => [],
|
||||||
|
"encryption" => []
|
||||||
|
}
|
||||||
|
assert_equal empty_multi, @settings.get_idp_cert_multi
|
||||||
|
|
||||||
|
@settings.idp_cert_multi = {
|
||||||
|
"yyy" => [],
|
||||||
|
"zzz" => []
|
||||||
|
}
|
||||||
|
assert_equal empty_multi, @settings.get_idp_cert_multi
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the hash with certificates when values were valid" do
|
||||||
|
certificates = [ruby_saml_cert_text]
|
||||||
|
@settings.idp_cert_multi = {
|
||||||
|
:signing => certificates,
|
||||||
|
:encryption => certificates,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert @settings.get_idp_cert_multi.kind_of? Hash
|
||||||
|
assert @settings.get_idp_cert_multi[:signing].kind_of? Array
|
||||||
|
assert @settings.get_idp_cert_multi[:encryption].kind_of? Array
|
||||||
|
assert @settings.get_idp_cert_multi[:signing][0].kind_of? OpenSSL::X509::Certificate
|
||||||
|
assert @settings.get_idp_cert_multi[:encryption][0].kind_of? OpenSSL::X509::Certificate
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the hash with certificates when values were valid and with string keys" do
|
||||||
|
certificates = [ruby_saml_cert_text]
|
||||||
|
@settings.idp_cert_multi = {
|
||||||
|
"signing" => certificates,
|
||||||
|
"encryption" => certificates,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert @settings.get_idp_cert_multi.kind_of? Hash
|
assert @settings.get_idp_cert_multi.kind_of? Hash
|
||||||
|
|
|
@ -170,7 +170,7 @@ class RubySamlTest < Minitest::Test
|
||||||
Timecop.freeze Time.parse('2014-07-17T01:01:49Z') do
|
Timecop.freeze Time.parse('2014-07-17T01:01:49Z') do
|
||||||
logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
|
logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
|
||||||
assert !logout_request.send(:validate_not_on_or_after)
|
assert !logout_request.send(:validate_not_on_or_after)
|
||||||
assert /Current time is on or after NotOnOrAfter/.match(logout_request.errors[0])
|
assert_match(/Current time is on or after NotOnOrAfter/, logout_request.errors[0])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,21 +20,21 @@ class SloLogoutresponseTest < Minitest::Test
|
||||||
|
|
||||||
it "create the deflated SAMLResponse URL parameter" do
|
it "create the deflated SAMLResponse URL parameter" do
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
||||||
assert_match /^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url
|
assert_match(/^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url)
|
||||||
|
|
||||||
inflated = decode_saml_response_payload(unauth_url)
|
inflated = decode_saml_response_payload(unauth_url)
|
||||||
assert_match /^<samlp:LogoutResponse/, inflated
|
assert_match(/^<samlp:LogoutResponse/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "support additional params" do
|
it "support additional params" do
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :hello => nil })
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :hello => nil })
|
||||||
assert_match /&hello=$/, unauth_url
|
assert_match(/&hello=$/, unauth_url)
|
||||||
|
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :foo => "bar" })
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :foo => "bar" })
|
||||||
assert_match /&foo=bar$/, unauth_url
|
assert_match(/&foo=bar$/, unauth_url)
|
||||||
|
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://idp.example.com" })
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://idp.example.com" })
|
||||||
assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
|
assert_match(/&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "RelayState cases" do
|
it "RelayState cases" do
|
||||||
|
@ -55,45 +55,45 @@ class SloLogoutresponseTest < Minitest::Test
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
||||||
|
|
||||||
inflated = decode_saml_response_payload(unauth_url)
|
inflated = decode_saml_response_payload(unauth_url)
|
||||||
assert_match /InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated
|
assert_match(/InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "set a custom successful logout message on the response" do
|
it "set a custom successful logout message on the response" do
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, "Custom Logout Message")
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, "Custom Logout Message")
|
||||||
|
|
||||||
inflated = decode_saml_response_payload(unauth_url)
|
inflated = decode_saml_response_payload(unauth_url)
|
||||||
assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
|
assert_match(/<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "set a custom logout message and an status on the response" do
|
it "set a custom logout message and an status on the response" do
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message", {}, "urn:oasis:names:tc:SAML:2.0:status:PartialLogout")
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message", {}, "urn:oasis:names:tc:SAML:2.0:status:PartialLogout")
|
||||||
|
|
||||||
inflated = decode_saml_response_payload(unauth_url)
|
inflated = decode_saml_response_payload(unauth_url)
|
||||||
assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
|
assert_match(/<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated)
|
||||||
assert_match /<samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:PartialLogout/, inflated
|
assert_match(/<samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:PartialLogout/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "uses the response location when set" do
|
it "uses the response location when set" do
|
||||||
settings.idp_slo_response_service_url = "http://unauth.com/logout/return"
|
settings.idp_slo_response_service_url = "http://unauth.com/logout/return"
|
||||||
|
|
||||||
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
|
||||||
assert_match /^http:\/\/unauth\.com\/logout\/return\?SAMLResponse=/, unauth_url
|
assert_match(/^http:\/\/unauth\.com\/logout\/return\?SAMLResponse=/, unauth_url)
|
||||||
|
|
||||||
inflated = decode_saml_response_payload(unauth_url)
|
inflated = decode_saml_response_payload(unauth_url)
|
||||||
assert_match /Destination='http:\/\/unauth.com\/logout\/return'/, inflated
|
assert_match(/Destination='http:\/\/unauth.com\/logout\/return'/, inflated)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "playgin with preix" do
|
describe "playgin with preix" do
|
||||||
it "creates request with ID prefixed with default '_'" do
|
it "creates request with ID prefixed with default '_'" do
|
||||||
request = OneLogin::RubySaml::SloLogoutresponse.new
|
request = OneLogin::RubySaml::SloLogoutresponse.new
|
||||||
|
|
||||||
assert_match /^_/, request.uuid
|
assert_match(/^_/, request.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
it "creates request with ID is prefixed, when :id_prefix is passed" do
|
||||||
OneLogin::RubySaml::Utils::set_prefix("test")
|
OneLogin::RubySaml::Utils::set_prefix("test")
|
||||||
request = OneLogin::RubySaml::SloLogoutresponse.new
|
request = OneLogin::RubySaml::SloLogoutresponse.new
|
||||||
assert_match /^test/, request.uuid
|
assert_match(/^test/, request.uuid)
|
||||||
OneLogin::RubySaml::Utils::set_prefix("_")
|
OneLogin::RubySaml::Utils::set_prefix("_")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -147,8 +147,8 @@ class SloLogoutresponseTest < Minitest::Test
|
||||||
|
|
||||||
response_xml = Base64.decode64(params["SAMLResponse"])
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
||||||
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
||||||
assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml
|
assert_match(/<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml)
|
||||||
assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml
|
assert_match(/<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create a signed logout response with 256 digest and signature methods" do
|
it "create a signed logout response with 256 digest and signature methods" do
|
||||||
|
@ -159,8 +159,8 @@ class SloLogoutresponseTest < Minitest::Test
|
||||||
|
|
||||||
response_xml = Base64.decode64(params["SAMLResponse"])
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
||||||
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
||||||
assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml
|
assert_match(/<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml)
|
||||||
assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml
|
assert_match(/<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
|
it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
|
||||||
|
@ -172,8 +172,8 @@ class SloLogoutresponseTest < Minitest::Test
|
||||||
|
|
||||||
response_xml = Base64.decode64(params["SAMLResponse"])
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
||||||
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
||||||
assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml
|
assert_match(/<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml)
|
||||||
assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml
|
assert_match(/<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
require 'simplecov'
|
require 'simplecov'
|
||||||
require 'coveralls'
|
require 'simplecov-lcov'
|
||||||
|
|
||||||
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
|
||||||
|
SimpleCov::Formatter::LcovFormatter.config.output_directory = 'coverage'
|
||||||
|
SimpleCov::Formatter::LcovFormatter.config.lcov_file_name = 'lcov.info'
|
||||||
|
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
|
||||||
SimpleCov.start do
|
SimpleCov.start do
|
||||||
add_filter "test/"
|
add_filter "test/"
|
||||||
add_filter "vendor/"
|
add_filter "vendor/"
|
||||||
|
|
|
@ -183,18 +183,25 @@ class UtilsTest < Minitest::Test
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#status_error_msg" do
|
describe "#status_error_msg" do
|
||||||
it "returns a error msg with a status message" do
|
it "returns a error msg with status_code and status message" do
|
||||||
error_msg = "The status code of the Logout Response was not Success"
|
error_msg = "The status code of the Logout Response was not Success"
|
||||||
status_code = "urn:oasis:names:tc:SAML:2.0:status:Requester"
|
status_code = "urn:oasis:names:tc:SAML:2.0:status:Requester"
|
||||||
status_message = "The request could not be performed due to an error on the part of the requester."
|
status_message = "The request could not be performed due to an error on the part of the requester."
|
||||||
status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code, status_message)
|
status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code, status_message)
|
||||||
assert_equal = "The status code of the Logout Response was not Success, was Requester -> The request could not be performed due to an error on the part of the requester.", status_error_msg
|
assert_equal "The status code of the Logout Response was not Success, was Requester -> The request could not be performed due to an error on the part of the requester.", status_error_msg
|
||||||
|
end
|
||||||
|
|
||||||
status_error_msg2 = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code)
|
it "returns a error msg with status_code" do
|
||||||
assert_equal = "The status code of the Logout Response was not Success, was Requester", status_error_msg2
|
error_msg = "The status code of the Logout Response was not Success"
|
||||||
|
status_code = "urn:oasis:names:tc:SAML:2.0:status:Requester"
|
||||||
|
status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code)
|
||||||
|
assert_equal "The status code of the Logout Response was not Success, was Requester", status_error_msg
|
||||||
|
end
|
||||||
|
|
||||||
status_error_msg3 = OneLogin::RubySaml::Utils.status_error_msg(error_msg)
|
it "returns a error msg" do
|
||||||
assert_equal = "The status code of the Logout Response was not Success", status_error_msg3
|
error_msg = "The status code of the Logout Response was not Success"
|
||||||
|
status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg)
|
||||||
|
assert_equal "The status code of the Logout Response was not Success", status_error_msg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -202,7 +209,7 @@ class UtilsTest < Minitest::Test
|
||||||
|
|
||||||
describe ".uuid" do
|
describe ".uuid" do
|
||||||
it "returns a uuid starting with an underscore" do
|
it "returns a uuid starting with an underscore" do
|
||||||
assert_match /^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, OneLogin::RubySaml::Utils.uuid
|
assert_match(/^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, OneLogin::RubySaml::Utils.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't return the same value twice" do
|
it "doesn't return the same value twice" do
|
||||||
|
|
|
@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
||||||
s.summary = "Summary of SsoLoginBox."
|
s.summary = "Summary of SsoLoginBox."
|
||||||
s.description = "Description of SsoLoginBox."
|
s.description = "Description of SsoLoginBox."
|
||||||
s.license = "MIT"
|
s.license = "MIT"
|
||||||
s.add_dependency 'ruby-saml', '1.11.0'
|
s.add_dependency 'ruby-saml-custom'
|
||||||
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
|
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
|
||||||
s.test_files = Dir["test/**/*"]
|
s.test_files = Dir["test/**/*"]
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue