2

I am attempting to follow the discussion here using Ruby and Savon. I am able to retrieve a session ID, but whenever I perform a request from the clients that require authentication (tracker), I receive an Authorization Failed error.

require 'Savon'

tracker_url = 'http://myserver/polarion/ws/services/TrackerWebService?wsdl'
session_url = 'http://myserver/polarion/ws/services/SessionWebService?wsdl'

# todo handle bad login credentials gracefully
session_client = Savon.client(wsdl: session_url)
response = session_client.call(:log_in, message: {user_name: 'lsimons', password: 'mypassword'})
session_id = response.header[:session_id]

puts "Session ID: #{session_id}"

tracker_client = Savon.client(wsdl: tracker_url, soap_header: {"session" => session_id},     headers: {"sessionID" => session_id})

puts "Requesting Workitem"
begin
    tracker_client.call(:get_work_item_by_id, message: {project_id: 'myProject', workitem_id: 'myWorkitem'})
rescue
    puts "Client call failed"
end

This code creates the following SOAP request for the tracker_client:

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins0="http://ws.polarion.com/TrackerWebService-impl" xmlns:ins1="http://ws.polarion.com/types" xmlns:ins2="http://ws.polarion.com/TrackerWebService-types" xmlns:ins3="http://ws.polarion.com/ProjectWebService-types" xmlns:tns1="http://ws.polarion.com/TrackerWebService" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <env:Header>
        <session>2164640482421325916</session>
    </env:Header>
    <env:Body>
        <tns1:getWorkItemById>
            <ins0:projectId>myProject</ins0:projectId>
            <ins0:workitemId>myWorkitem</ins0:workitemId>
        </tns1:getWorkItemById>
    </env:Body>
</env:Envelope>

However, in the forum discussion, the sessionID element occurs before the header. I didn't think this was possible with standard SOAP? Is there a way to achieve this with Savon or am I misinterpreting the forum discussion?

superlou
  • 679
  • 1
  • 8
  • 21

2 Answers2

3

I faced the same problem following the same thread. This is how I made it work (by replicating the response headers of the log_in request):

tracker_client = Savon.client(
  wsdl: tracker_url,
  soap_header: {
    "ns1:sessionID" => session_id,
    :attributes! => {
      "ns1:sessionID" => {
        "env:actor"           => "http://schemas.xmlsoap.org/soap/actor/next",
        "env:mustUnderstand"  => "0",
        "xmlns:ns1"           => "http://ws.polarion.com/session"
      }
    }
  }
)
jeanmartin
  • 937
  • 7
  • 7
  • 1
    It seems like the critical attribute is xmlns:ns1. I can comment out env:actor and env:mustUnderstand and still receive a response. Thanks! – superlou Jun 03 '13 at 16:24
0

Old question but thought I can add some info to hopefully help somebody.

I am using lolsoap to talk to polarion. In the above resulting document, the sessionID element is wiped off any namespaces and attributes. Also the assessment is right that actor and mustUnderstand attributes seem irrelevant.

To add header properly though with all fluff, one needs to get the Nokogiri::XML::Node and dup it, then add it to the header of the doc. This is a bug in nokogiri/libxml2 that adding child elements can often break namespaces unless Node is cloned before adding [1].

In lolsoap it is done something like:

auth_header = login_response.nokogiri_doc.xpath("//*[local-name()='sessionID']")[0].dup
other_request.header.__node__ << auth_header

Please note the dup operation. header.__node__ is just the header Nokogiri::XML::Element of a random SOAP request.

The dup operation makes adding desired element into another one with all necessary namespaces and attributes properly defined.

I don't know if savon allows one to directly touch request XML but I guess it does. Thus HTH

[1] https://github.com/sparklemotion/nokogiri/issues/1200

akostadinov
  • 17,364
  • 6
  • 77
  • 85