Authentication
The authentication process with Adaxes REST API consists of two HTTP requests that must be executed in the following order:
- Create authentication session.
- Obtain security token.
An authentication session is required only to issue a token. Once a token is obtained, you can use it to perform operations via the API by adding the token value in the Adm-Authorization
header to each request.
Create authentication session
This request creates an authentication session for a specific user account. The account must be located in a domain managed by Adaxes.
POST ~/api/authSessions/create
Operations that you can perform via REST API are determined by the security roles assigned to the authenticated user.
Request headers
-
Name
-
Required
-
Description
-
Content-Type
-
True
-
Use application/json as the value of this header.
Request body
The request body is a JSON object with the following data structure:
{
"username": "<username>",
"password": "<password>"
}
username string
User's logon name in one of the following formats: username@domain.com or DOMAIN\username.
password string
User's password.
Responses
If successful, returns 200 OK
status code and an AuthSession object in the response body. Otherwise, returns one of the common HTTP error codes and an error description in the response body.
AuthSession is a JSON representation of an authentication session with the following data structure:
{
"sessionId": "<sessionID>",
"totpState": null,
"changePasswordReason": "<changePasswordReason>",
"expiresAtUtc": "<expiresAtUtc>"
}
sessionId string
The identifier of the authentication session.
Take note of the sessionId value from your response and keep it secret. The session identifier is required to issue a security token.
totpState AuthTotpState
Always equals null
.
changePasswordReason enum
Specifies whether the password of the authenticated user must be changed or not.
Show possible enum values
Unspecified = 0, // No need to change the password
PasswordExpired = 1, // The password has expired and must be changed
PasswordMustBeChanged = 2 // The password must be changed at logon
expiresAtUtc datetime
Specifies when the session expires. Once a session expires, its identifier can no longer be used to issue new tokens. All existing tokens will remain valid until they are destroyed or expire.
You can change the maximum session lifetime. For information on how to do this, see Change session lifetime.
Examples
Create an authentication session
The following code sample creates an authentication session.
Request
- PowerShell
-
$baseUrl = "https://host.example.com/restApi" $endpoint = "/api/authSessions/create" # Request parameters $requestUrl = $baseUrl + $endpoint $requestBody = ConvertTo-Json @{ "username" = "administrator@example.com"; "password" = "MyPassword" } # Make request Invoke-RestMethod -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json"
- C#
-
using System; using System.Text; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { const string baseUrl = "https://host.example.com/restApi"; const string endpoint = "/api/authSessions/create"; // Create JSON request body string jsonRequest = @" { 'username': 'administrator@example.com', 'password': 'MyPassword' }"; StringContent requestBody = new(jsonRequest, Encoding.UTF8, "application/json"); // Initialize HTTP client using HttpClient client = new(); // Make request HttpResponseMessage response = await client.PostAsync( baseUrl + endpoint, requestBody); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); } }
- cURL
-
curl --request POST 'https://host.example.com/restApi/api/authSessions/create' \ --header 'Content-Type: application/json' \ --data-raw '{ "username": "administrator@example.com", "password": "MyPassword" }'
- node.js
-
var https = require('https'); // Request parameters var options = { 'method': 'POST', 'hostname': 'host.example.com', 'path': '/restApi/api/authSessions/create', 'headers': {"Content-Type": "application/json"} }; // Create JSON request body var postData = ` { "username": "administrator@example.com", "password": "MyPassword" }`; // Make request var req = https.request(options, res => { var data = []; res.on("data", chunk => { data.push(chunk); }); res.on("end", () => { var body = Buffer.concat(data); console.log(body.toString()); }); res.on("error", error => { console.error(error); }); }); req.write(postData); req.end();
- Python
-
import requests import json baseUrl = "https://host.example.com/restApi" endpoint = "/api/authSessions/create" # Request parameters requestUrl = baseUrl + endpoint requestBody = { "username": "administrator@example.com", "password": "MyPassword" } # Make request request = requests.post(requestUrl, json=requestBody) response = json.loads(request.content) print(response)
Response
HTTP Status code: 200 OK
Response body:
{
"sessionId": "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5",
"totpState": null,
"changePasswordReason": 0,
"expiresAtUtc": "2020-07-30T15:41:10.3730467Z"
}
Obtain security token
This request uses an existing authentication session to obtain a security token.
POST ~/api/auth
Request headers
-
Name
-
Required
-
Description
-
Content-Type
-
True
-
Use application/json as the value of this header.
Request body
The request body is a JSON object with the following data structure:
{
"sessionId": "<sessionId>",
"type": 0
}
sessionId string
The identifier of an existing authentication session.
type integer
Authentication type. Must be set to 0.
Responses
If successful, returns 200 OK
status code and an AuthTicketInfo object in the response body. Otherwise, returns one of the common HTTP error codes and an error description in the response body.
AuthTicketInfo is a JSON representation of an authentication ticket with the following data structure:
{
"id": "<id>",
"token": "<token>",
"sid": "<SID>",
"expiresAtUtc": "<expiresAtUtc>",
"applications": [
"<REST API>"
]
}
id string
The ticket identifier.
token string
The security token. Specify it as the value of the Adm-Authorization
header in all further requests.
Take note of the token value from your response and keep it secret until the ticket expires or is destroyed. Anyone in possession of a valid security token can perform operations via the API.
sid string
The Security Identifier (SID) of the user who was issued the authentication ticket.
expiresAtUtc datetime
Specifies when the security token expires. Once a token expires, any requests with its value in the Adm-Authorization
header will be considered as unauthorized and will be rejected by the server.
You can change the maximum token lifetime. For information on how to do this, see Change token lifetime.
applications string array
Always contains a single element that equals REST API. Specifies that the token grants access to the REST API.
Examples
Obtain security token
The following code sample obtains a security token.
Request
- PowerShell
-
$baseUrl = "https://host.example.com/restApi" $endpoint = "/api/auth" # Request parameters $requestUrl = $baseUrl + $endpoint $requestBody = ConvertTo-Json @{ "sessionId" = "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5"; "type" = 0 } # Make request Invoke-RestMethod -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json"
- C#
-
using System; using System.Text; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { const string baseUrl = "https://host.example.com/restApi"; const string endpoint = "/api/auth"; // Create JSON request body string jsonRequest = @" { 'sessionId': 'LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5', 'type': '0' }"; StringContent requestBody = new(jsonRequest, Encoding.UTF8, "application/json"); // Initialize HTTP client using HttpClient client = new(); // Make request HttpResponseMessage response = await client.PostAsync( baseUrl + endpoint, requestBody); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); } }
- cURL
-
curl --request POST 'https://host.example.com/restApi/api/auth' \ --header 'Content-Type: application/json' \ --data-raw '{ "sessionId": "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5", "type": 0 }'
- node.js
-
var https = require('https'); // Request parameters var options = { 'method': 'POST', 'hostname': 'host.example.com', 'path': '/restApi/api/auth', 'headers': {"Content-Type": "application/json"} }; // Create JSON request body var postData = ` { "sessionId": "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5", "type": 0 }`; // Make request var req = https.request(options, res => { var data = []; res.on("data", chunk => { data.push(chunk); }); res.on("end", () => { var body = Buffer.concat(data); console.log(body.toString()); }); res.on("error", error => { console.error(error); }); }); req.write(postData); req.end();
- Python
-
import requests import json baseUrl = "https://host.example.com/restApi" endpoint = "/api/auth" # Request parameters requestUrl = baseUrl + endpoint requestBody = { "sessionId": "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5", "type": 0 } # Make request request = requests.post(requestUrl, json=requestBody) response = json.loads(request.content) print(response)
Response
HTTP Status code: 200 OK
Response body:
{
"id": "5PG_xHGLU7YhKI5vb4GCvvNHs8VaCPvuHVIlj",
"token": YOUR-SECURITY-TOKEN,
"sid": "S-1-5-21-3656734-1720699-187516-1186",
"expiresAtUtc": "2020-08-03T10:26:22.898414Z",
"applications": [
"<REST API>"
]
}
Renew security token
You can renew a security token by making this request. The previous token will still be valid until its expiration date or until destroyed.
PATCH ~/api/auth?<parameters>
Token renewal does not require an existing authentication session.
Query parameters
Request headers
-
Name
-
Required
-
Description
-
Adm-Authorization
-
True
-
Specify a valid security token.
Responses
If successful, returns 200 OK
status code and an AuthTicketInfo object with the new security token and its expiration date in the response body. Otherwise, returns one of the common HTTP error codes and an error description in the response body.
Examples
Renew security token
The following code sample renews the specified security token.
Request
- PowerShell
-
Add-Type -AssemblyName System.Web $baseUrl = "https://host.example.com/restApi" $endpoint = "/api/auth" # Request parameters $queryParams = "?token=" + [System.Web.HttpUtility]::UrlEncode(YOUR-SECURITY-TOKEN) $requestUrl = $baseUrl + $endpoint + $queryParams $requestHeaders = @{"Adm-Authorization" = YOUR-SECURITY-TOKEN} # Make request Invoke-RestMethod -Method PATCH -Headers $requestHeaders -Uri $requestUrl
- C#
-
using System; using System.Web; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { const string baseUrl = "https://host.example.com/restApi"; const string endpoint = "/api/auth"; // Request parameters string encodedToken = HttpUtility.UrlEncode(YOUR-SECURITY-TOKEN); UriBuilder requestUrl = new() { Host = baseUrl + endpoint, Query = $"?token={encodedToken}" }; // Initialize HTTP client using HttpClient client = new(); client.DefaultRequestHeaders.Add("Adm-Authorization", YOUR-SECURITY-TOKEN); // Make request HttpResponseMessage response = await client.PatchAsync( requestUrl.ToString(), null); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); } }
- cURL
-
curl --header 'Adm-Authorization: YOUR-SECURITY-TOKEN' \ --get -X PATCH 'https://host.example.com/restApi/api/auth' \ --data-urlencode 'token=YOUR-SECURITY-TOKEN'
- node.js
-
var https = require('https'); // Request parameters var encodedToken = encodeURIComponent("YOUR-SECURITY-TOKEN"); var options = { 'method': 'PATCH', 'hostname': 'host.example.com', 'path': '/restApi/api/auth?token=' + encodedToken, 'headers': {'Adm-Authorization': 'YOUR-SECURITY-TOKEN'} }; // Make request var req = https.request(options, res => { var data = []; res.on("data", chunk => { data.push(chunk); }); res.on("end", () => { var body = Buffer.concat(data); console.log(body.toString()); }); res.on("error", error => { console.error(error); }); }); req.end();
- Python
-
import requests import json baseUrl = "https://host.example.com/restApi" endpoint = "/api/auth" # Request parameters requestUrl = baseUrl + endpoint requestHeaders = {"Adm-Authorization": YOUR-SECURITY-TOKEN} queryParams = {"token": YOUR-SECURITY-TOKEN} # Make request request = requests.patch(requestUrl, headers=requestHeaders, params=queryParams) response = json.loads(request.content) print(response)
Response
HTTP Status code: 200 OK
Response body:
{
"id": "5PG_xHGLU7YhKI5vb4GCvvNHs8VaCPvuHVIlj",
"token": "FU3Y9Jyz1Hf2bc7....w7lQvxjJHP9prwuDfCVd4K",
"sid": "S-1-5-21-3656734-1720699-187516-1186",
"expiresAtUtc": "2020-08-03T14:22:16.831510Z",
"applications": [
"<REST API>"
]
}
Terminate authentication session
You can terminate an existing authentication session manually before its expiration by making this request.
DELETE ~/api/authSessions?<parameters>
Query parameters
-
Name
-
Required
-
Type
-
Description
-
id
-
True
-
string
-
The identifier of the authentication session which should be terminated.
Responses
Always returns 204 No Content
status code.
Examples
Terminate authentication session
The following code sample terminates the specified authentication session.
Request
- PowerShell
-
$baseUrl = "https://host.example.com/restApi" $endpoint = "/api/authSessions" # Request parameters $queryParams = "?id=LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5" $requestUrl = $baseUrl + $endpoint + $queryParams # Make request Invoke-RestMethod -Method DELETE -Uri $requestUrl
- C#
-
using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { const string baseUrl = "https://host.example.com/restApi"; const string endpoint = "/api/authSessions"; // Request parameters const string sessionId = "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5"; string requestParams = $"?id={sessionId}"; // Initialize HTTP client using HttpClient client = new(); // Make request HttpResponseMessage response = await client.DeleteAsync( baseUrl + endpoint + requestParams); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); } }
- cURL
-
curl --get -X DELETE 'https://host.example.com/restApi/api/authSessions' \ --data-urlencode 'id=LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5'
- node.js
-
var https = require('https'); // Request parameters var options = { 'method': 'DELETE', 'hostname': 'host.example.com', 'path': '/restApi/api/authSessions?id=LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5', 'headers': {'Adm-Authorization': 'YOUR-SECURITY-TOKEN'} }; // Make request var req = https.request(options, res => { var data = []; res.on("data", chunk => { data.push(chunk); }); res.on("end", () => { var body = Buffer.concat(data); console.log(body.toString()); }); res.on("error", error => { console.error(error); }); }); req.end();
- Python
-
import requests import json baseUrl = "https://host.example.com/restApi" endpoint = "/api/authSessions" # Request parameters requestUrl = baseUrl + endpoint queryParams = {"id": "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5"} # Make request request = requests.delete(requestUrl, params=queryParams)
Response
HTTP Status code: 204 No Content
Destroy security token
You can destroy an existing security token manually before its expiration by making this request.
DELETE ~/api/auth?<parameters>
Query parameters
-
Name
-
Required
-
Type
-
Description
-
token
-
True
-
string
-
The identifier of the security token which should be destroyed.
Request headers
-
Name
-
Required
-
Description
-
Adm-Authorization
-
True
-
Specify a valid security token.
Responses
Always returns 204 No Content
status code.
Examples
Destroy security token
The following code sample destroys the specified security token.
Request
- PowerShell
-
Add-Type -AssemblyName System.Web $baseUrl = "https://host.example.com/restApi" $endpoint = "/api/auth" # Request parameters $queryParams = "?token=" + [System.Web.HttpUtility]::UrlEncode(YOUR-SECURITY-TOKEN) $requestUrl = $baseUrl + $endpoint + $queryParams $requestHeaders = @{"Adm-Authorization" = YOUR-SECURITY-TOKEN} # Make request Invoke-RestMethod -Method DELETE -Headers $requestHeaders -Uri $requestUrl
- C#
-
using System; using System.Web; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main() { const string baseUrl = "https://host.example.com"; const string endpoint = "/restApi/api/auth"; // Request parameters string encodedToken = HttpUtility.UrlEncode(YOUR-SECURITY-TOKEN); UriBuilder requestUrl = new() { Host = baseUrl + endpoint, Query = $"?token={encodedToken}" }; // Initialize HTTP client using HttpClient client = new(); client.DefaultRequestHeaders.Add("Adm-Authorization", YOUR-SECURITY-TOKEN); // Make request HttpResponseMessage response = await client.DeleteAsync(requestUrl.ToString()); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); } }
- cURL
-
curl --header 'Adm-Authorization: YOUR-SECURITY-TOKEN' \ --get -X DELETE 'https://host.example.com/restApi/api/auth' \ --data-urlencode 'token=YOUR-SECURITY-TOKEN'
- node.js
-
var https = require('https'); // Request parameters var encodedToken = encodeURIComponent("YOUR-SECURITY-TOKEN"); var options = { 'method': 'DELETE', 'hostname': 'host.example.com', 'path': '/restApi/api/auth?token=' + encodedToken, 'headers': {'Adm-Authorization': 'YOUR-SECURITY-TOKEN'} }; // Make request var req = https.request(options, res => { var data = []; res.on("data", chunk => { data.push(chunk); }); res.on("end", () => { var body = Buffer.concat(data); console.log(body.toString()); }); res.on("error", error => { console.error(error); }); }); req.end();
- Python
-
import requests import json baseUrl = "https://host.example.com/restApi" endpoint = "/api/auth" # Request parameters requestUrl = baseUrl + endpoint requestHeaders = {"Adm-Authorization": YOUR-SECURITY-TOKEN} queryParams = {"token": YOUR-SECURITY-TOKEN} # Make request request = requests.delete(requestUrl, headers=requestHeaders, params=queryParams)
Response
HTTP Status code: 204 No Content
Full authentication process
The following code sample demonstrates the full authentication process. It authenticates a user to REST API, and then invalidates the authentication session and security token.
- PowerShell
-
$baseUrl = "https://host.example.com/restApi" $username = "administrator@example.com" $password = "MyPassword" # Session request parameters $requestUrl = $baseUrl + "/api/authSessions/create" $requestBody = ConvertTo-Json @{ "username" = $username; "password" = $password } # Create session $session = Invoke-RestMethod -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json" # Get session ID $sessionId = $session.sessionId # Security token request parameters $requestUrl = $baseUrl + "/api/auth" $requestBody = ConvertTo-Json @{ "sessionId" = $sessionId; "type" = 0 } # Obtain token $authTicketInfo = Invoke-RestMethod -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json" $token = $authTicketInfo.token # Insert your requests here # Optionally: renew token # Renew token parameters $queryParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token) $requestUrl = $baseUrl + "/api/auth" + $queryParams $requestHeaders = @{"Adm-Authorization" = $token} # Renew token $authTicketInfo = Invoke-RestMethod -Method PATCH -Headers $requestHeaders ` -Uri $requestUrl $newExpirationDate = $authTicketInfo.expiresAtUtc $token = $authTicketInfo.token # Session and token will expire automatically # Optionally: terminate session and destroy token manually # Terminate session parameters $requestUrl = $baseUrl + "/api/authSessions?id=$sessionId" # Terminate session Invoke-RestMethod -Method DELETE -Uri $requestUrl # Destroy token parameters $queryParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token) $requestUrl = $baseUrl + "/api/auth" + $queryParams $requestHeaders = @{"Adm-Authorization" = $token} # Destroy token Invoke-RestMethod -Method DELETE -Headers $requestHeaders -Uri $requestUrl
- C#
-
using System.Web; using System.Text; using System.Text.Json; class Program { private const string url = "https://host.example.com/restApi"; private static HttpClient client = new(); static async Task Main() { // Get credentials string? username = Console.ReadLine(); string? password = Console.ReadLine(); string sessionId = null; string token = null; try { string jsonBody = $@" {{ 'username': ""{username}"", 'password': ""{password}"" }}"; StringContent requestBody = new(jsonBody, Encoding.UTF8, "application/json"); // Get the session identifier. HttpResponseMessage response = await client.PostAsync( $"{url}/api/authSessions/create", requestBody); string responseBody = response.Content.ReadAsStringAsync().Result; sessionId = GetJsonElement(responseBody, "sessionId"); jsonBody = $@" {{ 'sessionId': ""{sessionId}"", 'type': 0 }}"; requestBody = new(jsonBody, Encoding.UTF8, "application/json"); // Get a security token. response = await client.PostAsync($"{url}/api/auth", requestBody); responseBody = response.Content.ReadAsStringAsync().Result; token = GetJsonElement(responseBody, "token"); // Attach the security token to the HTTP client. client.DefaultRequestHeaders.Add("Adm-Authorization", token); // Renew the token every 29 minutes before it expires. using Timer timer = new( new TimerCallback(RenewToken), token, TimeSpan.Zero, TimeSpan.FromMinutes(29)); // Insert your code here } finally { // Terminate the authentication session and destroy the security token. if (sessionId is not null) await client.DeleteAsync($"{url}/api/auth?id={sessionId}"); if (token is not null) await client.DeleteAsync($"{url}/api/auth?token={token}"); // Release resources client.Dispose(); } } /// <summary> /// Returns the specified JSON element as a string. /// </summary> private static string GetJsonElement(string text, string elementName) { using JsonDocument doc = JsonDocument.Parse(text); return doc.RootElement.GetProperty(elementName).ToString(); } /// <summary> /// Renews a security token. /// </summary> private static void RenewToken(object? token) { if (token is not null) { string requestParams = $"?token={HttpUtility.UrlEncode(token.ToString())}"; client.PatchAsync($"{url}/api/auth{requestParams}", null).GetAwaiter().GetResult(); } } }
Alternative approach
The value of the security token contains encoded information that facilitates load balancing between Adaxes services that share common configuration. As a result, the token length can easily exceed 400 characters. Some client applications that send HTTP requests have a limitation on the header length, so it might not be possible to specify the token as the value of the Adm-Authorization
header.
If this is the case, you can specify the identifier of the authentication ticket (AuthTicketInfo.id) as the value of the Adm-Authorization
header instead. Such requests will be considered authorized only on one Adaxes service instance – the one where the ticket was issued.
If you have multiple Adaxes service instances that share common configuration and have to use this alternative method, you need to force all further REST API requests to be processed by the same Adaxes service. To do this, capture the value of the Adm-Service
response header, and add it as a request header to each subsequent request.
The following code sample creates an authentication session, obtains the authentication ticket identifier and the value of the Adm-Service
header, and then uses these values to send a request to retrieve a user.
- PowerShell
-
$baseUrl = "https://host.example.com/restApi" $username = "administrator@example.com" $password = "MyPassword" # Create authentication session. $requestUrl = $baseUrl + "/api/authSessions/create" $requestBody = ConvertTo-Json @{ "username" = $username; "password" = $password } $session = Invoke-RestMethod -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json" # Get session ID. $sessionId = $session.sessionId # Obtain authentication ticket. $requestUrl = $baseUrl + "/api/auth" $requestBody = ConvertTo-Json @{ "sessionId" = $sessionId; "type" = 0 } $authTicketInfo = Invoke-WebRequest -Method POST -Uri $requestUrl ` -Body $requestBody -ContentType "application/json" # Get response header and ticket identifier. $serviceHeader = $authTicketInfo.Headers.'Adm-Service' $ticketId = ($authTicketInfo.Content | ConvertFrom-Json).id # Once you have the ticket identifier and the Adm-Service header, # use these values in subsequent requests. For example, to get a user: # Specify request parameters. $userIdentifier = "CN=John Dowson,CN=Users,DC=example,DC=com" $requestUrl = $baseUrl + "/api/directoryObjects?directoryObject=$userIdentifier" $requestHeaders = @{ "Adm-Authorization" = $ticketId; "Adm-Service" = $serviceHeader } # Make request Invoke-RestMethod -Method GET -Headers $requestHeaders -Uri $requestUrl
- C#
-
using System.Web; using System.Text; using System.Text.Json; class Program { private const string url = "https://host.example.com/restApi"; private static HttpClient client = new(); static async Task Main() { // Get credentials string? username = Console.ReadLine(); string? password = Console.ReadLine(); string sessionId = null; string ticketId = null; try { string jsonBody = $@" {{ 'username': ""{username}"", 'password': ""{password}"" }}"; StringContent requestBody = new(jsonBody, Encoding.UTF8, "application/json"); // Get the session identifier. HttpResponseMessage response = await client.PostAsync( $"{url}/api/authSessions/create", requestBody); string responseBody = response.Content.ReadAsStringAsync().Result; sessionId = GetJsonElement(responseBody, "sessionId"); jsonBody = $@" {{ 'sessionId': ""{sessionId}"", 'type': 0 }}"; requestBody = new(jsonBody, Encoding.UTF8, "application/json"); // Get the authentication ticket identifier // and the Adm-Service header. response = await client.PostAsync($"{url}/api/auth", requestBody); IEnumerable<string> headerValues = response.Headers.GetValues("Adm-Service"); responseBody = response.Content.ReadAsStringAsync().Result; ticketId = GetJsonElement(responseBody, "id"); // Attach the ticket identifier to the HTTP client. client.DefaultRequestHeaders.Add("Adm-Authorization", ticketId); // Renew the ticket every 29 minutes before it expires. using Timer timer = new( new TimerCallback(RenewTicket), ticketId, TimeSpan.Zero, TimeSpan.FromMinutes(29)); // Send all subsequent requests to the same Adaxes service. client.DefaultRequestHeaders.Add("Adm-Service", headerValues.Single()); // Insert your code here } finally { // Terminate the authentication session and destroy the ticket. if (sessionId is not null) await client.DeleteAsync($"{url}/api/auth?id={sessionId}"); if (ticketId is not null) await client.DeleteAsync($"{url}/api/auth?token={ticketId}"); // Release resources client.Dispose(); } } /// <summary> /// Returns the specified JSON element as a string. /// </summary> private static string GetJsonElement(string text, string elementName) { using JsonDocument doc = JsonDocument.Parse(text); return doc.RootElement.GetProperty(elementName).ToString(); } /// <summary> /// Renews an authentication ticket. /// </summary> private static void RenewTicket(object? ticketId) { if (ticketId is not null) { string requestParams = $"?token={HttpUtility.UrlEncode(ticketId.ToString())}"; client.PatchAsync($"{url}/api/auth{requestParams}", null).GetAwaiter().GetResult(); } } }