How to Authenticate using SOAP? followed the documentation but without success
We have installed Milestone XProtect VMS Products 2019 R2 System Installer.exe and I followed the instruction in to login using SOAP Requests. https://doc.developer.milestonesys.com/html/index.html?base=reference/architecture/product_support.html&tree=tree_3.html without sucess.
I used the same username/password we used to login into XProtect Management Client 1019 R2 with basic authentication.
Below you can see the HTTP messages during our test captured from Wireshark.
We found in the developer forms question regarding this and they pointed to run your samples and capture the network to see what it was sent. We can’t see the content of the message because your samples are sending the data in https and the data is encrypted.
POST /ServerAPI/ServerCommandService.asmx HTTP/1.1
Content-Length: 399
Content-Type: text/xml; charset=UTF-8
Host: 192.168.1.121
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.2.1 (java 1.5)
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd=“http://www.w3.org/2001/XMLSchema” xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/”>
soap:Body
fc0352e7-6a7a-418b-ad1d-2f16c09adddf
</soap:Body>
</soap:Envelope>
HTTP/1.1 401 Unauthorized
Content-Type: text/html
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-Frame-Options: SAMEORIGIN
Date: Wed, 30 Jan 2019 14:41:20 GMT
Content-Length: 1293
401 - Unauthorized: Access is denied due to invalid credentials.
Server Error
401 - Unauthorized: Access is denied due to invalid credentials.
You do not have permission to view this directory or page using the credentials that you supplied.
This issue can sometimes be caused if you are not sending an InstanceGuid when you obtain the token. To fix it, generate a random GUID (Free Online GUID Generator) for your application, and store it. Then include it always when obtaining the token.
A sample body would be the following one:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xpr="http://videoos.net/2/XProtectCSServerCommand">
<soapenv:Header/>
<soapenv:Body>
<xpr:Login>
<xpr:instanceId>DDF4BA55-808E-479F-BE8B-72F69913442F</xpr:instanceId>
</xpr:Login>
</soapenv:Body>
</soapenv:Envelope>
Here is a sample of how to obtain a token using Node.js.
const xml2js = require("xml2js");
const INTEGRATION_INSTANCE_ID = 'd3cd8c36-bbc9-4528-8509-e7dd8898d24a';
const TOKEN_REQUEST_BODY = `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xpr="http://videoos.net/2/XProtectCSServerCommand">
<soapenv:Header/>
<soapenv:Body>
<xpr:Login>
<xpr:instanceId>${INTEGRATION_INSTANCE_ID}</xpr:instanceId>
</xpr:Login>
</soapenv:Body>
</soapenv:Envelope>`;
const SOAP_ACTION = 'http://videoos.net/2/XProtectCSServerCommand/IServerCommandService/Login';
const MANAGEMENT_SERVER_HOST = '127.0.0.1'; // IP of the Management server
/**
* encodes a string to base64
*
* @param data, a string
* @returns data but base64 encoded
*/
const toBase64 = (data) => new Buffer.from(data).toString('base64');
/**
* returns the basic HTTP authentication header
* @param username
* @param password
* @returns the HTTP basic auth header
*/
const basicAuth = (username, password) => `Basic ${toBase64(`${username}:${password}`)}`;
/**
* parses the token from the xml response body
* @returns the token
*/
async function getToken(xml){
const parser = new xml2js.Parser();
return new Promise((resolve, reject) =>
parser.parseStringPromise(xml).then(function (result) {
resolve(result['s:Envelope']['s:Body'][0]['LoginResponse'][0]['LoginResult'][0]['Token'][0]);
}).catch(function (err) {
reject(err);
}));
}
/**
* @param username, a Basic user username
* @param password, a Basic user password
* @returns the management server token
*/
const getSessionKey = async (username, password) => {
if (!username) throw new Error("empty username");
if (!password) throw new Error("empty password");
// exchange username+password for a token through the Management Server
const response = await request({
url: `https://${MANAGEMENT_SERVER_HOST}/ManagementServer/ServerCommandService.svc`,
method: 'POST',
headers: {
'content-type': 'text/xml;charset=UTF-8',
'accept': '*/*',
'SOAPAction': SOAP_ACTION,
'Authorization': basicAuth(`[BASIC]\\\\${username}`, password)
},
body: TOKEN_REQUEST_BODY
});
// parse token from response
const token = await getToken(response.content)
return token;
};