saml_idp 0.7.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -1
- data/README.md +41 -13
- data/lib/saml_idp/configurator.rb +5 -1
- data/lib/saml_idp/controller.rb +9 -5
- data/lib/saml_idp/incoming_metadata.rb +22 -1
- data/lib/saml_idp/metadata_builder.rb +23 -8
- data/lib/saml_idp/persisted_metadata.rb +4 -0
- data/lib/saml_idp/request.rb +22 -3
- data/lib/saml_idp/response_builder.rb +19 -5
- data/lib/saml_idp/saml_response.rb +15 -3
- data/lib/saml_idp/service_provider.rb +15 -6
- data/lib/saml_idp/signable.rb +1 -2
- data/lib/saml_idp/version.rb +1 -1
- data/lib/saml_idp/xml_security.rb +1 -1
- data/saml_idp.gemspec +25 -23
- data/spec/acceptance/idp_controller_spec.rb +5 -4
- data/spec/lib/saml_idp/algorithmable_spec.rb +6 -6
- data/spec/lib/saml_idp/assertion_builder_spec.rb +8 -8
- data/spec/lib/saml_idp/attribute_decorator_spec.rb +8 -8
- data/spec/lib/saml_idp/configurator_spec.rb +8 -7
- data/spec/lib/saml_idp/controller_spec.rb +47 -20
- data/spec/lib/saml_idp/encryptor_spec.rb +4 -4
- data/spec/lib/saml_idp/incoming_metadata_spec.rb +60 -0
- data/spec/lib/saml_idp/metadata_builder_spec.rb +30 -17
- data/spec/lib/saml_idp/name_id_formatter_spec.rb +3 -3
- data/spec/lib/saml_idp/request_spec.rb +22 -22
- data/spec/lib/saml_idp/response_builder_spec.rb +5 -3
- data/spec/lib/saml_idp/saml_response_spec.rb +31 -8
- data/spec/lib/saml_idp/service_provider_spec.rb +2 -2
- data/spec/lib/saml_idp/signable_spec.rb +1 -1
- data/spec/lib/saml_idp/signature_builder_spec.rb +2 -2
- data/spec/lib/saml_idp/signed_info_builder_spec.rb +3 -3
- data/spec/rails_app/app/controllers/saml_controller.rb +5 -1
- data/spec/rails_app/config/application.rb +0 -6
- data/spec/rails_app/config/environments/development.rb +1 -6
- data/spec/rails_app/config/environments/production.rb +1 -0
- data/spec/rails_app/config/environments/test.rb +1 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/certificates/sp_cert_req.csr +12 -0
- data/spec/support/certificates/sp_private_key.pem +16 -0
- data/spec/support/certificates/sp_x509_cert.crt +18 -0
- data/spec/support/saml_request_macros.rb +64 -4
- data/spec/support/security_helpers.rb +10 -0
- data/spec/xml_security_spec.rb +12 -12
- metadata +89 -52
- data/spec/lib/saml_idp/.assertion_builder_spec.rb.swp +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f04deecaf7c0bd7c5655134d314a4b95b9438b24b67e83d7b160d9fa2232f2fc
|
4
|
+
data.tar.gz: b999a0a1f97e85e34704bfe35d3dddb89eebcfbfe1723be5e9dfcfb17e511ef5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94921b45008f31783c0428992b9cad6b4b1098ad312fd721987d0d27f89921f286f7bd8960237b5f371f8ccb23cac1a6c8b6c7aa110fcf4318a0b63b52497e9e
|
7
|
+
data.tar.gz: e142a4c38d3604dc033d0cfef0a298fbb094d5d36939518558aa219d6bd16ca753960fcc553c076e9969e031946e56d10ef3ba0c1505fcf9df3f7ee62ecdab11
|
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source "
|
1
|
+
source "https://rubygems.org"
|
2
2
|
gemspec
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Ruby SAML Identity Provider (IdP)
|
2
|
+
|
2
3
|
Forked from https://github.com/lawrencepit/ruby-saml-idp
|
3
4
|
|
4
|
-
[![Build Status](https://travis-ci.org/
|
5
|
-
[![Gem Version](https://badge.fury.io/rb/saml_idp.
|
5
|
+
[![Build Status](https://travis-ci.org/saml-idp/saml_idp.svg)](https://travis-ci.org/saml-idp/saml_idp)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/saml_idp.svg)](http://badge.fury.io/rb/saml_idp)
|
6
7
|
|
7
8
|
The ruby SAML Identity Provider library is for implementing the server side of SAML authentication. It allows
|
8
9
|
your application to act as an IdP (Identity Provider) using the
|
@@ -19,6 +20,7 @@ Add this to your Gemfile:
|
|
19
20
|
gem 'saml_idp'
|
20
21
|
|
21
22
|
## Not using rails?
|
23
|
+
|
22
24
|
Include `SamlIdp::Controller` and see the examples that use rails. It should be straightforward for you.
|
23
25
|
|
24
26
|
Basically you call `decode_request(params[:SAMLRequest])` on an incoming request and then use the value
|
@@ -30,9 +32,10 @@ posting to `saml_acs_url` the parameter `SAMLResponse` with the return value fro
|
|
30
32
|
`encode_response(user_email)`.
|
31
33
|
|
32
34
|
## Using rails?
|
35
|
+
|
33
36
|
Add to your `routes.rb` file, for example:
|
34
37
|
|
35
|
-
```
|
38
|
+
```ruby
|
36
39
|
get '/saml/auth' => 'saml_idp#new'
|
37
40
|
get '/saml/metadata' => 'saml_idp#show'
|
38
41
|
post '/saml/auth' => 'saml_idp#create'
|
@@ -41,7 +44,7 @@ match '/saml/logout' => 'saml_idp#logout', via: [:get, :post, :delete]
|
|
41
44
|
|
42
45
|
Create a controller that looks like this, customize to your own situation:
|
43
46
|
|
44
|
-
```
|
47
|
+
```ruby
|
45
48
|
class SamlIdpController < SamlIdp::IdpController
|
46
49
|
def idp_authenticate(email, password) # not using params intentionally
|
47
50
|
user = User.by_email(email).first
|
@@ -69,6 +72,22 @@ end
|
|
69
72
|
|
70
73
|
## Configuration
|
71
74
|
|
75
|
+
#### Signed assertions and Signed Response
|
76
|
+
|
77
|
+
By default SAML Assertion will be signed with an algorithm which defined to `config.algorithm`. Because SAML assertions contain secure information used for authentication such as NameID.
|
78
|
+
|
79
|
+
Signing SAML Response is optional, but some security perspective SP services might require Response message itself must be signed.
|
80
|
+
For that, you can enable it with `config.signed_message` option. [More about SAML spec](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=68)
|
81
|
+
|
82
|
+
#### Signing algorithm
|
83
|
+
|
84
|
+
Following algorithms you can set in your response signing algorithm
|
85
|
+
:sha1 - RSA-SHA1 default value but not recommended to production environment
|
86
|
+
Highly recommended to use one of following algorithm, suit with your computing power.
|
87
|
+
:sha256 - RSA-SHA256
|
88
|
+
:sha384 - RSA-SHA384
|
89
|
+
:sha512 - RSA-SHA512
|
90
|
+
|
72
91
|
Be sure to load a file like this during your app initialization:
|
73
92
|
|
74
93
|
```ruby
|
@@ -88,18 +107,21 @@ KEY DATA
|
|
88
107
|
CERT
|
89
108
|
|
90
109
|
# config.password = "secret_key_password"
|
91
|
-
# config.algorithm = :sha256
|
110
|
+
# config.algorithm = :sha256 # Default: sha1 only for development.
|
92
111
|
# config.organization_name = "Your Organization"
|
93
112
|
# config.organization_url = "http://example.com"
|
94
113
|
# config.base_saml_location = "#{base}/saml"
|
95
|
-
# config.reference_id_generator # Default: -> {
|
114
|
+
# config.reference_id_generator # Default: -> { SecureRandom.uuid }
|
115
|
+
# config.single_logout_service_post_location = "#{base}/saml/logout"
|
116
|
+
# config.single_logout_service_redirect_location = "#{base}/saml/logout"
|
96
117
|
# config.attribute_service_location = "#{base}/saml/attributes"
|
97
118
|
# config.single_service_post_location = "#{base}/saml/auth"
|
98
119
|
# config.session_expiry = 86400 # Default: 0 which means never
|
120
|
+
# config.signed_message = true # Default: false which means unsigned SAML Response
|
99
121
|
|
100
122
|
# Principal (e.g. User) is passed in when you `encode_response`
|
101
123
|
#
|
102
|
-
# config.name_id.formats
|
124
|
+
# config.name_id.formats =
|
103
125
|
# { # All 2.0
|
104
126
|
# email_address: -> (principal) { principal.email_address },
|
105
127
|
# transient: -> (principal) { principal.id },
|
@@ -169,7 +191,11 @@ CERT
|
|
169
191
|
service_providers = {
|
170
192
|
"some-issuer-url.com/saml" => {
|
171
193
|
fingerprint: "9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D",
|
172
|
-
metadata_url: "http://some-issuer-url.com/saml/metadata"
|
194
|
+
metadata_url: "http://some-issuer-url.com/saml/metadata",
|
195
|
+
|
196
|
+
# We now validate AssertionConsumerServiceURL will match the MetadataURL set above.
|
197
|
+
# *If* it's not going to match your Metadata URL's Host, then set this so we can validate the host using this list
|
198
|
+
response_hosts: ["foo.some-issuer-url.com"]
|
173
199
|
},
|
174
200
|
}
|
175
201
|
|
@@ -177,7 +203,7 @@ CERT
|
|
177
203
|
# settings is an IncomingMetadata object which has a to_h method that needs to be persisted
|
178
204
|
config.service_provider.metadata_persister = ->(identifier, settings) {
|
179
205
|
fname = identifier.to_s.gsub(/\/|:/,"_")
|
180
|
-
|
206
|
+
FileUtils.mkdir_p(Rails.root.join('cache', 'saml', 'metadata').to_s)
|
181
207
|
File.open Rails.root.join("cache/saml/metadata/#{fname}"), "r+b" do |f|
|
182
208
|
Marshal.dump settings.to_h, f
|
183
209
|
end
|
@@ -188,7 +214,7 @@ CERT
|
|
188
214
|
# `service_provider` you should return the settings.to_h from above
|
189
215
|
config.service_provider.persisted_metadata_getter = ->(identifier, service_provider){
|
190
216
|
fname = identifier.to_s.gsub(/\/|:/,"_")
|
191
|
-
|
217
|
+
FileUtils.mkdir_p(Rails.root.join('cache', 'saml', 'metadata').to_s)
|
192
218
|
full_filename = Rails.root.join("cache/saml/metadata/#{fname}")
|
193
219
|
if File.file?(full_filename)
|
194
220
|
File.open full_filename, "rb" do |f|
|
@@ -205,6 +231,7 @@ end
|
|
205
231
|
```
|
206
232
|
|
207
233
|
# Keys and Secrets
|
234
|
+
|
208
235
|
To generate the SAML Response it uses a default X.509 certificate and secret key... which isn't so secret.
|
209
236
|
You can find them in `SamlIdp::Default`. The X.509 certificate is valid until year 2032.
|
210
237
|
Obviously you shouldn't use these if you intend to use this in production environments. In that case,
|
@@ -218,18 +245,19 @@ The fingerprint to use, if you use the default X.509 certificate of this gem, is
|
|
218
245
|
9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D
|
219
246
|
```
|
220
247
|
|
221
|
-
|
222
248
|
# Service Providers
|
249
|
+
|
223
250
|
To act as a Service Provider which generates SAML Requests and can react to SAML Responses use the
|
224
251
|
excellent [ruby-saml](https://github.com/onelogin/ruby-saml) gem.
|
225
252
|
|
226
|
-
|
227
253
|
# Author
|
228
|
-
|
254
|
+
|
255
|
+
Jon Phenow, jon@jphenow.com, jphenow.com, @jphenow
|
229
256
|
|
230
257
|
Lawrence Pit, lawrence.pit@gmail.com, lawrencepit.com, @lawrencepit
|
231
258
|
|
232
259
|
# Copyright
|
260
|
+
|
233
261
|
Copyright (c) 2012 Sport Ngin.
|
234
262
|
Portions Copyright (c) 2010 OneLogin, LLC
|
235
263
|
Portions Copyright (c) 2012 Lawrence Pit (http://lawrencepit.com)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'ostruct'
|
3
|
+
require 'securerandom'
|
4
|
+
|
3
5
|
module SamlIdp
|
4
6
|
class Configurator
|
5
7
|
attr_accessor :x509_certificate
|
@@ -13,17 +15,19 @@ module SamlIdp
|
|
13
15
|
attr_accessor :reference_id_generator
|
14
16
|
attr_accessor :attribute_service_location
|
15
17
|
attr_accessor :single_service_post_location
|
18
|
+
attr_accessor :single_service_redirect_location
|
16
19
|
attr_accessor :single_logout_service_post_location
|
17
20
|
attr_accessor :single_logout_service_redirect_location
|
18
21
|
attr_accessor :attributes
|
19
22
|
attr_accessor :service_provider
|
23
|
+
attr_accessor :assertion_consumer_service_hosts
|
20
24
|
attr_accessor :session_expiry
|
21
25
|
|
22
26
|
def initialize
|
23
27
|
self.x509_certificate = Default::X509_CERTIFICATE
|
24
28
|
self.secret_key = Default::SECRET_KEY
|
25
29
|
self.algorithm = :sha1
|
26
|
-
self.reference_id_generator = ->() {
|
30
|
+
self.reference_id_generator = ->() { SecureRandom.uuid }
|
27
31
|
self.service_provider = OpenStruct.new
|
28
32
|
self.service_provider.finder = ->(_) { Default::SERVICE_PROVIDER }
|
29
33
|
self.service_provider.metadata_persister = ->(id, settings) { }
|
data/lib/saml_idp/controller.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'openssl'
|
3
3
|
require 'base64'
|
4
4
|
require 'time'
|
5
|
-
require '
|
5
|
+
require 'securerandom'
|
6
6
|
require 'saml_idp/request'
|
7
7
|
require 'saml_idp/logout_response_builder'
|
8
8
|
module SamlIdp
|
@@ -35,13 +35,15 @@ module SamlIdp
|
|
35
35
|
|
36
36
|
def validate_saml_request(raw_saml_request = params[:SAMLRequest])
|
37
37
|
decode_request(raw_saml_request)
|
38
|
-
|
38
|
+
return true if valid_saml_request?
|
39
|
+
if defined?(::Rails)
|
39
40
|
if Rails::VERSION::MAJOR >= 4
|
40
41
|
head :forbidden
|
41
42
|
else
|
42
43
|
render nothing: true, status: :forbidden
|
43
44
|
end
|
44
45
|
end
|
46
|
+
false
|
45
47
|
end
|
46
48
|
|
47
49
|
def decode_request(raw_saml_request)
|
@@ -62,6 +64,7 @@ module SamlIdp
|
|
62
64
|
expiry = opts[:expiry] || 60*60
|
63
65
|
session_expiry = opts[:session_expiry]
|
64
66
|
encryption_opts = opts[:encryption] || nil
|
67
|
+
signed_message_opts = opts[:signed_message] || false
|
65
68
|
|
66
69
|
SamlResponse.new(
|
67
70
|
reference_id,
|
@@ -75,7 +78,8 @@ module SamlIdp
|
|
75
78
|
my_authn_context_classref,
|
76
79
|
expiry,
|
77
80
|
encryption_opts,
|
78
|
-
session_expiry
|
81
|
+
session_expiry,
|
82
|
+
signed_message_opts
|
79
83
|
).build
|
80
84
|
end
|
81
85
|
|
@@ -122,11 +126,11 @@ module SamlIdp
|
|
122
126
|
end
|
123
127
|
|
124
128
|
def get_saml_response_id
|
125
|
-
|
129
|
+
SecureRandom.uuid
|
126
130
|
end
|
127
131
|
|
128
132
|
def get_saml_reference_id
|
129
|
-
|
133
|
+
SecureRandom.uuid
|
130
134
|
end
|
131
135
|
|
132
136
|
def default_algorithm
|
@@ -16,16 +16,37 @@ module SamlIdp
|
|
16
16
|
@document ||= Saml::XML::Document.parse raw
|
17
17
|
end
|
18
18
|
|
19
|
+
def entity_id
|
20
|
+
xpath('//md:EntityDescriptor/@entityID', md: metadata_namespace).first.try(:content).to_s
|
21
|
+
end
|
22
|
+
hashable :entity_id
|
23
|
+
|
19
24
|
def sign_assertions
|
20
25
|
doc = xpath(
|
21
26
|
"//md:SPSSODescriptor",
|
22
27
|
ds: signature_namespace,
|
23
28
|
md: metadata_namespace
|
24
29
|
).first
|
25
|
-
doc
|
30
|
+
if (doc && !doc['WantAssertionsSigned'].nil?)
|
31
|
+
return doc['WantAssertionsSigned'].strip.downcase == 'true'
|
32
|
+
end
|
33
|
+
return false
|
26
34
|
end
|
27
35
|
hashable :sign_assertions
|
28
36
|
|
37
|
+
def sign_authn_request
|
38
|
+
doc = xpath(
|
39
|
+
"//md:SPSSODescriptor",
|
40
|
+
ds: signature_namespace,
|
41
|
+
md: metadata_namespace
|
42
|
+
).first
|
43
|
+
if (doc && !doc['AuthnRequestsSigned'].nil?)
|
44
|
+
return doc['AuthnRequestsSigned'].strip.downcase == 'true'
|
45
|
+
end
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
hashable :sign_authn_request
|
49
|
+
|
29
50
|
def display_name
|
30
51
|
role_descriptor_document.present? ? role_descriptor_document["ServiceDisplayName"] : ""
|
31
52
|
end
|
@@ -24,13 +24,15 @@ module SamlIdp
|
|
24
24
|
|
25
25
|
entity.IDPSSODescriptor protocolSupportEnumeration: protocol_enumeration do |descriptor|
|
26
26
|
build_key_descriptor descriptor
|
27
|
-
descriptor
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
build_endpoint descriptor, [
|
28
|
+
{ tag: 'SingleLogoutService', url: single_logout_service_post_location, bind: 'HTTP-POST' },
|
29
|
+
{ tag: 'SingleLogoutService', url: single_logout_service_redirect_location, bind: 'HTTP-Redirect'}
|
30
|
+
]
|
31
31
|
build_name_id_formats descriptor
|
32
|
-
descriptor
|
33
|
-
|
32
|
+
build_endpoint descriptor, [
|
33
|
+
{ tag: 'SingleSignOnService', url: single_service_post_location, bind: 'HTTP-POST' },
|
34
|
+
{ tag: 'SingleSignOnService', url: single_service_redirect_location, bind: 'HTTP-Redirect'}
|
35
|
+
]
|
34
36
|
build_attribute descriptor
|
35
37
|
end
|
36
38
|
|
@@ -38,8 +40,9 @@ module SamlIdp
|
|
38
40
|
build_key_descriptor authority_descriptor
|
39
41
|
build_organization authority_descriptor
|
40
42
|
build_contact authority_descriptor
|
41
|
-
authority_descriptor
|
42
|
-
|
43
|
+
build_endpoint authority_descriptor, [
|
44
|
+
{ tag: 'AttributeService', url: attribute_service_location, bind: 'HTTP-Redirect' }
|
45
|
+
]
|
43
46
|
build_name_id_formats authority_descriptor
|
44
47
|
build_attribute authority_descriptor
|
45
48
|
end
|
@@ -69,6 +72,17 @@ module SamlIdp
|
|
69
72
|
end
|
70
73
|
private :build_name_id_formats
|
71
74
|
|
75
|
+
def build_endpoint(el, end_points)
|
76
|
+
end_points.each do |ep|
|
77
|
+
next unless ep[:url].present?
|
78
|
+
|
79
|
+
el.tag! ep[:tag],
|
80
|
+
Binding: "urn:oasis:names:tc:SAML:2.0:bindings:#{ep[:bind]}",
|
81
|
+
Location: ep[:url]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
private :build_endpoint
|
85
|
+
|
72
86
|
def build_attribute(el)
|
73
87
|
attributes.each do |attribute|
|
74
88
|
el.tag! "saml:Attribute",
|
@@ -151,6 +165,7 @@ module SamlIdp
|
|
151
165
|
organization_url
|
152
166
|
attribute_service_location
|
153
167
|
single_service_post_location
|
168
|
+
single_service_redirect_location
|
154
169
|
single_logout_service_post_location
|
155
170
|
single_logout_service_redirect_location
|
156
171
|
technical_contact
|
data/lib/saml_idp/request.rb
CHANGED
@@ -105,13 +105,24 @@ module SamlIdp
|
|
105
105
|
return false
|
106
106
|
end
|
107
107
|
|
108
|
+
if !service_provider.acceptable_response_hosts.include?(response_host)
|
109
|
+
log "#{service_provider.acceptable_response_hosts} compare to #{response_host}"
|
110
|
+
log "No acceptable AssertionConsumerServiceURL, either configure them via config.service_provider.response_hosts or match to your metadata_url host"
|
111
|
+
return false
|
112
|
+
end
|
113
|
+
|
108
114
|
return true
|
109
115
|
end
|
110
116
|
|
111
117
|
def valid_signature?
|
112
|
-
# Force signatures for logout requests because there is no other
|
113
|
-
#
|
114
|
-
service_provider.
|
118
|
+
# Force signatures for logout requests because there is no other protection against a cross-site DoS.
|
119
|
+
# Validate signature when metadata specify AuthnRequest should be signed
|
120
|
+
metadata = service_provider.current_metadata
|
121
|
+
if logout_request? || authn_request? && metadata.respond_to?(:sign_authn_request?) && metadata.sign_authn_request?
|
122
|
+
document.valid_signature?(service_provider.fingerprint)
|
123
|
+
else
|
124
|
+
true
|
125
|
+
end
|
115
126
|
end
|
116
127
|
|
117
128
|
def service_provider?
|
@@ -136,6 +147,14 @@ module SamlIdp
|
|
136
147
|
@_session_index ||= xpath("//samlp:SessionIndex", samlp: samlp).first.try(:content)
|
137
148
|
end
|
138
149
|
|
150
|
+
def response_host
|
151
|
+
uri = URI(response_url)
|
152
|
+
if uri
|
153
|
+
uri.host
|
154
|
+
end
|
155
|
+
end
|
156
|
+
private :response_host
|
157
|
+
|
139
158
|
def document
|
140
159
|
@_document ||= Saml::XML::Document.parse(raw_xml)
|
141
160
|
end
|
@@ -1,32 +1,45 @@
|
|
1
1
|
require 'builder'
|
2
|
+
require 'saml_idp/algorithmable'
|
3
|
+
require 'saml_idp/signable'
|
2
4
|
module SamlIdp
|
3
5
|
class ResponseBuilder
|
6
|
+
include Algorithmable
|
7
|
+
include Signable
|
4
8
|
attr_accessor :response_id
|
5
9
|
attr_accessor :issuer_uri
|
6
10
|
attr_accessor :saml_acs_url
|
7
11
|
attr_accessor :saml_request_id
|
8
12
|
attr_accessor :assertion_and_signature
|
13
|
+
attr_accessor :raw_algorithm
|
9
14
|
|
10
|
-
|
15
|
+
alias_method :reference_id, :response_id
|
16
|
+
|
17
|
+
def initialize(response_id, issuer_uri, saml_acs_url, saml_request_id, assertion_and_signature, raw_algorithm)
|
11
18
|
self.response_id = response_id
|
12
19
|
self.issuer_uri = issuer_uri
|
13
20
|
self.saml_acs_url = saml_acs_url
|
14
21
|
self.saml_request_id = saml_request_id
|
15
22
|
self.assertion_and_signature = assertion_and_signature
|
23
|
+
self.raw_algorithm = raw_algorithm
|
16
24
|
end
|
17
25
|
|
18
|
-
def encoded
|
19
|
-
@encoded ||=
|
26
|
+
def encoded(signed_message: false)
|
27
|
+
@encoded ||= signed_message ? encode_signed_message : encode_raw_message
|
20
28
|
end
|
21
29
|
|
22
30
|
def raw
|
23
31
|
build
|
24
32
|
end
|
25
33
|
|
26
|
-
def
|
34
|
+
def encode_raw_message
|
27
35
|
Base64.strict_encode64(raw)
|
28
36
|
end
|
29
|
-
private :
|
37
|
+
private :encode_raw_message
|
38
|
+
|
39
|
+
def encode_signed_message
|
40
|
+
Base64.strict_encode64(signed)
|
41
|
+
end
|
42
|
+
private :encode_signed_message
|
30
43
|
|
31
44
|
def build
|
32
45
|
resp_options = {}
|
@@ -41,6 +54,7 @@ module SamlIdp
|
|
41
54
|
builder = Builder::XmlMarkup.new
|
42
55
|
builder.tag! "samlp:Response", resp_options do |response|
|
43
56
|
response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION
|
57
|
+
sign response
|
44
58
|
response.tag! "samlp:Status" do |status|
|
45
59
|
status.tag! "samlp:StatusCode", Value: Saml::XML::Namespaces::Statuses::SUCCESS
|
46
60
|
end
|