saml-kit 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/saml/kit.rb +1 -0
- data/lib/saml/kit/assertion.rb +33 -5
- data/lib/saml/kit/bindings/url_builder.rb +1 -1
- data/lib/saml/kit/buildable.rb +4 -0
- data/lib/saml/kit/builders/xml_signature.rb +1 -1
- data/lib/saml/kit/certificate.rb +2 -2
- data/lib/saml/kit/document.rb +2 -1
- data/lib/saml/kit/locales/en.yml +2 -1
- data/lib/saml/kit/metadata.rb +2 -1
- data/lib/saml/kit/response.rb +7 -32
- data/lib/saml/kit/signature.rb +12 -11
- data/lib/saml/kit/signatures.rb +20 -1
- data/lib/saml/kit/templatable.rb +5 -1
- data/lib/saml/kit/translatable.rb +9 -0
- data/lib/saml/kit/trustable.rb +7 -12
- data/lib/saml/kit/version.rb +1 -1
- data/lib/saml/kit/xml_decryption.rb +1 -1
- data/lib/saml/kit/xsd_validatable.rb +0 -4
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b98601350af83c7090bc7fead240f7fabb4736f642a262502a96c48e533f3203
|
4
|
+
data.tar.gz: a51e398301b1115654dbe0a8a31bf61b029456c12302bb42512b7dac716d38e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d032fb605d2c62e45e491ddde0e90274f3ae0ddab82c7e4daa72cfcc7c992483abcd5151399c67d7205bcb0de2ebe1fb1e1953fe416c9efac333e1dba86ab56
|
7
|
+
data.tar.gz: d330dc2cc0a7dfd9d7fb29e9ec9da4b9549739160f77bc6de73f1d6bd9ca15851faa595a3ccf7a75064479751b81123beaf4fb0dd6b31f5f193fbc4fd0ce182e
|
data/lib/saml/kit.rb
CHANGED
data/lib/saml/kit/assertion.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
module Saml
|
2
2
|
module Kit
|
3
3
|
class Assertion
|
4
|
+
include ActiveModel::Validations
|
5
|
+
include Translatable
|
6
|
+
|
7
|
+
validate :must_match_issuer
|
8
|
+
validate :must_be_active_session
|
9
|
+
attr_reader :name
|
10
|
+
|
4
11
|
def initialize(xml_hash, configuration:)
|
12
|
+
@name = "Assertion"
|
5
13
|
@xml_hash = xml_hash
|
6
14
|
@configuration = configuration
|
7
15
|
end
|
@@ -11,7 +19,20 @@ module Saml
|
|
11
19
|
end
|
12
20
|
|
13
21
|
def signed?
|
14
|
-
|
22
|
+
signature.present?
|
23
|
+
end
|
24
|
+
|
25
|
+
def signature
|
26
|
+
xml_hash = assertion.fetch('Signature', nil)
|
27
|
+
xml_hash ? Signature.new(xml_hash) : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def expired?
|
31
|
+
Time.current > expired_at
|
32
|
+
end
|
33
|
+
|
34
|
+
def active?
|
35
|
+
Time.current > started_at && !expired?
|
15
36
|
end
|
16
37
|
|
17
38
|
def attributes
|
@@ -35,10 +56,6 @@ module Saml
|
|
35
56
|
parse_date(assertion.fetch('Conditions', {}).fetch('NotOnOrAfter', nil))
|
36
57
|
end
|
37
58
|
|
38
|
-
def certificate
|
39
|
-
assertion.fetch('Signature', {}).fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
|
40
|
-
end
|
41
|
-
|
42
59
|
def audiences
|
43
60
|
Array(assertion['Conditions']['AudienceRestriction']['Audience'])
|
44
61
|
rescue => error
|
@@ -68,6 +85,17 @@ module Saml
|
|
68
85
|
Saml::Kit.logger.error(error)
|
69
86
|
Time.at(0).to_datetime
|
70
87
|
end
|
88
|
+
|
89
|
+
def must_match_issuer
|
90
|
+
unless audiences.include?(@configuration.issuer)
|
91
|
+
errors[:audience] << error_message(:must_match_issuer)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def must_be_active_session
|
96
|
+
return if active?
|
97
|
+
errors[:base] << error_message(:expired)
|
98
|
+
end
|
71
99
|
end
|
72
100
|
end
|
73
101
|
end
|
@@ -21,7 +21,7 @@ module Saml
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def signature_for(payload)
|
24
|
-
private_key = configuration.private_keys(use: :signing).
|
24
|
+
private_key = configuration.private_keys(use: :signing).last
|
25
25
|
encode(private_key.sign(OpenSSL::Digest::SHA256.new, payload))
|
26
26
|
end
|
27
27
|
|
data/lib/saml/kit/buildable.rb
CHANGED
@@ -24,7 +24,7 @@ module Saml
|
|
24
24
|
def initialize(reference_id, configuration:)
|
25
25
|
@configuration = configuration
|
26
26
|
@reference_id = reference_id
|
27
|
-
@x509_certificate = configuration.certificates(use: :signing).
|
27
|
+
@x509_certificate = configuration.certificates(use: :signing).last.stripped
|
28
28
|
end
|
29
29
|
|
30
30
|
def signature_method
|
data/lib/saml/kit/certificate.rb
CHANGED
data/lib/saml/kit/document.rb
CHANGED
@@ -2,8 +2,9 @@ module Saml
|
|
2
2
|
module Kit
|
3
3
|
class Document
|
4
4
|
PROTOCOL_XSD = File.expand_path("./xsd/saml-schema-protocol-2.0.xsd", File.dirname(__FILE__)).freeze
|
5
|
-
include XsdValidatable
|
6
5
|
include ActiveModel::Validations
|
6
|
+
include XsdValidatable
|
7
|
+
include Translatable
|
7
8
|
include Trustable
|
8
9
|
include Buildable
|
9
10
|
validates_presence_of :content
|
data/lib/saml/kit/locales/en.yml
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
en:
|
3
3
|
saml/kit:
|
4
4
|
errors:
|
5
|
+
Assertion:
|
6
|
+
expired: "must not be expired."
|
5
7
|
AuthnRequest:
|
6
8
|
invalid: "must contain AuthnRequest."
|
7
9
|
invalid_fingerprint: "does not match."
|
@@ -17,7 +19,6 @@ en:
|
|
17
19
|
LogoutResponse:
|
18
20
|
unregistered: "is unregistered."
|
19
21
|
Response:
|
20
|
-
expired: "must not be expired."
|
21
22
|
invalid: "must contain Response."
|
22
23
|
invalid_fingerprint: "does not match."
|
23
24
|
invalid_response_to: "must match request id."
|
data/lib/saml/kit/metadata.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Saml
|
2
2
|
module Kit
|
3
3
|
class Metadata
|
4
|
+
METADATA_XSD = File.expand_path("./xsd/saml-schema-metadata-2.0.xsd", File.dirname(__FILE__)).freeze
|
4
5
|
include ActiveModel::Validations
|
5
6
|
include XsdValidatable
|
7
|
+
include Translatable
|
6
8
|
include Buildable
|
7
|
-
METADATA_XSD = File.expand_path("./xsd/saml-schema-metadata-2.0.xsd", File.dirname(__FILE__)).freeze
|
8
9
|
|
9
10
|
validates_presence_of :metadata
|
10
11
|
validate :must_contain_descriptor
|
data/lib/saml/kit/response.rb
CHANGED
@@ -4,50 +4,25 @@ module Saml
|
|
4
4
|
include Respondable
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
def_delegators :assertion, :name_id, :[], :attributes
|
7
|
+
def_delegators :assertion, :name_id, :[], :attributes
|
8
8
|
|
9
|
-
validate :
|
10
|
-
validate :must_match_issuer
|
9
|
+
validate :must_be_valid_assertion
|
11
10
|
|
12
11
|
def initialize(xml, request_id: nil, configuration: Saml::Kit.configuration)
|
13
12
|
@request_id = request_id
|
14
13
|
super(xml, name: "Response", configuration: configuration)
|
15
14
|
end
|
16
15
|
|
17
|
-
def expired?
|
18
|
-
Time.current > expired_at
|
19
|
-
end
|
20
|
-
|
21
|
-
def active?
|
22
|
-
Time.current > started_at && !expired?
|
23
|
-
end
|
24
|
-
|
25
16
|
def assertion
|
26
|
-
@assertion
|
27
|
-
end
|
28
|
-
|
29
|
-
def signed?
|
30
|
-
super || assertion.signed?
|
31
|
-
end
|
32
|
-
|
33
|
-
def certificate
|
34
|
-
super || assertion.certificate
|
17
|
+
@assertion ||= Saml::Kit::Assertion.new(to_h, configuration: @configuration)
|
35
18
|
end
|
36
19
|
|
37
20
|
private
|
38
21
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
def must_match_issuer
|
46
|
-
return unless expected_type?
|
47
|
-
return unless success?
|
48
|
-
|
49
|
-
unless audiences.include?(configuration.issuer)
|
50
|
-
errors[:audience] << error_message(:must_match_issuer)
|
22
|
+
def must_be_valid_assertion
|
23
|
+
assertion.valid?
|
24
|
+
assertion.errors.each do |attribute, error|
|
25
|
+
self.errors[attribute] << error
|
51
26
|
end
|
52
27
|
end
|
53
28
|
|
data/lib/saml/kit/signature.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
module Saml
|
2
2
|
module Kit
|
3
3
|
class Signature
|
4
|
-
|
5
|
-
|
4
|
+
def initialize(xml_hash)
|
5
|
+
@xml_hash = xml_hash
|
6
|
+
end
|
6
7
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
8
|
+
def certificate
|
9
|
+
value = to_h.fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
|
10
|
+
return if value.nil?
|
11
|
+
Saml::Kit::Certificate.new(value, use: :signing)
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def trusted?(metadata)
|
15
|
+
return false if metadata.nil?
|
16
|
+
metadata.matches?(certificate.fingerprint, use: :signing)
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
|
18
|
-
yield xml, new(xml, signatures)
|
19
|
-
signatures.complete(xml.target!)
|
19
|
+
def to_h
|
20
|
+
@xml_hash
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
data/lib/saml/kit/signatures.rb
CHANGED
@@ -14,9 +14,28 @@ module Saml
|
|
14
14
|
|
15
15
|
def complete(raw_xml)
|
16
16
|
return raw_xml unless configuration.sign?
|
17
|
-
private_key = configuration.private_keys(use: :signing).
|
17
|
+
private_key = configuration.private_keys(use: :signing).last
|
18
18
|
Xmldsig::SignedDocument.new(raw_xml).sign(private_key)
|
19
19
|
end
|
20
|
+
|
21
|
+
def self.sign(xml: ::Builder::XmlMarkup.new, configuration: Saml::Kit.configuration)
|
22
|
+
signatures = Saml::Kit::Signatures.new(configuration: configuration)
|
23
|
+
yield xml, XmlSignatureTemplate.new(xml, signatures)
|
24
|
+
signatures.complete(xml.target!)
|
25
|
+
end
|
26
|
+
|
27
|
+
class XmlSignatureTemplate
|
28
|
+
attr_reader :signatures, :xml
|
29
|
+
|
30
|
+
def initialize(xml, signatures)
|
31
|
+
@signatures = signatures
|
32
|
+
@xml = xml
|
33
|
+
end
|
34
|
+
|
35
|
+
def template(reference_id)
|
36
|
+
Template.new(signatures.build(reference_id)).to_xml(xml: xml)
|
37
|
+
end
|
38
|
+
end
|
20
39
|
end
|
21
40
|
end
|
22
41
|
end
|
data/lib/saml/kit/templatable.rb
CHANGED
@@ -21,7 +21,7 @@ module Saml
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def encryption_for(xml:)
|
24
|
-
if encrypt
|
24
|
+
if encrypt?
|
25
25
|
temp = ::Builder::XmlMarkup.new
|
26
26
|
yield temp
|
27
27
|
xml_encryption = Saml::Kit::Builders::XmlEncryption.new(temp.target!, encryption_certificate.public_key)
|
@@ -31,6 +31,10 @@ module Saml
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def encrypt?
|
35
|
+
encrypt && encryption_certificate
|
36
|
+
end
|
37
|
+
|
34
38
|
def render(model, options)
|
35
39
|
Saml::Kit::Template.new(model).to_xml(options)
|
36
40
|
end
|
data/lib/saml/kit/trustable.rb
CHANGED
@@ -9,24 +9,18 @@ module Saml
|
|
9
9
|
validate :must_be_trusted, unless: :signature_manually_verified
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
to_h.fetch(name, {}).fetch('Signature', {}).fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
|
15
|
-
end
|
16
|
-
|
17
|
-
def fingerprint
|
18
|
-
return if certificate.blank?
|
19
|
-
Fingerprint.new(certificate)
|
12
|
+
def signed?
|
13
|
+
signature.present?
|
20
14
|
end
|
21
15
|
|
22
|
-
def
|
23
|
-
to_h.fetch(name, {}).fetch('Signature', nil)
|
16
|
+
def signature
|
17
|
+
xml_hash = to_h.fetch(name, {}).fetch('Signature', nil)
|
18
|
+
xml_hash ? Signature.new(xml_hash) : nil
|
24
19
|
end
|
25
20
|
|
26
21
|
def trusted?
|
27
|
-
return false if provider.nil?
|
28
22
|
return false unless signed?
|
29
|
-
|
23
|
+
signature.trusted?(provider)
|
30
24
|
end
|
31
25
|
|
32
26
|
def provider
|
@@ -59,6 +53,7 @@ module Saml
|
|
59
53
|
|
60
54
|
def must_be_trusted
|
61
55
|
return if trusted?
|
56
|
+
return if provider.present? && !signed?
|
62
57
|
errors[:fingerprint] << error_message(:invalid_fingerprint)
|
63
58
|
end
|
64
59
|
end
|
data/lib/saml/kit/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saml-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mo khan
|
@@ -246,6 +246,7 @@ files:
|
|
246
246
|
- lib/saml/kit/signatures.rb
|
247
247
|
- lib/saml/kit/templatable.rb
|
248
248
|
- lib/saml/kit/template.rb
|
249
|
+
- lib/saml/kit/translatable.rb
|
249
250
|
- lib/saml/kit/trustable.rb
|
250
251
|
- lib/saml/kit/version.rb
|
251
252
|
- lib/saml/kit/xml.rb
|