saml-kit 1.0.15 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -5
- data/exe/saml-kit-create-self-signed-certificate +6 -2
- data/exe/saml-kit-decode-http-post +2 -1
- data/exe/saml-kit-decode-http-redirect +2 -1
- data/lib/saml/kit/assertion.rb +22 -48
- data/lib/saml/kit/attribute_statement.rb +25 -0
- data/lib/saml/kit/authentication_request.rb +34 -15
- data/lib/saml/kit/bindings/binding.rb +4 -7
- data/lib/saml/kit/bindings/http_post.rb +6 -2
- data/lib/saml/kit/bindings/http_redirect.rb +8 -5
- data/lib/saml/kit/bindings/url_builder.rb +7 -7
- data/lib/saml/kit/bindings.rb +4 -3
- data/lib/saml/kit/builders/assertion.rb +6 -3
- data/lib/saml/kit/builders/authentication_request.rb +4 -2
- data/lib/saml/kit/builders/encrypted_assertion.rb +3 -1
- data/lib/saml/kit/builders/identity_provider_metadata.rb +14 -4
- data/lib/saml/kit/builders/metadata.rb +8 -4
- data/lib/saml/kit/builders/null.rb +0 -1
- data/lib/saml/kit/builders/response.rb +14 -5
- data/lib/saml/kit/builders/service_provider_metadata.rb +10 -3
- data/lib/saml/kit/builders.rb +0 -1
- data/lib/saml/kit/composite_metadata.rb +18 -3
- data/lib/saml/kit/{buildable.rb → concerns/buildable.rb} +0 -0
- data/lib/saml/kit/{requestable.rb → concerns/requestable.rb} +0 -0
- data/lib/saml/kit/{respondable.rb → concerns/respondable.rb} +0 -0
- data/lib/saml/kit/{serializable.rb → concerns/serializable.rb} +0 -0
- data/lib/saml/kit/{translatable.rb → concerns/translatable.rb} +0 -0
- data/lib/saml/kit/{trustable.rb → concerns/trustable.rb} +9 -7
- data/lib/saml/kit/concerns/xml_parseable.rb +62 -0
- data/lib/saml/kit/{xml_templatable.rb → concerns/xml_templatable.rb} +3 -2
- data/lib/saml/kit/{xsd_validatable.rb → concerns/xsd_validatable.rb} +10 -0
- data/lib/saml/kit/conditions.rb +37 -0
- data/lib/saml/kit/configuration.rb +28 -10
- data/lib/saml/kit/default_registry.rb +19 -4
- data/lib/saml/kit/document.rb +21 -67
- data/lib/saml/kit/identity_provider_metadata.rb +34 -15
- data/lib/saml/kit/invalid_document.rb +1 -1
- data/lib/saml/kit/logout_request.rb +11 -6
- data/lib/saml/kit/logout_response.rb +3 -1
- data/lib/saml/kit/metadata.rb +63 -109
- data/lib/saml/kit/namespaces.rb +2 -1
- data/lib/saml/kit/organization.rb +36 -0
- data/lib/saml/kit/parser.rb +28 -0
- data/lib/saml/kit/response.rb +10 -2
- data/lib/saml/kit/rspec/have_xpath.rb +4 -2
- data/lib/saml/kit/service_provider_metadata.rb +2 -1
- data/lib/saml/kit/signature.rb +21 -5
- data/lib/saml/kit/version.rb +1 -1
- data/lib/saml/kit.rb +14 -7
- data/saml-kit.gemspec +0 -1
- metadata +16 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 870747d355b7bcad61bc1d7c502492b74d34e3d374b11134b0f39acebf5b6bb0
|
4
|
+
data.tar.gz: 3c683b3ce55dcefc468e2e5ff4c9a103fd82b4f314b4e0e2bc41e0f6461b1c3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01243f10344d2615911d3d9d139e2a39f3a08afe1c66badf311208947d16ee51276977df6e32a52ca085962e952bc470f72e07982c944b40d6b36d11450e453c
|
7
|
+
data.tar.gz: 84d3a97162a0f01cc2a31b484539a97f92ff452c5c406020318d32a3e3719381825e02c3fd0ce08e43d4597f8701587e1e047f9e0e19ad57bdaf87f122225de5
|
data/Rakefile
CHANGED
@@ -2,16 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'bundler/audit/task'
|
4
4
|
require 'bundler/gem_tasks'
|
5
|
-
require 'reek/rake/task'
|
6
5
|
require 'rspec/core/rake_task'
|
7
6
|
require 'rubocop/rake_task'
|
8
7
|
|
9
8
|
RSpec::Core::RakeTask.new(:spec)
|
10
9
|
RuboCop::RakeTask.new(:rubocop)
|
11
10
|
Bundler::Audit::Task.new
|
12
|
-
Reek::Rake::Task.new(:reek) do |task|
|
13
|
-
task.config_file = '.reek'
|
14
|
-
end
|
15
11
|
|
16
|
-
task lint: [:rubocop,
|
12
|
+
task lint: [:rubocop, 'bundle:audit']
|
17
13
|
task default: :spec
|
@@ -3,11 +3,15 @@
|
|
3
3
|
|
4
4
|
require 'saml/kit'
|
5
5
|
|
6
|
-
|
6
|
+
message = "Use the 'saml-kit-cli' gem instead."\
|
7
|
+
' saml-kit-create-self-signed-certificate'
|
8
|
+
Saml::Kit.deprecate(message)
|
7
9
|
|
8
10
|
puts 'Enter Passphrase:'
|
9
11
|
passphrase = STDIN.read.strip
|
10
|
-
certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new.create(
|
12
|
+
certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new.create(
|
13
|
+
passphrase: passphrase
|
14
|
+
)
|
11
15
|
|
12
16
|
puts '** BEGIN File Format **'
|
13
17
|
print certificate
|
@@ -3,7 +3,8 @@
|
|
3
3
|
|
4
4
|
require 'saml/kit'
|
5
5
|
|
6
|
-
|
6
|
+
message = "Use the 'saml-kit-cli' gem instead. saml-kit-decode-http-post"
|
7
|
+
Saml::Kit.deprecate(message)
|
7
8
|
|
8
9
|
saml = STDIN.read
|
9
10
|
binding = Saml::Kit::Bindings::HttpPost.new(location: '')
|
@@ -3,7 +3,8 @@
|
|
3
3
|
|
4
4
|
require 'saml/kit'
|
5
5
|
|
6
|
-
|
6
|
+
message = "Use the 'saml-kit-cli' gem instead. saml-kit-decode-http-redirect*"
|
7
|
+
Saml::Kit.deprecate(message)
|
7
8
|
|
8
9
|
input = STDIN.read
|
9
10
|
binding = Saml::Kit::Bindings::HttpRedirect.new(location: '')
|
data/lib/saml/kit/assertion.rb
CHANGED
@@ -8,10 +8,14 @@ module Saml
|
|
8
8
|
class Assertion
|
9
9
|
include ActiveModel::Validations
|
10
10
|
include Translatable
|
11
|
+
include XmlParseable
|
12
|
+
extend Forwardable
|
11
13
|
XPATH = [
|
12
14
|
'/samlp:Response/saml:Assertion',
|
13
15
|
'/samlp:Response/saml:EncryptedAssertion'
|
14
16
|
].join('|')
|
17
|
+
def_delegators :conditions, :started_at, :expired_at, :audiences
|
18
|
+
def_delegators :attribute_statement, :attributes
|
15
19
|
|
16
20
|
validate :must_be_decryptable
|
17
21
|
validate :must_match_issuer, if: :decryptable?
|
@@ -20,15 +24,17 @@ module Saml
|
|
20
24
|
attr_reader :name
|
21
25
|
attr_accessor :occurred_at
|
22
26
|
|
23
|
-
def initialize(
|
27
|
+
def initialize(
|
28
|
+
node, configuration: Saml::Kit.configuration, private_keys: []
|
29
|
+
)
|
24
30
|
@name = 'Assertion'
|
25
|
-
@
|
31
|
+
@to_nokogiri = node
|
26
32
|
@configuration = configuration
|
27
33
|
@occurred_at = Time.current
|
28
34
|
@cannot_decrypt = false
|
29
35
|
@encrypted = false
|
30
|
-
|
31
|
-
decrypt(::Xml::Kit::Decryption.new(private_keys:
|
36
|
+
keys = configuration.private_keys(use: :encryption) + private_keys
|
37
|
+
decrypt(::Xml::Kit::Decryption.new(private_keys: keys.uniq))
|
32
38
|
end
|
33
39
|
|
34
40
|
def issuer
|
@@ -39,6 +45,10 @@ module Saml
|
|
39
45
|
at_xpath('./saml:Subject/saml:NameID').try(:text)
|
40
46
|
end
|
41
47
|
|
48
|
+
def name_id_format
|
49
|
+
at_xpath('./saml:Subject/saml:NameID').attribute('Format').try(:value)
|
50
|
+
end
|
51
|
+
|
42
52
|
def signed?
|
43
53
|
signature.present?
|
44
54
|
end
|
@@ -56,23 +66,13 @@ module Saml
|
|
56
66
|
now > drifted_started_at && !expired?(now)
|
57
67
|
end
|
58
68
|
|
59
|
-
def
|
60
|
-
@
|
61
|
-
|
62
|
-
memo
|
63
|
-
end.with_indifferent_access
|
69
|
+
def attribute_statement
|
70
|
+
@attribute_statement ||=
|
71
|
+
AttributeStatement.new(search('./saml:AttributeStatement'))
|
64
72
|
end
|
65
73
|
|
66
|
-
def
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def expired_at
|
71
|
-
parse_date(at_xpath('./saml:Conditions/@NotOnOrAfter').try(:value))
|
72
|
-
end
|
73
|
-
|
74
|
-
def audiences
|
75
|
-
search('./saml:Conditions/saml:AudienceRestriction/saml:Audience').map(&:text)
|
74
|
+
def conditions
|
75
|
+
@conditions ||= Conditions.new(search('./saml:Conditions'))
|
76
76
|
end
|
77
77
|
|
78
78
|
def encrypted?
|
@@ -84,16 +84,8 @@ module Saml
|
|
84
84
|
!@cannot_decrypt
|
85
85
|
end
|
86
86
|
|
87
|
-
def present?
|
88
|
-
@node.present?
|
89
|
-
end
|
90
|
-
|
91
|
-
def to_xml(pretty: nil)
|
92
|
-
pretty ? @node.to_xml(indent: 2) : to_s
|
93
|
-
end
|
94
|
-
|
95
87
|
def to_s
|
96
|
-
@
|
88
|
+
@to_nokogiri.to_s
|
97
89
|
end
|
98
90
|
|
99
91
|
private
|
@@ -104,22 +96,14 @@ module Saml
|
|
104
96
|
encrypted_assertion = at_xpath('./xmlenc:EncryptedData')
|
105
97
|
@encrypted = encrypted_assertion.present?
|
106
98
|
return unless @encrypted
|
107
|
-
@
|
99
|
+
@to_nokogiri = decryptor.decrypt_node(encrypted_assertion)
|
108
100
|
rescue Xml::Kit::DecryptionError => error
|
109
101
|
@cannot_decrypt = true
|
110
102
|
Saml::Kit.logger.error(error)
|
111
103
|
end
|
112
104
|
|
113
|
-
def parse_date(value)
|
114
|
-
DateTime.parse(value)
|
115
|
-
rescue StandardError => error
|
116
|
-
Saml::Kit.logger.error(error)
|
117
|
-
Time.at(0).to_datetime
|
118
|
-
end
|
119
|
-
|
120
105
|
def must_match_issuer
|
121
|
-
return if audiences.empty?
|
122
|
-
return if audiences.include?(configuration.entity_id)
|
106
|
+
return if audiences.empty? || audiences.include?(configuration.entity_id)
|
123
107
|
errors[:audience] << error_message(:must_match_issuer)
|
124
108
|
end
|
125
109
|
|
@@ -130,7 +114,6 @@ module Saml
|
|
130
114
|
|
131
115
|
def must_have_valid_signature
|
132
116
|
return if !signed? || signature.valid?
|
133
|
-
|
134
117
|
signature.errors.each do |attribute, message|
|
135
118
|
errors.add(attribute, message)
|
136
119
|
end
|
@@ -139,15 +122,6 @@ module Saml
|
|
139
122
|
def must_be_decryptable
|
140
123
|
errors.add(:base, error_message(:cannot_decrypt)) unless decryptable?
|
141
124
|
end
|
142
|
-
|
143
|
-
def at_xpath(xpath)
|
144
|
-
return unless @node
|
145
|
-
@node.at_xpath(xpath, Saml::Kit::Document::NAMESPACES)
|
146
|
-
end
|
147
|
-
|
148
|
-
def search(xpath)
|
149
|
-
@node.search(xpath, Saml::Kit::Document::NAMESPACES)
|
150
|
-
end
|
151
125
|
end
|
152
126
|
end
|
153
127
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Saml
|
4
|
+
module Kit
|
5
|
+
class AttributeStatement
|
6
|
+
include XmlParseable
|
7
|
+
|
8
|
+
attr_reader :content
|
9
|
+
|
10
|
+
def initialize(node)
|
11
|
+
@to_nokogiri = node
|
12
|
+
@content = node.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
@attributes ||= search('./saml:Attribute').inject({}) do |memo, item|
|
17
|
+
namespace = Saml::Kit::Document::NAMESPACES
|
18
|
+
attribute = item.at_xpath('./saml:AttributeValue', namespace)
|
19
|
+
memo[item.attribute('Name').value] = attribute.try(:text)
|
20
|
+
memo
|
21
|
+
end.with_indifferent_access
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -11,9 +11,17 @@ module Saml
|
|
11
11
|
# end
|
12
12
|
#
|
13
13
|
# <?xml version="1.0" encoding="UTF-8"?>
|
14
|
-
# <samlp:AuthnRequest
|
14
|
+
# <samlp:AuthnRequest
|
15
|
+
# xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
16
|
+
# xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
17
|
+
# ID="_ca3a0e72-9530-41f1-9518-c53716de88b2"
|
18
|
+
# Version="2.0"
|
19
|
+
# IssueInstant="2017-12-19T16:27:44Z"
|
20
|
+
# Destination="http://hartmann.info"
|
21
|
+
# AssertionConsumerServiceURL="https://carroll.com/acs">
|
15
22
|
# <saml:Issuer>Day of the Dangerous Cousins</saml:Issuer>
|
16
|
-
# <samlp:NameIDPolicy
|
23
|
+
# <samlp:NameIDPolicy
|
24
|
+
# Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>
|
17
25
|
# </samlp:AuthnRequest>
|
18
26
|
#
|
19
27
|
# Example:
|
@@ -25,13 +33,16 @@ module Saml
|
|
25
33
|
# Create an instance of an AuthnRequest document.
|
26
34
|
#
|
27
35
|
# @param xml [String] the raw xml.
|
28
|
-
# @param configuration [Saml::Kit::Configuration] defaults to the global
|
36
|
+
# @param configuration [Saml::Kit::Configuration] defaults to the global
|
37
|
+
# configuration.
|
29
38
|
def initialize(xml, configuration: Saml::Kit.configuration)
|
30
39
|
super(xml, name: 'AuthnRequest', configuration: configuration)
|
31
40
|
end
|
32
41
|
|
33
42
|
# Extract the AssertionConsumerServiceURL from the AuthnRequest
|
34
|
-
# <samlp:AuthnRequest
|
43
|
+
# <samlp:AuthnRequest
|
44
|
+
# AssertionConsumerServiceURL="https://carroll.com/acs">
|
45
|
+
# </samlp:AuthnRequest>
|
35
46
|
def assertion_consumer_service_url
|
36
47
|
at_xpath('./*/@AssertionConsumerServiceURL').try(:value)
|
37
48
|
end
|
@@ -42,23 +53,31 @@ module Saml
|
|
42
53
|
|
43
54
|
# Extract the NameIDPolicy from the AuthnRequest
|
44
55
|
# <samlp:AuthnRequest>
|
45
|
-
# <samlp:NameIDPolicy
|
56
|
+
# <samlp:NameIDPolicy
|
57
|
+
# Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>
|
46
58
|
# </samlp:AuthnRequest>
|
47
59
|
def name_id_policy
|
48
60
|
at_xpath('./*/samlp:NameIDPolicy/@Format').try(:value)
|
49
61
|
end
|
50
62
|
|
51
63
|
# Generate a Response for a specific user.
|
52
|
-
# @param user [Object] this is a custom user object that can be used for
|
53
|
-
#
|
54
|
-
# @param
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
# @param user [Object] this is a custom user object that can be used for
|
65
|
+
# generating a nameid and assertion attributes.
|
66
|
+
# @param binding [Symbol] the SAML binding to use
|
67
|
+
# `:http_post` or `:http_redirect`.
|
68
|
+
# @param configuration [Saml::Kit::Configuration] the configuration to
|
69
|
+
# use to build the response.
|
70
|
+
def response_for(
|
71
|
+
user, binding:, relay_state: nil, configuration: Saml::Kit.configuration
|
72
|
+
)
|
73
|
+
response =
|
74
|
+
Response.builder(user, self, configuration: configuration) do |x|
|
75
|
+
x.embed_signature = provider.want_assertions_signed
|
76
|
+
yield x if block_given?
|
77
|
+
end
|
78
|
+
provider
|
79
|
+
.assertion_consumer_service_for(binding: binding)
|
80
|
+
.serialize(response, relay_state: relay_state)
|
62
81
|
end
|
63
82
|
end
|
64
83
|
end
|
@@ -56,13 +56,10 @@ module Saml
|
|
56
56
|
SAMLRequest: params[:SAMLRequest] || params['SAMLRequest'],
|
57
57
|
SAMLResponse: params[:SAMLResponse] || params['SAMLResponse'],
|
58
58
|
}
|
59
|
-
if parameters[:SAMLRequest].present?
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
else
|
64
|
-
raise ArgumentError, 'SAMLRequest or SAMLResponse parameter is required.'
|
65
|
-
end
|
59
|
+
return parameters[:SAMLRequest] if parameters[:SAMLRequest].present?
|
60
|
+
return parameters[:SAMLResponse] if parameters[:SAMLResponse].present?
|
61
|
+
message = 'SAMLRequest or SAMLResponse parameter is required.'
|
62
|
+
raise ArgumentError, message
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
@@ -19,8 +19,9 @@ module Saml
|
|
19
19
|
def serialize(builder, relay_state: nil)
|
20
20
|
builder.destination = location
|
21
21
|
document = builder.build
|
22
|
+
xml = document.to_xml
|
22
23
|
saml_params = {
|
23
|
-
document.query_string_parameter => Base64.strict_encode64(
|
24
|
+
document.query_string_parameter => Base64.strict_encode64(xml),
|
24
25
|
}
|
25
26
|
saml_params['RelayState'] = relay_state if relay_state.present?
|
26
27
|
[location, saml_params]
|
@@ -28,7 +29,10 @@ module Saml
|
|
28
29
|
|
29
30
|
def deserialize(params, configuration: Saml::Kit.configuration)
|
30
31
|
xml = decode(saml_param_from(params))
|
31
|
-
Saml::Kit::Document.to_saml_document(
|
32
|
+
Saml::Kit::Document.to_saml_document(
|
33
|
+
xml,
|
34
|
+
configuration: configuration
|
35
|
+
)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -20,7 +20,8 @@ module Saml
|
|
20
20
|
builder.embed_signature = false
|
21
21
|
builder.destination = location
|
22
22
|
document = builder.build
|
23
|
-
|
23
|
+
url_builder = UrlBuilder.new(configuration: builder.configuration)
|
24
|
+
[url_builder.build(document, relay_state: relay_state), {}]
|
24
25
|
end
|
25
26
|
|
26
27
|
def deserialize(params, configuration: Saml::Kit.configuration)
|
@@ -34,18 +35,20 @@ module Saml
|
|
34
35
|
|
35
36
|
def deserialize_document_from(params, configuration)
|
36
37
|
xml = inflate(decode(unescape(saml_param_from(params))))
|
37
|
-
Saml::Kit::Document.to_saml_document(
|
38
|
+
Saml::Kit::Document.to_saml_document(
|
39
|
+
xml,
|
40
|
+
configuration: configuration
|
41
|
+
)
|
38
42
|
end
|
39
43
|
|
40
44
|
def ensure_valid_signature(params, document)
|
41
45
|
signature = params[:Signature]
|
42
|
-
algorithm = params[:SigAlg]
|
43
46
|
provider = document.provider
|
44
|
-
return if signature.blank? ||
|
47
|
+
return if signature.blank? || params[:SigAlg].blank?
|
45
48
|
return if provider.nil?
|
46
49
|
|
47
50
|
return document.signature_verified! if provider.verify(
|
48
|
-
algorithm_for(
|
51
|
+
algorithm_for(params[:SigAlg]),
|
49
52
|
decode(signature),
|
50
53
|
canonicalize(params)
|
51
54
|
)
|
@@ -17,17 +17,16 @@ module Saml
|
|
17
17
|
@configuration = configuration
|
18
18
|
end
|
19
19
|
|
20
|
-
def build(
|
21
|
-
destination =
|
20
|
+
def build(document, relay_state: nil)
|
21
|
+
destination = document.destination
|
22
22
|
if configuration.sign?
|
23
|
-
payload = canonicalize(
|
23
|
+
payload = canonicalize(document, relay_state)
|
24
24
|
"#{destination}?#{payload}&Signature=#{signature_for(payload)}"
|
25
25
|
else
|
26
|
-
|
27
|
-
|
26
|
+
"#{destination}?" + to_query_string(
|
27
|
+
document.query_string_parameter => serialize(document.to_xml),
|
28
28
|
'RelayState' => relay_state
|
29
29
|
)
|
30
|
-
"#{destination}?#{payload}"
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
@@ -39,8 +38,9 @@ module Saml
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def canonicalize(saml_document, relay_state)
|
41
|
+
xml = saml_document.to_xml
|
42
42
|
to_query_string(
|
43
|
-
saml_document.query_string_parameter => serialize(
|
43
|
+
saml_document.query_string_parameter => serialize(xml),
|
44
44
|
'RelayState' => relay_state,
|
45
45
|
'SigAlg' => ::Xml::Kit::Namespaces::SHA256
|
46
46
|
)
|
data/lib/saml/kit/bindings.rb
CHANGED
@@ -11,9 +11,10 @@ module Saml
|
|
11
11
|
# the different SAML bindings that are
|
12
12
|
# supported by this gem.
|
13
13
|
module Bindings
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
BINDINGS_2_0 = 'urn:oasis:names:tc:SAML:2.0:bindings'.freeze
|
15
|
+
HTTP_ARTIFACT = "#{BINDINGS_2_0}:HTTP-Artifact".freeze
|
16
|
+
HTTP_POST = "#{BINDINGS_2_0}:HTTP-POST".freeze
|
17
|
+
HTTP_REDIRECT = "#{BINDINGS_2_0}:HTTP-Redirect".freeze
|
17
18
|
ALL = {
|
18
19
|
http_post: HTTP_POST,
|
19
20
|
http_redirect: HTTP_REDIRECT,
|
@@ -9,7 +9,9 @@ module Saml
|
|
9
9
|
include XmlTemplatable
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
def_delegators :@response_builder,
|
12
|
+
def_delegators :@response_builder,
|
13
|
+
:request, :issuer, :reference_id, :now, :configuration, :user,
|
14
|
+
:version, :destination
|
13
15
|
|
14
16
|
def initialize(response_builder, embed_signature)
|
15
17
|
@response_builder = response_builder
|
@@ -17,7 +19,7 @@ module Saml
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def name_id_format
|
20
|
-
request.try(:name_id_format)
|
22
|
+
request.try(:name_id_format)
|
21
23
|
end
|
22
24
|
|
23
25
|
def name_id
|
@@ -62,7 +64,8 @@ module Saml
|
|
62
64
|
{
|
63
65
|
AuthnInstant: now.iso8601,
|
64
66
|
SessionIndex: reference_id,
|
65
|
-
SessionNotOnOrAfter:
|
67
|
+
SessionNotOnOrAfter:
|
68
|
+
configuration.session_timeout.since(now).utc.iso8601,
|
66
69
|
}
|
67
70
|
end
|
68
71
|
end
|
@@ -7,7 +7,8 @@ module Saml
|
|
7
7
|
# {include:file:spec/saml/kit/builders/authentication_request_spec.rb}
|
8
8
|
class AuthenticationRequest
|
9
9
|
include XmlTemplatable
|
10
|
-
attr_accessor :id, :now, :issuer, :assertion_consumer_service_url
|
10
|
+
attr_accessor :id, :now, :issuer, :assertion_consumer_service_url
|
11
|
+
attr_accessor :name_id_format, :destination
|
11
12
|
attr_accessor :version
|
12
13
|
attr_reader :configuration
|
13
14
|
|
@@ -36,7 +37,8 @@ module Saml
|
|
36
37
|
Destination: destination,
|
37
38
|
}
|
38
39
|
if assertion_consumer_service_url.present?
|
39
|
-
options[:AssertionConsumerServiceURL] =
|
40
|
+
options[:AssertionConsumerServiceURL] =
|
41
|
+
assertion_consumer_service_url
|
40
42
|
end
|
41
43
|
options
|
42
44
|
end
|
@@ -10,7 +10,9 @@ module Saml
|
|
10
10
|
extend Forwardable
|
11
11
|
|
12
12
|
attr_reader :assertion
|
13
|
-
def_delegators :@response_builder,
|
13
|
+
def_delegators :@response_builder,
|
14
|
+
:configuration,
|
15
|
+
:encryption_certificate
|
14
16
|
|
15
17
|
def initialize(response_builder, assertion)
|
16
18
|
@response_builder = response_builder
|
@@ -13,7 +13,9 @@ module Saml
|
|
13
13
|
attr_reader :logout_urls, :single_sign_on_urls
|
14
14
|
attr_reader :configuration
|
15
15
|
attr_reader :metadata
|
16
|
-
def_delegators :metadata, :id, :id=, :entity_id, :entity_id=,
|
16
|
+
def_delegators :metadata, :id, :id=, :entity_id, :entity_id=,
|
17
|
+
:organization_name, :organization_name=, :organization_url,
|
18
|
+
:organization_url=, :contact_email, :contact_email=, :to_xml
|
17
19
|
|
18
20
|
def initialize(configuration: Saml::Kit.configuration)
|
19
21
|
@attributes = []
|
@@ -24,16 +26,24 @@ module Saml
|
|
24
26
|
@name_id_formats = [Namespaces::PERSISTENT]
|
25
27
|
@single_sign_on_urls = []
|
26
28
|
@want_authn_requests_signed = true
|
27
|
-
@metadata = Saml::Kit::Builders::Metadata.new(
|
29
|
+
@metadata = Saml::Kit::Builders::Metadata.new(
|
30
|
+
configuration: configuration
|
31
|
+
)
|
28
32
|
@metadata.identity_provider = self
|
29
33
|
end
|
30
34
|
|
31
35
|
def add_single_sign_on_service(url, binding: :http_post)
|
32
|
-
@single_sign_on_urls.push(
|
36
|
+
@single_sign_on_urls.push(
|
37
|
+
location: url,
|
38
|
+
binding: Bindings.binding_for(binding)
|
39
|
+
)
|
33
40
|
end
|
34
41
|
|
35
42
|
def add_single_logout_service(url, binding: :http_post)
|
36
|
-
@logout_urls.push(
|
43
|
+
@logout_urls.push(
|
44
|
+
location: url,
|
45
|
+
binding: Bindings.binding_for(binding)
|
46
|
+
)
|
37
47
|
end
|
38
48
|
|
39
49
|
def build
|
@@ -22,14 +22,18 @@ module Saml
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def build_service_provider
|
25
|
-
@service_provider = Saml::Kit::ServiceProviderMetadata.builder(
|
26
|
-
|
25
|
+
@service_provider = Saml::Kit::ServiceProviderMetadata.builder(
|
26
|
+
configuration: configuration
|
27
|
+
) do |x|
|
28
|
+
yield x if block_given?
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def build_identity_provider
|
31
|
-
@identity_provider = Saml::Kit::IdentityProviderMetadata.builder(
|
32
|
-
|
33
|
+
@identity_provider = Saml::Kit::IdentityProviderMetadata.builder(
|
34
|
+
configuration: configuration
|
35
|
+
) do |x|
|
36
|
+
yield x if block_given?
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
@@ -13,7 +13,9 @@ module Saml
|
|
13
13
|
attr_accessor :issuer, :destination
|
14
14
|
attr_reader :configuration
|
15
15
|
|
16
|
-
def initialize(
|
16
|
+
def initialize(
|
17
|
+
user, request = nil, configuration: Saml::Kit.configuration
|
18
|
+
)
|
17
19
|
@user = user
|
18
20
|
@request = request
|
19
21
|
@id = ::Xml::Kit::Id.generate
|
@@ -23,23 +25,30 @@ module Saml
|
|
23
25
|
@status_code = Namespaces::SUCCESS
|
24
26
|
@status_message = nil
|
25
27
|
@issuer = configuration.entity_id
|
26
|
-
@encryption_certificate = request.try(:provider)
|
28
|
+
@encryption_certificate = request.try(:provider)
|
29
|
+
.try(:encryption_certificates).try(:last)
|
27
30
|
@encrypt = encryption_certificate.present?
|
28
31
|
@configuration = configuration
|
29
32
|
end
|
30
33
|
|
31
34
|
def build
|
32
|
-
Saml::Kit::Response.new(
|
35
|
+
Saml::Kit::Response.new(
|
36
|
+
to_xml,
|
37
|
+
request_id: request.try(:id),
|
38
|
+
configuration: configuration
|
39
|
+
)
|
33
40
|
end
|
34
41
|
|
35
42
|
def assertion=(value)
|
36
|
-
@assertion = value
|
43
|
+
@assertion = value || Null.new
|
37
44
|
end
|
38
45
|
|
39
46
|
def assertion
|
40
47
|
@assertion ||=
|
41
48
|
begin
|
42
|
-
assertion = Saml::Kit::Builders::Assertion.new(
|
49
|
+
assertion = Saml::Kit::Builders::Assertion.new(
|
50
|
+
self, embed_signature
|
51
|
+
)
|
43
52
|
if encrypt
|
44
53
|
Saml::Kit::Builders::EncryptedAssertion.new(self, assertion)
|
45
54
|
else
|
@@ -12,7 +12,9 @@ module Saml
|
|
12
12
|
attr_accessor :want_assertions_signed
|
13
13
|
attr_reader :configuration
|
14
14
|
attr_reader :metadata
|
15
|
-
def_delegators :metadata, :id, :id=, :entity_id, :entity_id=,
|
15
|
+
def_delegators :metadata, :id, :id=, :entity_id, :entity_id=,
|
16
|
+
:organization_name, :organization_name=, :organization_url,
|
17
|
+
:organization_url=, :contact_email, :contact_email=, :to_xml
|
16
18
|
|
17
19
|
def initialize(configuration: Saml::Kit.configuration)
|
18
20
|
@acs_urls = []
|
@@ -20,7 +22,9 @@ module Saml
|
|
20
22
|
@logout_urls = []
|
21
23
|
@name_id_formats = [Namespaces::PERSISTENT]
|
22
24
|
@want_assertions_signed = true
|
23
|
-
@metadata = Saml::Kit::Builders::Metadata.new(
|
25
|
+
@metadata = Saml::Kit::Builders::Metadata.new(
|
26
|
+
configuration: configuration
|
27
|
+
)
|
24
28
|
@metadata.service_provider = self
|
25
29
|
end
|
26
30
|
|
@@ -29,7 +33,10 @@ module Saml
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def add_single_logout_service(url, binding: :http_post)
|
32
|
-
@logout_urls.push(
|
36
|
+
@logout_urls.push(
|
37
|
+
location: url,
|
38
|
+
binding: Bindings.binding_for(binding)
|
39
|
+
)
|
33
40
|
end
|
34
41
|
|
35
42
|
def build
|