Authentication and authorization

To use any of the SOAP services or the ImageServer protocol, you must first authenticate and login to the XProtect VMS, using the ServerCommandService to obtain authentication tokens for the session.

ServerCommandService endpoints

There are currently three ServerCommandService endpoints available:

Use ManagementServer/ServerCommandServiceOAuth.svc or ManagementServer/ServerCommandService.svcfor new development. Most of the protocol samples relies on a convenience wrapper, ServerCommandWrapper, that uses ServerCommandServiceOAuth.svc if available and falls back on ServerCommandService.svc.

The ServerAPI/ServerCommandService.asmx endpoint is deprecated, but useful for illustrating the initial login process.

Authentication method

Three authentication methods are available:

The convenience wrapper, ServerCommandWrapper used by most of the protocol samples will use ServerCommandServiceOAuth.svc if available and falls back on ServerCommandService.svc.

Register your protocol integration application

You are encouraged to register your application after each initial login. This will provide data for reporting applications used at this XProtect VMS site. The feature is available in XProtect 2020 R3 and later releases.

The ServerCommandWrapper for ServerCommandServiceOAuth.svc and ServerCommandServiceOAuth.svc includes an overloaded Login() method that takes care of the registration.

When registering your application, you provide the following information:

Parameter Type Description
instanceId string Identifier uniquely identifying the calling instance. Typically, each ID should refer to a specific machine running an integration.
integrationId guid Unique identifier representing the integration. Should be hardcoded in the integrating application.
integrationVersion string Version of the calling application.
integrationName string Name of the calling application.
manufacturerName string Name of the manufacturer of the calling application

All strings are max 256 characters.

Login and register using ServerCommandService.asmx

The following example assumes that you are using a HTTP library or class that supports Windows authentication.

POST /ServerAPI/ServerCommandService.asmx HTTP/1.1
Host: {xprotectserver.company.com}
Authorization: {generated by HTTP library or class applied}
Content-Type: text/xml; charset=utf-8
Content-Length: {number of bytes}
SOAPAction: http://videoos.net/2/XProtectCSServerCommand/Login"

<?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>
    <Login xmlns="http://videoos.net/2/XProtectCSServerCommand">
      <instanceId>{guid}</instanceId>
      <currentToken>{token}</currentToken>
    </Login>
  </soap:Body>
</soap:Envelope>

If the login is successful, you will receive a response which looks like this:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: {length}

<?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>
    <LoginResponse xmlns="http://videoos.net/2/XProtectCSServerCommand">
      <LoginResult>
        <Token>{token}</Token>
        <RegistrationTime>{DateTime}</RegistrationTime>
        <TimeToLive>
          <MicroSeconds>{valid period}</MicroSeconds>
        </TimeToLive>
      </LoginResult>
    </LoginResponse>
  </soap:Body>
</soap:Envelope>

Right after authenticating and obtaining a token, submit a RegisterIntegration request:

POST /ServerAPI/ServerCommandService.asmx HTTP/1.1
Host: {xprotectserver.company.com}
Authorization: {generated by HTTP library or class applied}
Content-Type: text/xml; charset=utf-8
Content-Length: {number of bytes}
SOAPAction: http://videoos.net/2/XProtectCSServerCommand/RegisterIntegration"

<?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>
    <RegisterIntegration xmlns="http://videoos.net/2/XProtectCSServerCommand">
      <token>{token}</currentToken>
      <instanceId>{instanceId}</instanceId>
      <integrationId>{integrationId}<integrationId>
      <integrationVersion>{integrationVersion}<integrationVersion>
      <integrationName>{integrationName}<integrationName>
      <manufacturerName>{manufacturerName}<manufacturerName>
    </RegisterIntegration>
  </soap:Body>
</soap:Envelope>

Login and register using ServerCommandServiceOAuth.svc or ServerCommandService.svc

The TcpVideoViewer sample illustrates how a convenience wrapper, ServerCommandWrapper, can simplify authentication and login, and also how to maintain token-authenticated sessions, in this case ImageServer connections. This section highlights the initial login and subsequent re-logins; it is not a complete walk-through of the TcpVideoViewer sample.

In the TcpVideoViewer sample, the proxy class SystemAccess takes care of the connection:

public class SystemAccess
{
    private static readonly Guid IntegrationId = new Guid("BE07504F-B330-4475-9AE4-1A7FF10BD486");
    private const string IntegrationName = "TCP Video Viewer";
    private const string Version = "1.0";
    public AuthenticationType AuthenticationType = AuthenticationType.WindowsDefault;

    public String Server = "localhost";
    public String User = "";
    public String Password = "";
    public String Domain = "";

    public LoginInfo LoginInfo;

    private NtlmConnection _ntlmConnection;
    private BasicConnection _basicConnection;

    public event EventHandler<string> OnTokenRefreshed = delegate { };

/// <summary>
/// Connect to the specified server
/// </summary>
/// <param name="server">URL of the server</param>
public void Connect(String server)
{
    if (_basicConnection != null)
    {
        _basicConnection.OnTokenRefreshed -= _connection_OnTokenRefreshed;
        _basicConnection.Logout();
        _basicConnection = null;
    }
    if (_ntlmConnection != null)
    {
        _ntlmConnection.OnTokenRefreshed -= _connection_OnTokenRefreshed;
        _ntlmConnection.Logout();
        _ntlmConnection = null;
    }
    Server = server;
    switch (AuthenticationType)
    {
        case AuthenticationType.Basic:
            {
                int port = 443;
                _basicConnection = new BasicConnection(User, Password, Server, port);
                LoginInfo = _basicConnection.Login(IntegrationId, Version, IntegrationName);
                _basicConnection.OnTokenRefreshed += _connection_OnTokenRefreshed;
                break;
            }
        case AuthenticationType.Windows:
        case AuthenticationType.WindowsDefault:
            {
                _ntlmConnection = new NtlmConnection(Domain, AuthenticationType, User, Password, Server);
                LoginInfo = _ntlmConnection.Login(IntegrationId, Version, IntegrationName);
                _ntlmConnection.OnTokenRefreshed += _connection_OnTokenRefreshed;
                break;
            }
        default:
            //empty
            break;
    }
}

private void _connection_OnTokenRefreshed(object sender, string e)
{
    OnTokenRefreshed.Invoke(this, e);
}
...
TcpVideoViewer SystemsAccess.cs

When the OnTokenRefreshed event is raised, the new token is passed on to all connections in the session.

    /// <summary>
    /// Interaction logic for WindowMain.xaml
    /// </summary>
    public partial class WindowMain : Window , INotifyPropertyChanged
    {
        private SystemAccess _sysInfo = new SystemAccess();
        ...
        private ImageServerConnection _isc = null;
        ...

        public WindowMain()
        {
            ...
            _sysInfo.OnTokenRefreshed += Token_Refreshed;
        }

        private void Token_Refreshed(object sender, string e)
        {
            TokenString = e;
            ...

            if (_isc != null)
            {
                _isc.SetToken(TokenString);

                // We need to update the Token on the recording server:
                // This will pass the token back on the live imageserver TCP session using the CONNECTUPDATE command
                // DoLiveCmd() will do nothing if there is no live sesssion
                _isc.DoLiveCmd(_isc.FormatConnectUpdate());

                // This will cause an active playback to pass the token back on the imageserver TCP session using the CONNECTUPDATE command
                // If no playback session is active, this will cause no change.
                _isc.PlaybackSendConnectUpdateFlag = true;
            }
        }
TcpVideoViewer WindowMain.xaml.cs

ImageServer requests like the connectupdate request can be wrapped in a simple string formatting function like this:

    class ImageServerConnection
    {
        ...
        public string FormatConnectUpdate()
        {
            string sendBuffer = string.Format(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodcall><requestid>{0}</requestid>" +
                "<methodname>connectupdate</methodname>" +
                "<connectparam>id={1}&connectiontoken={2}</connectparam>" +
                "</methodcall>\r\n\r\n",
                ++_reqCounter, _cameraGuid, _token);
        
            return sendBuffer;
        }
        ....
        
ImageServerConnection.cs