ruby-saml-bekk 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/onelogin/saml/logoutrequest.rb +9 -9
- data/lib/onelogin/saml/logoutresponse.rb +5 -0
- data/lib/onelogin/saml/response.rb +4 -0
- data/lib/onelogin/saml/settings.rb +1 -2
- data/test/ruby-saml_test.rb +39 -5
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.3
|
@@ -1,36 +1,36 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'uuid'
|
3
|
-
require 'cgi'
|
4
2
|
|
5
3
|
module Onelogin::Saml
|
6
4
|
class Logoutrequest
|
5
|
+
include Codeing
|
7
6
|
attr_reader :transaction_id
|
8
7
|
|
9
8
|
def initialize
|
10
9
|
@transaction_id = UUID.new.generate
|
11
10
|
end
|
12
11
|
|
13
|
-
def create(settings,
|
12
|
+
def create(settings, params={})
|
14
13
|
issue_instant = Onelogin::Saml::Logoutrequest.timestamp
|
15
14
|
|
16
|
-
request = xml(settings,
|
15
|
+
request = xml(settings, issue_instant)
|
17
16
|
|
18
|
-
deflated_request =
|
19
|
-
base64_request =
|
17
|
+
deflated_request = deflate(request)
|
18
|
+
base64_request = encode(deflated_request)
|
20
19
|
params["SAMLRequest"] = base64_request
|
21
|
-
query_string = params.map {|key, value| "#{key}=#{
|
20
|
+
query_string = params.map {|key, value| "#{key}=#{escape(value)}"}.join("&")
|
22
21
|
|
23
22
|
settings.idp_slo_target_url + "?#{query_string}"
|
24
23
|
end
|
25
24
|
|
26
|
-
def xml(settings,
|
25
|
+
def xml(settings, issue_instant)
|
27
26
|
request = <<-EOF
|
28
27
|
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
29
28
|
ID="#{transaction_id}" Version="2.0" IssueInstant="#{issue_instant}">
|
30
29
|
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">#{settings.issuer}</saml:Issuer>
|
31
30
|
<saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
32
31
|
NameQualifier="#{settings.sp_name_qualifier}"
|
33
|
-
Format="#{settings.name_identifier_format}">#{
|
32
|
+
Format="#{settings.name_identifier_format}">#{settings.name_id}</saml:NameID>
|
33
|
+
<samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">#{settings.sessionindex}</samlp:SessionIndex>
|
34
34
|
</samlp:LogoutRequest>
|
35
35
|
EOF
|
36
36
|
|
@@ -24,6 +24,11 @@ module Onelogin
|
|
24
24
|
document.elements["/samlp:LogoutResponse"].attributes["InResponseTo"]
|
25
25
|
end
|
26
26
|
|
27
|
+
def success?
|
28
|
+
document.elements["/samlp:LogoutResponse/samlp:Status/samlp:StatusCode"].attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success"
|
29
|
+
|
30
|
+
end
|
31
|
+
|
27
32
|
protected
|
28
33
|
def document
|
29
34
|
REXML::Document.new(@response)
|
@@ -43,6 +43,10 @@ module Onelogin::Saml
|
|
43
43
|
@expires_at ||= Time.parse(document.elements["/samlp:Response/saml:Assertion/saml:AuthnStatement"].attributes["SessionNotOnOrAfter"])
|
44
44
|
end
|
45
45
|
|
46
|
+
def sessionindex
|
47
|
+
document.elements["/samlp:Response/saml:Assertion/saml:AuthnStatement"].attributes["SessionIndex"]
|
48
|
+
end
|
49
|
+
|
46
50
|
private
|
47
51
|
|
48
52
|
def make_hash_access_indiferent(hash)
|
@@ -3,7 +3,6 @@ module Onelogin::Saml
|
|
3
3
|
attr_accessor :assertion_consumer_service_url, :issuer, :sp_name_qualifier
|
4
4
|
attr_accessor :idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format
|
5
5
|
attr_accessor :idp_slo_target_url
|
6
|
-
|
7
|
-
SLO_ELEMENT_PATH = "/EntityDescriptor/IDPSSODescriptor/SingleLogoutService[@Binding='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect']"
|
6
|
+
attr_accessor :sessionindex, :name_id
|
8
7
|
end
|
9
8
|
end
|
data/test/ruby-saml_test.rb
CHANGED
@@ -11,7 +11,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
should "should provide getters and settings" do
|
13
13
|
accessors = [
|
14
|
-
:assertion_consumer_service_url, :issuer, :sp_name_qualifier,
|
14
|
+
:assertion_consumer_service_url, :issuer, :sp_name_qualifier,
|
15
15
|
:idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format
|
16
16
|
]
|
17
17
|
|
@@ -82,6 +82,13 @@ class RubySamlTest < Test::Unit::TestCase
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
context "#sessionindex" do
|
86
|
+
should "get the sessionindex" do
|
87
|
+
response = Onelogin::Saml::Response.new(response_document)
|
88
|
+
assert_equal "_531c32d283bdff7e04e487bcdbc4dd8d", response.sessionindex
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
85
92
|
context "#session_expires_at" do
|
86
93
|
should "extract the value of the SessionNotOnOrAfter attribute" do
|
87
94
|
response = Onelogin::Saml::Response.new(response_document)
|
@@ -127,7 +134,9 @@ class RubySamlTest < Test::Unit::TestCase
|
|
127
134
|
should "generate a correct logout request" do
|
128
135
|
logoutrequest = Onelogin::Saml::Logoutrequest.new
|
129
136
|
|
130
|
-
|
137
|
+
@settings.name_id = "demo"
|
138
|
+
@settings.sessionindex = "s2c8e391dbfcb2f71796595c803cf8b4079119ff01"
|
139
|
+
logout_xml = logoutrequest.xml(@settings, "test")
|
131
140
|
|
132
141
|
expected_xml = <<-EOF
|
133
142
|
<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
@@ -136,6 +145,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
136
145
|
<saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\"
|
137
146
|
NameQualifier=\"sp name\"
|
138
147
|
Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">demo</saml:NameID>
|
148
|
+
<samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">s2c8e391dbfcb2f71796595c803cf8b4079119ff01</samlp:SessionIndex>
|
139
149
|
</samlp:LogoutRequest>
|
140
150
|
EOF
|
141
151
|
|
@@ -145,9 +155,11 @@ class RubySamlTest < Test::Unit::TestCase
|
|
145
155
|
|
146
156
|
should "generate a correct request" do
|
147
157
|
logoutrequest = Onelogin::Saml::Logoutrequest.new
|
148
|
-
|
158
|
+
@settings.name_id = "demo"
|
159
|
+
@settings.sessionindex = "sessionindex"
|
160
|
+
logout_url = logoutrequest.create(@settings, {})
|
149
161
|
|
150
|
-
expected_url = "http://slotarget.com/?SAMLRequest=
|
162
|
+
expected_url = "http://slotarget.com/?SAMLRequest=nZJNa8MwDEDv%2FRXG92xZCKMxTWBQBoFusBV2VxxlGGI7sxToz18%2Bui1hWw%2FV%0A0ZbekywLMceOwLadOvh33%2FMrfvRILE62daSmm1z2wSkPZEg5sEiKtTo%2BPB1U%0AchOrLnj22rdyIxZR7nNZw31aYRVHCeg0iu8SjCDTWZRuK623mDVpWkvxhoGM%0Ad7kcYFKURD2Wjhgc55LNYGOwlSxW9O%2Bu1ZQfFt1ebhaIMPCgk4WZKne3C8x%2F%0AkueBU%2B6vkPzijTHSXnpoTWMw5JI6MSL%2Bzn30wQJf1o0npo6aKVVxAEcGHcui%0ARuvP880TrOc7r%2F2INL5%2F6Wo8XbH1guZ6M9bPtjXzR%2Fp1u%2FpoxeYT%0A"
|
151
163
|
assert_equal expected_url, logout_url
|
152
164
|
end
|
153
165
|
|
@@ -166,7 +178,7 @@ class RubySamlTest < Test::Unit::TestCase
|
|
166
178
|
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{issuer}</saml:Issuer>
|
167
179
|
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
168
180
|
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
169
|
-
Value=\"urn:oasis:names:tc:SAML:2.0:status:
|
181
|
+
Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\">
|
170
182
|
</samlp:StatusCode>
|
171
183
|
</samlp:Status>
|
172
184
|
</samlp:LogoutResponse>"
|
@@ -177,6 +189,28 @@ class RubySamlTest < Test::Unit::TestCase
|
|
177
189
|
|
178
190
|
assert_equal logoutresponse.issuer, issuer
|
179
191
|
assert_equal logoutresponse.in_response_to, transaction_id
|
192
|
+
assert_equal true, logoutresponse.success?
|
193
|
+
end
|
194
|
+
|
195
|
+
should "validate the a failing response" do
|
196
|
+
|
197
|
+
|
198
|
+
logout_xml = "<samlp:LogoutResponse xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
199
|
+
ID=\"sedf164edc2121a23d4ca4b31d35261e5563dc352\" Version=\"2.0\"
|
200
|
+
IssueInstant=\"2011-03-07T14:43:34Z\" Destination=\"http://localhost:3000/saml/consume_logout\"
|
201
|
+
InResponseTo=\"adflkjalkfjalsdfjlaskjdf\">
|
202
|
+
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">https://test-idp.test.no:443/issuer</saml:Issuer>
|
203
|
+
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
204
|
+
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
205
|
+
Value=\"urn:oasis:names:tc:SAML:2.0:status:Requester\">
|
206
|
+
</samlp:StatusCode>
|
207
|
+
</samlp:Status>
|
208
|
+
</samlp:LogoutResponse>"
|
209
|
+
|
210
|
+
|
211
|
+
logoutresponse = Onelogin::Saml::Logoutresponse.new(encode(deflate(logout_xml)))
|
212
|
+
|
213
|
+
assert_equal false, logoutresponse.success?
|
180
214
|
end
|
181
215
|
end
|
182
216
|
|