Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :skip_audience option #548

Merged
merged 2 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_authnst
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
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_recipient_check: true}) # doens't skip subject confirmation, but skips the recipient check which is a sub check of the subject_confirmation check
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_audience: true}) # skips audience check
swordfish444 marked this conversation as resolved.
Show resolved Hide resolved
```

All that's left is to wrap everything in a controller and reference it in the initialization and consumption URLs in OneLogin. A full controller example could look like this:
Expand Down
6 changes: 5 additions & 1 deletion lib/onelogin/ruby-saml/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Response < SamlMessage
# This is not a whitelist to allow people extending OneLogin::RubySaml:Response
# and pass custom options
AVAILABLE_OPTIONS = [
:allowed_clock_drift, :check_duplicated_attributes, :matches_request_id, :settings, :skip_authnstatement, :skip_conditions,
:allowed_clock_drift, :check_duplicated_attributes, :matches_request_id, :settings, :skip_audience, :skip_authnstatement, :skip_conditions,
:skip_destination, :skip_recipient_check, :skip_subject_confirmation
]
# TODO: Update the comment on initialize to describe every option
Expand All @@ -47,6 +47,8 @@ class Response < SamlMessage
# 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
# or skip the recipient validation of the subject confirmation element with :skip_recipient_check option
# or skip the audience validation with :skip_audience option
#
def initialize(response, options = {})
raise ArgumentError.new("Response cannot be nil") if response.nil?

Expand Down Expand Up @@ -595,11 +597,13 @@ def validate_in_response_to
end

# Validates the Audience, (If the Audience match the Service Provider EntityID)
# If the response was initialized with the :skip_audience option, this validation is skipped,
# If fails, the error is added to the errors array
# @return [Boolean] True if there is an Audience Element that match the Service Provider EntityID, otherwise False if soft=True
# @raise [ValidationError] if soft == false and validation fails
#
def validate_audience
return true if options[:skip_audience]
swordfish444 marked this conversation as resolved.
Show resolved Hide resolved
return true if audiences.empty? || settings.sp_entity_id.nil? || settings.sp_entity_id.empty?

unless audiences.include? settings.sp_entity_id
Expand Down
8 changes: 8 additions & 0 deletions test/response_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class RubySamlTest < Minitest::Test
let(:response_multiple_signed) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_signed.xml.base64")) }
let(:response_audience_self_closed) { OneLogin::RubySaml::Response.new(read_response("response_audience_self_closed_tag.xml.base64")) }
let(:response_invalid_audience) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_audience.xml.base64")) }
let(:response_invalid_audience_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_audience.xml.base64"), {:skip_audience => true}) }
let(:response_invalid_signed_element) { OneLogin::RubySaml::Response.new(read_invalid_response("response_invalid_signed_element.xml.base64")) }
let(:response_invalid_issuer_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_issuer_assertion.xml.base64")) }
let(:response_invalid_issuer_message) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_issuer_message.xml.base64")) }
Expand Down Expand Up @@ -683,6 +684,13 @@ def generate_audience_error(expected, actual)
assert !response_invalid_audience.send(:validate_audience)
assert_includes response_invalid_audience.errors, generate_audience_error(response_invalid_audience.settings.sp_entity_id, ['http://invalid.audience.com'])
end

it "return true when there is no valid audience but skip_destination option is used" do
response_invalid_audience_with_skip.settings = settings
response_invalid_audience_with_skip.settings.sp_entity_id = "https://invalid.example.com/audience"
assert response_invalid_audience_with_skip.send(:validate_audience)
assert_empty response_invalid_audience_with_skip.errors
end
end

describe "#validate_issuer" do
Expand Down