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

Tip

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.

Important

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 {.black}
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.

Tip

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"
$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 StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Initialize HTTP client
        using (HttpClient client = new HttpClient())
        {
            // 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 and headers
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, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.write(postData);

req.end();

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.

Important

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.

Tip

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"
$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 StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Initialize HTTP client
        using (HttpClient client = new HttpClient())
        {
            // 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 and headers
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, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.write(postData);

req.end();

Response

HTTP Status code: 200 OK
Response body:

{
    "id": "5PG_xHGLU7YhKI5vb4GCvvNHs8VaCPvuHVIlj",
    "token": "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD",
    "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>

Tip

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

$token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD"
$baseUrl = "https://host.example.com/restApi"
$endpoint = "/api/auth"
$requestParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token)
$requestUrl = $baseUrl + $endpoint + $requestParams
$requestHeaders = @{"Adm-Authorization" = $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 token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD";
        string encodedToken = HttpUtility.UrlEncode(token);

        UriBuilder requestUrl = new UriBuilder(
            "https://host.example.com/restApi/api/auth");
        requestUrl.Query = $"?token={encodedToken}";

        // Initialize HTTP client
        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("Adm-Authorization", 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: HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD' \
--get -X PATCH 'https://host.example.com/restApi/api/auth' \
--data-urlencode 'token=HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD'
node.js
var https = require('https');

var token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD";
var encodedToken = encodeURIComponent(token);

// Request parameters and headers
var options = {
    'method': 'PATCH',
    'hostname': 'host.example.com',
    'path': '/restApi/api/auth?token=' + encodedToken,
    'headers': {
        "Adm-Authorization": token
    }
};

// Make request
var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();

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"
$requestParams = "?id=LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5"
$requestUrl = $baseUrl + $endpoint + $requestParams

# 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 sessionId = "LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5";

        const string baseUrl = "https://host.example.com/restApi";
        const string endpoint = "/api/authSessions";
        string requestParams = $"?id={sessionId}";

        // Initialize HTTP client
        using (HttpClient client = new HttpClient())
        {
            // Make request
            HttpResponseMessage response = await client.DeleteAsync(
                baseUrl + endpoint + requestParams);
            Console.WriteLine(response);
        }
    }
}
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 and headers
var options = {
    'method': 'DELETE',
    'hostname': 'host.example.com',
    'path': '/restApi/api/authSessions?id=LBxsm-yOBDNSxwT6o_DLAOf9ocVRtW5',
    'headers': {
    }
};

// Make request
var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();

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

$token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD"
$baseUrl = "https://host.example.com/restApi"
$endpoint = "/api/auth"
$requestParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token)
$requestUrl = $baseUrl + $endpoint + $requestParams
$requestHeaders = @{"Adm-Authorization" = $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 token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD";
        string encodedToken = HttpUtility.UrlEncode(token);

        UriBuilder requestUrl = new UriBuilder(
            "https://host.example.com/restApi/api/auth");
        requestUrl.Query = $"?token={encodedToken}";

        // Initialize HTTP client
        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("Adm-Authorization", token);

            // Make request
            HttpResponseMessage response = await client.DeleteAsync(requestUrl.ToString());
            Console.WriteLine(response);
        }
    }
}
cURL
curl --header 'Adm-Authorization: HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD' \
--get -X DELETE 'https://host.example.com/restApi/api/auth' \
--data-urlencode 'token=HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD'
node.js
var https = require('https');

var token = "HxtdAPz73OFfae7....w7lQvxjJHIbVqgkCtPtLD";
var encodedToken = encodeURIComponent(token);

// Request parameters and headers
var options = {
    'method': 'DELETE',
    'hostname': 'host.example.com',
    'path': '/restApi/api/auth?token=' + encodedToken,
    'headers': {
        "Adm-Authorization": token
    }
};

// Make request
var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();

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"

# Session request parameters
$requestUrl = $baseUrl + "/api/authSessions/create"
$requestBody = ConvertTo-Json @{
    "username" = "administrator@example.com";
    "password" = "MyPassword"
}

# 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
$requestParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token)
$requestUrl = $baseUrl + "/api/auth" + $requestParams
$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
$requestParams = "?token=" + [System.Web.HttpUtility]::UrlEncode($token)
$requestUrl = $baseUrl + "/api/auth" + $requestParams
$requestHeaders = @{"Adm-Authorization" = $token}

# Destroy token
Invoke-RestMethod -Method DELETE -Headers $requestHeaders -Uri $requestUrl
C#
using System;
using System.Web;
using System.Text;
using System.Text.Json;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;

// Define base URL
static class BaseUrl
{
    public const string url = "https://host.example.com/restApi";
}

// Define request body data structures
public class AuthSessionRequest
{
    public string username { get; set; }
    public string password { get; set; }
}

public class AuthTicketRequest
{
    public string sessionId { get; set; }
    public int type { get; set; }
}

// Define response body data structures
public class AuthSession
{
    public string sessionId { get; set; }
    public object totpState { get; set; }
    public int changePasswordReason { get; set; }
    public DateTime expiresAtUtc { get; set; }
}

public class AuthTicketInfo
{
    public string id { get; set; }
    public string token { get; set; }
    public string sid { get; set; }
    public DateTime expiresAtUtc { get; set; }
    public List<string> applications { get; set; }
    public object signaturePublicKey { get; set; }
}

class Program
{
    static readonly HttpClient Client = new HttpClient();

    // Create authentication session
    static async Task<AuthSession> CreateSession(string username, string password)
    {
        const string endpoint = "/api/authSessions/create";

        // Build JSON session request body
        AuthSessionRequest request = new AuthSessionRequest();
        request.username = username;
        request.password = password;

        string jsonRequest = JsonSerializer.Serialize(request);
        StringContent requestBody = new StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Make request
        HttpResponseMessage response = await Client.PostAsync(
            BaseUrl.url + endpoint, requestBody);

        // Deserialize and return response body
        string responseBody = response.Content.ReadAsStringAsync().Result;
        AuthSession session = JsonSerializer.Deserialize<AuthSession>(responseBody);
        return session;
    }

    // Issue authentication ticket
    static async Task<AuthTicketInfo> IssueTicket(string sessionId)
    {
        const string endpoint = "/api/auth";

        // Build JSON ticket request body
        AuthTicketRequest request = new AuthTicketRequest();
        request.sessionId = sessionId;
        request.type = 0;

        string jsonRequest = JsonSerializer.Serialize(request);
        StringContent requestBody = new StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Make request
        HttpResponseMessage response = await Client.PostAsync(
            BaseUrl.url + endpoint, requestBody);

        // Deserialize and return response body
        string responseBody = response.Content.ReadAsStringAsync().Result;
        AuthTicketInfo authTicket = JsonSerializer.Deserialize<AuthTicketInfo>(responseBody);
        return authTicket;
    }

    // Renew security token
    static async Task<AuthTicketInfo> RenewToken(string token)
    {
        const string endpoint = "/api/auth";
        string encodedToken = HttpUtility.UrlEncode(token);
        string requestParams = "?token=" + encodedToken;
        Client.DefaultRequestHeaders.Add("Adm-Authorization", token);

        // Make request
        HttpResponseMessage response = await Client.PatchAsync(
            BaseUrl.url + endpoint + requestParams, null!);

        // Deserialize and return response body
        string responseBody = response.Content.ReadAsStringAsync().Result;
        AuthTicketInfo authTicket = JsonSerializer.Deserialize<AuthTicketInfo>(responseBody);
        return authTicket;
    }

    // Terminate authentication session
    static async Task TerminateSession(string sessionId)
    {
        const string endpoint = "/api/authSessions";
        string requestParams = "?id=" + sessionId;

        // Make request
        await Client.DeleteAsync(BaseUrl.url + endpoint + requestParams);
    }

    // Destroy security token
    static async Task DestroyToken(string token)
    {
        const string endpoint = "/api/auth";
        string encodedToken = HttpUtility.UrlEncode(token);
        string requestParams = "?token=" + encodedToken;
        Client.DefaultRequestHeaders.Add("Adm-Authorization", token);

        // Make request
        await Client.DeleteAsync(BaseUrl.url + endpoint + requestParams);
    }

    static async Task Main()
    {
        // Obtain token
        AuthSession mySession = await CreateSession("administrator@example.com", "MyPassword");
        AuthTicketInfo authTicket = await IssueTicket(mySession.sessionId);

        // Save the token value
        string token = authTicket.token;

        // Insert your requests here
        
        // Optionally:Renew token
        authTicket = await RenewToken(token);
        DateTime newExpirationDate = authTicket.expiresAtUtc;
        token = authTicket.token;

        // Session and token will expire automatically
        // Optionally: terminate session and destroy token manually
        await TerminateSession(mySession.sessionId);
        await DestroyToken(token);

        // Release resources
        Client.Dispose();
    }
}

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"

# Create authentication session.
$requestUrl = $baseUrl + "/api/authSessions/create"
$requestBody = ConvertTo-Json @{
    "username" = "administrator@example.com";
    "password" = "MyPassword"
}
$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.
$admServiceHeader = $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" = $admServiceHeader
}

# Make request
Invoke-RestMethod -Method GET -Headers $requestHeaders -Uri $requestUrl
C#
using System;
using System.Text;
using System.Text.Json;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

// Define base URL
static class BaseUrl
{
    public const string url = "https://host.example.com/restApi";
}

// Define request body data structures
public class AuthSessionRequest
{
    public string username { get; set; }
    public string password { get; set; }
}

public class AuthTicketRequest
{
    public string sessionId { get; set; }
    public int type { get; set; }
}

// Define response body data structures
public class AuthSession
{
    public string sessionId { get; set; }
    public object totpState { get; set; }
    public int changePasswordReason { get; set; }
    public DateTime expiresAtUtc { get; set; }
}

public class AuthTicketInfo
{
    public string id { get; set; }
    public string token { get; set; }
    public string sid { get; set; }
    public DateTime expiresAtUtc { get; set; }
    public List<string> applications { get; set; }
    public object signaturePublicKey { get; set; }
}

class Program
{
    static readonly HttpClient Client = new HttpClient();

    // Create authentication session
    static async Task<AuthSession> CreateSession(string username, string password)
    {
        const string endpoint = "/api/authSessions/create";

        // Build JSON session request body
        AuthSessionRequest request = new AuthSessionRequest();
        request.username = username;
        request.password = password;

        string jsonRequest = JsonSerializer.Serialize(request);
        StringContent requestBody = new StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Make request
        HttpResponseMessage response = await Client.PostAsync(
            BaseUrl.url + endpoint, requestBody);

        // Deserialize and return response body
        string responseBody = response.Content.ReadAsStringAsync().Result;
        AuthSession session = JsonSerializer.Deserialize<AuthSession>(responseBody);
        return session;
    }

    // Issue authentication ticket
    static async Task<(AuthTicketInfo,string)> IssueTicket(string sessionId)
    {
        const string endpoint = "/api/auth";

        // Build JSON ticket request body
        AuthTicketRequest request = new AuthTicketRequest();
        request.sessionId = sessionId;
        request.type = 0;

        string jsonRequest = JsonSerializer.Serialize(request);
        StringContent requestBody = new StringContent(
            jsonRequest, Encoding.UTF8, "application/json");

        // Make request
        HttpResponseMessage response = await Client.PostAsync(
            BaseUrl.url + endpoint, requestBody);

        // Deserialize and return response body and header
        string responseBody = response.Content.ReadAsStringAsync().Result;
        IEnumerable<string> headerValues = response.Headers.GetValues("Adm-Service");
        string admServiceHeader = headerValues.Single();
        AuthTicketInfo authTicket = JsonSerializer.Deserialize<AuthTicketInfo>(responseBody);
        return (authTicket, admServiceHeader);
    }
    static async Task Main()
    {
        // Obtain ticket identifier and Adm-Service reponse header
        AuthSession mySession = await CreateSession("administrator@example.com", "MyPassword");
        (AuthTicketInfo ticket, string admServiceHeader) = await IssueTicket(mySession.sessionId);

        // Once you have the ticket identifier and the Adm-Service header, 
        // use these values in subsequent requests. For example, to get a user:
        string userIdentifier = "CN=John Smith,CN=Users,DC=example,DC=com";
        UriBuilder requestUrl = new UriBuilder(BaseUrl.url);
        requestUrl.Path += "/api/directoryObjects";
        requestUrl.Query += $"?directoryObject={userIdentifier}";
        Client.DefaultRequestHeaders.Add("Adm-Authorization", ticket.id);
        Client.DefaultRequestHeaders.Add("Adm-Service", admServiceHeader);

        string response = await Client.GetStringAsync(requestUrl.ToString());
        Console.WriteLine(response);

        // Release resources
        Client.Dispose();
    }
}

See also