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("&amp;").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