saml-kit 1.0.15 → 1.0.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|