Asymmetric Authentication

Asymmetric authentication allows selected users to log in the Veeam Service Provider Console REST API v3 automatically. It is based on asymmetric algorithm and challenge-response mechanism.

Before you set up asymmetric authentication for a user account, you must assign a public key to that account. To do that:

  1. Log in using one of the methods described in the Username and Password and OAuth 2.0 Authentication sections.
  2. Generate a pair of RSA public and private keys using a keygen application or by sending the GET HTTPS request to the https://<hostname>:1280/api/v3/authentication/keys/rsa path. Save the generated keys locally.
  3. Send a POST HTTPS request to the https://<hostname>:1280/api/v3/users/{userId}/logins/asymmetricalgorithm path. The request body must include the public key received at step 2.

You will use the assigned public key and the private key from the same pair in the authentication process. To perform authentication:

  1. Send the POST HTTPS request to the https://<hostname>:1280/api/v3/token path.

In the body of the request, the client specifies the following parameters:

  • grant_type — the authorization process requires that the private_key value must be specified for this parameter.
  • public_key — public key assigned to a user.

The server returns a response containing a decryption challenge in the encrypted_code property.

  1. Decrypt the challenge sent by the server using the private key.
  2. Send the POST HTTPS request to the https://<hostname>:1280/api/v3/token path.

In the body of the request, the client specifies the following parameters:

  • grant_type — the authorization process requires that the authorization_code value must be specified for this parameter.
  • code — decrypted challenge.

The request must be sent in 30 seconds or less.

A successfully completed operation returns the 200 OK response code and an access and a refresh token in the response body. The client inserts the access token in headers of further requests to the Veeam Service Provider Console REST API. The refresh token must be saved locally.

Below is the example of the C# code that performs authentication.

using System.Net;

using System.Security.Cryptography;

using Newtonsoft.Json;

using Newtonsoft.Json.Linq;

 

var publicKey = Encoding.ASCII.GetBytes("<RSAKeyValue><Modulus>vbRr7cFmlRyi6Tbj6ySK7IOvucqxvMPbPwG9qGfxGlP80WYRTwdEb/wr6LlXtZ16QTuAnJhkKJ2n+pMJ2G1J1OOAwPsOhPcLtyWtEe4kJ2SD3Xi4oHF65YtG29OK/FKGX3+WUPEWtqsEsFM0n42bhzGQS2eZgHkOSANovQesuQ82ksEVbRpOf4979hyTFaae6ppC34bBHybQEKD1SXNkny1fEqnO8kir6/2duUjrdlhGdHQkJ46B2Y9Wpo8EWiyM5ICyiOvtbTcCNpyFme2vA7W9ZvpnAJZYsQDOB4YLK+HITSH5w2JhFIcfntrHu0PljQZgbDI0E+i7A5zVn6v/KQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>");

var privateKey = "<RSAKeyValue><Modulus>vbRr7cFmlRyi6Tbj6ySK7IOvucqxvMPbPwG9qGfxGlP80WYRTwdEb/wr6LlXtZ16QTuAnJhkKJ2n+pMJ2G1J1OOAwPsOhPcLtyWtEe4kJ2SD3Xi4oHF65YtG29OK/FKGX3+WUPEWtqsEsFM0n42bhzGQS2eZgHkOSANovQesuQ82ksEVbRpOf4979hyTFaae6ppC34bBHybQEKD1SXNkny1fEqnO8kir6/2duUjrdlhGdHQkJ46B2Y9Wpo8EWiyM5ICyiOvtbTcCNpyFme2vA7W9ZvpnAJZYsQDOB4YLK+HITSH5w2JhFIcfntrHu0PljQZgbDI0E+i7A5zVn6v/KQ==</Modulus><Exponent>AQAB</Exponent><P>yzM34w1NuhS+VCkl/poVreUzTdrocbelsZJL6XGCjJfNneb+15mrdswVpkhk3+DOOeoen+y597a1JIkt8FBujFjaiDHKe30gXZOmIzCV+jL3ctx5pHGbrWL6zX4JGYJ6zwdCyj7KE1wOLX19qlrGki3t8VXaIixA1S+S8mO/eWs=</P><Q>7v+AceCmX2AuyVlZ7xmxq02oc8JNfu2imLv0SJixX0K4mhjpa6Rg5HJPDSJKxSg2k5fZl8RzaVda6mL/dTWvvBQXhRZ44pAvwHMyyCr+JfE4wenYP8UFpWzjFQXwINjfcMENlckk5e62TMuAVWQvjC98hs519WfrAWe6lemYars=</Q><DP>X5IvbvMK48Jt4leYLy95ktiCUNPtD884d1Q/sARbSpT7eJD0u6LjKnTCmfritwmc9VBQJxfIP+IHQK/kk2rBE/GWlwgUHBC18E1JjrODVrIyACwCan2kouAy5gOpc/4SlNztZQIzOPfLE0o6mK0pSAeiKige+IOn2p0NmEOiAxE=</DP><DQ>1OfLdqbXzzMRutDcKwHKon3lyGmZO69aH5GgRmOv7tqzNKNonTmsDxY9kcewr/3o0IZ/kpGw9nCZTx+tzq5qxLNpWGfyfHJR97En1eVmzkobc7NrrzNGml1r1biad8h7FCkGfx7WvfZvc+39fxRmvw02c6jMsDdIxNGxCAc2fi0=</DQ><InverseQ>VDh8LDHjeNBT32UJPFzc2ah6M/YL1qiZzFSrMkx5fCSAlKutDqQZNdzYDKfEE8lZZAZ0K4TQpyyme0KSamXVq34dZWNQNoNxXf2APJuHsSWJ5/5CuEemLaTc78RBtHj8awMKS1NICwEDjbwPNVugA47WS+8QNI9ElCyGAVuSMuw=</InverseQ><D>J7MhPxFROXVTtoCRM/1iwVpRpQ0BIyLNuCLSIPMXps3aw6ubhbFcph7cxYg8DbrWAd7E7ICLvWA47hxlXBCK+e1eXYRspnDY18wfqvfuQvwrCGciJBl7gZwjCQ/9Lw7KJiQaPfgmK7YgdhIDmjxVRvadXtpgal1rGrDz81Mu1082LxbFyhYh1YbjQ0iN56yE9437mPg2mLpzvZjoY00SJf1hFPDCHsbcj2fH6Qj0jx5/2icK9j8fUNbjGOMjDPerZmXIuX5M+uHj8Qb7OX8egjJ8xDpfnIoVX+ch6FbIwEsMy9bdWDgviS6d0RkyFN/mBlWXR6vPEQBjwTLbWJZXTQ==</D></RSAKeyValue>";

var client = new WebClient();

var responseData = client.UploadData("https://localhost:5001/tokens/asymmetricalgorithm", "POST", publicKey);

var responseString = Encoding.ASCII.GetString(responseData);

var response = JsonConvert.DeserializeObject<JObject>(responseString);

var encryptedChallenge = Convert.FromBase64String(response["data"]["challenge"].ToString());

var challenge = default(byte[]);

 

using(var rsa = new RSACryptoServiceProvider())

{

   rsa.PersistKeyInCsp = false;

   rsa.FromXmlString(privateKey);

 

   challenge = rsa.Decrypt(encryptedChallenge, RSAEncryptionPadding.OaepSHA1);

}

 

responseData = client.UploadData("https://localhost:5001/tokens/asymmetricalgorithm", "PATCH", challenge);

responseString = Encoding.ASCII.GetString(responseData);

response = JsonConvert.DeserializeObject<JObject>(responseString);  

var token = response["data"]["token"].ToString();