main
1require_relative './principal'
2
3RSpec.describe "Response" do
4 let(:user) { Principal.new(id: SecureRandom.uuid, email: "hello@example.com") }
5 let(:request) { Saml::Kit::AuthenticationRequest.build }
6
7 it 'consumes a Response' do
8 raw_xml = <<-XML
9<?xml version="1.0" encoding="UTF-8"?>
10<Response xmlns="urn:oasis:names:tc:SAML:2.0:protocol" ID="_32594448-5d41-4e5b-87c5-ee32ef1f14f7" Version="2.0" IssueInstant="2017-12-23T18:13:58Z" Destination="" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_55236abc-636f-41d1-8c0d-81c5384786dd">
11 <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://www.example.com/metadata</Issuer>
12 <Status>
13 <StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
14 </Status>
15 <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_843f14bc-51e9-40d3-9861-23e59ccc8427" IssueInstant="2017-12-23T18:13:58Z" Version="2.0">
16 <Issuer>https://www.example.com/metadata</Issuer>
17 <Subject>
18 <NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">ed215a85-597f-4e74-a892-ac83c386190b</NameID>
19 <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
20 <SubjectConfirmationData InResponseTo="_55236abc-636f-41d1-8c0d-81c5384786dd" NotOnOrAfter="2017-12-23T21:13:58Z" Recipient=""/>
21 </SubjectConfirmation>
22 </Subject>
23 <Conditions NotBefore="2017-12-23T18:13:58Z" NotOnOrAfter="2017-12-23T21:13:58Z">
24 <AudienceRestriction>
25 <Audience/>
26 </AudienceRestriction>
27 </Conditions>
28 <AuthnStatement AuthnInstant="2017-12-23T18:13:58Z" SessionIndex="_843f14bc-51e9-40d3-9861-23e59ccc8427" SessionNotOnOrAfter="2017-12-23T21:13:58Z">
29 <AuthnContext>
30 <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
31 </AuthnContext>
32 </AuthnStatement>
33 </Assertion>
34</Response>
35 XML
36 response = Saml::Kit::Response.new(raw_xml)
37 expect(response.assertion.name_id).to eql('ed215a85-597f-4e74-a892-ac83c386190b')
38 expect(response.issuer).to eql("https://www.example.com/metadata")
39 end
40
41 it 'builds a Response document' do
42 response = Saml::Kit::Response.build(user, request) do |builder|
43 builder.issuer = "blah"
44 end
45
46 expect(response.issuer).to eql("blah")
47 expect(response.to_xml).to have_xpath("/samlp:Response/saml:Assertion/saml:Issuer[text()=\"blah\"]")
48 end
49
50 it 'generates a SAMLResponse' do
51 xml = Saml::Kit::Metadata.build_xml do |builder|
52 builder.contact_email = 'hi@example.com'
53 builder.organization_name = "Acme, Inc"
54 builder.organization_url = 'https://www.example.com'
55 builder.build_identity_provider do |x|
56 x.add_single_sign_on_service('https://www.example.com/login', binding: :http_post)
57 x.add_single_sign_on_service('https://www.example.com/login', binding: :http_redirect)
58 x.add_single_logout_service('https://www.example.com/logout', binding: :http_post)
59 x.name_id_formats = [ Saml::Kit::Namespaces::EMAIL_ADDRESS ]
60 x.attributes << :id
61 x.attributes << :email
62 end
63 builder.build_service_provider do |x|
64 x.add_assertion_consumer_service('https://www.example.com/consume', binding: :http_post)
65 x.add_single_logout_service('https://www.example.com/logout', binding: :http_post)
66 end
67 end
68
69 idp = Saml::Kit::IdentityProviderMetadata.new(xml)
70 url, saml_params = idp.login_request_for(binding: :http_post)
71 uri = URI.parse("#{url}?#{saml_params.map { |(x, y)| "#{x}=#{y}" }.join('&')}")
72
73 sp = Saml::Kit::ServiceProviderMetadata.new(xml)
74
75 binding = idp.single_sign_on_service_for(binding: :http_post)
76 raw_params = Hash[uri.query.split("&").map { |x| x.split("=", 2) }].symbolize_keys
77 saml_request = binding.deserialize(raw_params)
78 allow(saml_request).to receive(:provider).and_return(sp)
79
80 url, saml_params = saml_request.response_for(user, binding: :http_post)
81
82 expect(url).to eql("https://www.example.com/consume")
83 expect(saml_params['SAMLResponse']).to be_present
84 end
85end
86