Authentication

The authentication process with Adaxes REST API consists of two HTTP requests that must be executed in the following order:

  1. Create authentication session.
  2. 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

  • Name

  • Required

  • Type

  • Description

  • token

  • True

  • string

  • The security token that should be renewed.

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

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();   
        }
    }
}

See also