Skip to content

Commit

Permalink
Merge pull request #261 from sthanson/skip_validate_subject_confirmat…
Browse files Browse the repository at this point in the history
…ion_flag

Allow validate_subject_confirmation Response validation to be skipped
  • Loading branch information
pitbulk committed Aug 18, 2015
2 parents 7b4417e + ff99262 commit b86345c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ def saml_settings
end
```
Some assertion validations can be skipped by passing parameters to OneLogin::RubySaml::Response.new(). For example, you can skip the Conditions validation or the SubjectConfirmation validations by initializing the response with different options:
```ruby
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_conditions: true}) # skips conditions
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_subject_confirmation: true}) # skips subject confirmation
```
What's left at this point, is to wrap it all up in a controller and point the initialization and consumption URLs in OneLogin at that. A full controller example could look like this:
```ruby
Expand Down
7 changes: 5 additions & 2 deletions lib/onelogin/ruby-saml/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class Response < SamlMessage
# @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object
# Or some options for the response validation process like skip the conditions validation
# with the :skip_conditions, or allow a clock_drift when checking dates with :allowed_clock_drift
# or :matches_request_id that will validate that the response matches the ID of the request.
# or :matches_request_id that will validate that the response matches the ID of the request,
# or skip the subject confirmation validation with the :skip_subject_confirmation option
def initialize(response, options = {})
@errors = []

Expand Down Expand Up @@ -524,12 +525,14 @@ def validate_session_expiration(soft = true)
end

# Validates if exists valid SubjectConfirmation (If the response was initialized with the :allowed_clock_drift option,
# timimg validation are relaxed by the allowed_clock_drift value)
# timimg validation are relaxed by the allowed_clock_drift value. If the response was initialized with the
# :skip_subject_confirmation option, this validation is skipped)
# If fails, the error is added to the errors array
# @return [Boolean] True if exists a valid SubjectConfirmation, otherwise False if soft=True
# @raise [ValidationError] if soft == false and validation fails
#
def validate_subject_confirmation
return true if options[:skip_subject_confirmation]
valid_subject_confirmation = false

subject_confirmation_nodes = xpath_from_signed_assertion('/a:Subject/a:SubjectConfirmation')
Expand Down
25 changes: 23 additions & 2 deletions test/response_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,27 @@ class RubySamlTest < Minitest::Test
assert !response_invalid_subjectconfirmation_noa.send(:validate_subject_confirmation)
assert_includes response_invalid_subjectconfirmation_noa.errors, "A valid SubjectConfirmation was not found on this Response"
end

it "return true when the skip_subject_confirmation option is passed and the subject confirmation is valid" do
opts = {}
opts[:skip_subject_confirmation] = true
response_with_skip = OneLogin::RubySaml::Response.new(response_document_valid_signed, opts)
response_with_skip.settings = settings
response_with_skip.settings.assertion_consumer_service_url = 'recipient'
Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
assert response_with_skip.send(:validate_subject_confirmation)
assert_empty response_with_skip.errors
end

it "return true when the skip_subject_confirmation option is passed and the response has an invalid subject confirmation" do
opts = {}
opts[:skip_subject_confirmation] = true
response_with_skip = OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_noa.xml.base64"), opts)
response_with_skip.settings = settings
Time.expects(:now).times(0) # ensures the test isn't run and thus Time.now.utc is never called within the test
assert response_with_skip.send(:validate_subject_confirmation)
assert_empty response_with_skip.errors
end
end

describe "#validate_session_expiration" do
Expand All @@ -632,8 +653,8 @@ class RubySamlTest < Minitest::Test
end

it "returns true when the session has expired, but is still within the allowed_clock_drift" do
drift = (Time.now - Time.parse("2010-11-19T21:57:37Z")) * 60 # minutes ago that this assertion expired
drift += 10 # add a buffer of 10 minutes to make sure the test passes
drift = (Time.now - Time.parse("2010-11-19T21:57:37Z")) * 60 # seconds ago that this assertion expired
drift += 10 # add a buffer of 10 seconds to make sure the test passes
opts = {}
opts[:allowed_clock_drift] = drift

Expand Down

0 comments on commit b86345c

Please sign in to comment.