Comparing changes
v1.0.4
→
v1.0.5
9 commits
7 files changed
Commits
Changed files (7)
lib
spec
lib/saml/kit/assertion.rb
@@ -36,7 +36,8 @@ module Saml
end
def active?(now = Time.current)
- now > configuration.clock_drift.seconds.before(started_at) && !expired?
+ drifted_started_at = started_at - configuration.clock_drift.to_i.seconds
+ now > drifted_started_at && !expired?
end
def attributes
lib/saml/kit/default_registry.rb
@@ -90,6 +90,7 @@ module Saml
http.read_timeout = 30
http.use_ssl = uri.is_a?(URI::HTTPS)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless verify_ssl
+ http.set_debug_output(Saml::Kit.logger)
http
end
end
lib/saml/kit/namespaces.rb
@@ -1,25 +1,32 @@
module Saml
module Kit
module Namespaces
- ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
- ATTR_SPLAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:*"
- BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
- BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
- EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
- INVALID_NAME_ID_POLICY = "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"
- METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
- PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
- PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
- PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
- PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
- REQUESTER_ERROR = "urn:oasis:names:tc:SAML:2.0:status:Requester"
- RESPONDER_ERROR = "urn:oasis:names:tc:SAML:2.0:status:Responder"
- SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
- TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
- UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
- UNSPECIFIED_NAMEID = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
- URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
- VERSION_MISMATCH_ERROR = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch"
+ SAML_2_0 = "urn:oasis:names:tc:SAML:2.0"
+ SAML_1_1 = "urn:oasis:names:tc:SAML:1.1"
+ ATTR_NAME_FORMAT = "#{SAML_2_0}:attrname-format"
+ NAME_ID_FORMAT_1_1 = "#{SAML_1_1}:nameid-format"
+ NAME_ID_FORMAT_2_0 = "#{SAML_2_0}:nameid-format"
+ STATUS = "#{SAML_2_0}:status"
+
+ ASSERTION = "#{SAML_2_0}:assertion"
+ ATTR_SPLAT = "#{ATTR_NAME_FORMAT}:*"
+ BASIC = "#{ATTR_NAME_FORMAT}:basic"
+ BEARER = "#{SAML_2_0}:cm:bearer"
+ EMAIL_ADDRESS = "#{NAME_ID_FORMAT_1_1}:emailAddress"
+ INVALID_NAME_ID_POLICY = "#{STATUS}:InvalidNameIDPolicy"
+ METADATA = "#{SAML_2_0}:metadata"
+ PASSWORD = "#{SAML_2_0}:ac:classes:Password"
+ PASSWORD_PROTECTED = "#{SAML_2_0}:ac:classes:PasswordProtectedTransport"
+ PERSISTENT = "#{NAME_ID_FORMAT_2_0}:persistent"
+ PROTOCOL = "#{SAML_2_0}:protocol"
+ REQUESTER_ERROR = "#{STATUS}:Requester"
+ RESPONDER_ERROR = "#{STATUS}:Responder"
+ SUCCESS = "#{STATUS}:Success"
+ TRANSIENT = "#{NAME_ID_FORMAT_2_0}:transient"
+ UNSPECIFIED = "#{SAML_2_0}:consent:unspecified"
+ UNSPECIFIED_NAMEID = "#{NAME_ID_FORMAT_1_1}:unspecified"
+ URI = "#{ATTR_NAME_FORMAT}:uri"
+ VERSION_MISMATCH_ERROR = "#{STATUS}:VersionMismatch"
end
end
end
lib/saml/kit/signature.rb
@@ -1,6 +1,8 @@
module Saml
module Kit
class Signature
+ include ActiveModel::Validations
+
def initialize(xml_hash)
@xml_hash = xml_hash
end
lib/saml/kit/version.rb
@@ -1,5 +1,5 @@
module Saml
module Kit
- VERSION = "1.0.4"
+ VERSION = "1.0.5"
end
end
spec/saml/response_spec.rb
@@ -419,15 +419,16 @@ RSpec.describe Saml::Kit::Response do
let(:now) { Time.now.utc }
let(:assertion_consumer_service_url) { FFaker::Internet.uri("https") }
let(:password) { FFaker::Movie.title }
+ let(:email) { FFaker::Internet.email }
+ let(:created_at) { DateTime.now }
let(:assertion) do
- FFaker::Movie.title
<<-XML
-<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="#{id}" IssueInstant="2017-11-23T04:33:58Z" Version="2.0">
+<Assertion xmlns="#{Saml::Kit::Namespaces::ASSERTION}" ID="#{id}" IssueInstant="2017-11-23T04:33:58Z" Version="2.0">
<Issuer>#{FFaker::Internet.uri("https")}</Issuer>
<Subject>
- <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">fdddf7ad-c4a4-443c-b96d-c953913b7b4e</NameID>
- <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
- <SubjectConfirmationData InResponseTo="cc8c4131-9336-4d1a-82f2-4ad92abeee22" NotOnOrAfter="2017-11-23T07:33:58Z" Recipient="https://westyundt.ca/acs"/>
+ <NameID Format="#{Saml::Kit::Namespaces::PERSISTENT}">#{SecureRandom.uuid}</NameID>
+ <SubjectConfirmation Method="#{Saml::Kit::Namespaces::BEARER}">
+ <SubjectConfirmationData InResponseTo="#{SecureRandom.uuid}" NotOnOrAfter="2017-11-23T07:33:58Z" Recipient="https://westyundt.ca/acs"/>
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2017-11-23T04:33:58Z" NotOnOrAfter="2017-11-23T07:33:58Z">
@@ -437,15 +438,15 @@ RSpec.describe Saml::Kit::Response do
</Conditions>
<AuthnStatement AuthnInstant="2017-11-23T04:33:58Z" SessionIndex="_11d39a7f-1b86-43ed-90d7-68090a857ca8" SessionNotOnOrAfter="2017-11-23T07:33:58Z">
<AuthnContext>
- <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
+ <AuthnContextClassRef>#{Saml::Kit::Namespaces::PASSWORD}</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
<AttributeStatement>
- <Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="email">
- <AttributeValue>sidney_bayer@nienowemmerich.com</AttributeValue>
+ <Attribute Name="email" NameFormat="#{Saml::Kit::Namespaces::URI}">
+ <AttributeValue>#{email}</AttributeValue>
</Attribute>
- <Attribute Name="created_at" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="created_at">
- <AttributeValue>2017-11-23T04:33:58Z</AttributeValue>
+ <Attribute Name="created_at" NameFormat="#{Saml::Kit::Namespaces::URI}">
+ <AttributeValue>#{created_at.iso8601}</AttributeValue>
</Attribute>
</AttributeStatement>
</Assertion>
@@ -492,8 +493,8 @@ XML
subject = described_class.new(xml)
expect(subject.attributes).to match_array([
- ["created_at", "2017-11-23T04:33:58Z"],
- ["email", "sidney_bayer@nienowemmerich.com"]
+ ["created_at", created_at.iso8601],
+ ["email", email]
])
end
end
spec/saml/signature_spec.rb
@@ -0,0 +1,22 @@
+RSpec.describe Saml::Kit::Signature do
+ describe "#valid?" do
+ let(:key_pair) { ::Xml::Kit::KeyPair.generate(use: :signing) }
+
+ it 'returns true when the signature is valid' do
+ signed_document = Saml::Kit::AuthenticationRequest.build do |x|
+ x.sign_with(key_pair)
+ end
+ subject = described_class.new(Hash.from_xml(signed_document.to_xml))
+ expect(subject).to be_valid
+ end
+
+ xit 'is invalid when the xml has been tampered' do
+ signed_document = Saml::Kit::AuthenticationRequest.build do |x|
+ x.sign_with(key_pair)
+ end
+ tampered_xml = signed_document.to_xml.gsub("Issuer", "Hacked")
+ subject = described_class.new(Hash.from_xml(tampered_xml))
+ expect(subject).to_not be_valid
+ end
+ end
+end