Protect the Nodinite Log API with OAuth 2.0 and Entra ID
By default, the Nodinite Log API accepts Log Events from any client that can reach it. When Nodinite runs in OpenID Connect / OAuth 2.0 mode, you can require a bearer access token on every Log Event. This guide shows how to:
- Register the Log API in Microsoft Entra ID.
- Register a client for each system that sends Log Events.
- Turn on authentication in the Nodinite Portal.
- Get a token and send Log Events.
- Harden (recommended for production): allow only approved clients to send Log Events.
Note
This guide continues Register Nodinite Applications in Azure AD (Entra ID) with OpenID. Complete that guide first. Nodinite must already run in OpenID mode, with the webApi, webClient, and NodiniteInstallationClient app registrations in place.
Understanding the Protected Log API
The logging client gets a token for the Log API from Entra ID with the client credentials flow, and sends it with every Log Event.
Key Components
| App registration | Purpose |
|---|---|
| logApi | Represents the Nodinite Log API. Clients request their tokens for it. |
| Logging client (one per sending system) | The identity of a system that sends Log Events, such as an integration, a custom logger, a script, or the Pickup Service. |
Important
Who can send Log Events with the basic setup: the Log API accepts any valid token issued for it, and Entra ID issues a Log API token to any application registered in your tenant. The client needs no permission for it. So after Steps 1–4, any app registration in your tenant can send Log Events. Before, anyone who could reach the Log API could. To allow only clients you approve, also complete Step 5: Harden. We recommend it for every production environment.
Basic vs Hardened Setup
| Steps 1–4 only | Steps 1–5 (hardened) | |
|---|---|---|
| Who can send Log Events | Any app registration in your tenant | Only clients assigned AppRole_LogApi_write |
| Extra work per new client | None | Add the permission and grant admin consent (Step 5.2) |
| A client that is not approved | Gets a token, and its Log Events are accepted | Gets no token (AADSTS501051) |
Prerequisites
- Nodinite v7 runs in OpenID mode with Entra ID, and users can sign in to the Web Client.
- You can create app registrations in Entra ID.
- You can sign in to the Nodinite Portal and edit the environment's OpenID settings.
- You have a list of every system that sends Log Events to this Log API.
Warning
Once authentication is on, every client that sends Log Events must send a valid bearer token. A client without one gets
401 Unauthorized, and its Log Events are lost. Before you turn authentication on in Step 3, check that every logging client in your list can get and send a token.
Step 1: Register the Log API (logApi)
1.1 Create the App Registration
- In the Microsoft Entra admin center, go to Entra ID > App registrations > + New registration.
- Name:
logApi, or your own convention, for examplenodinite-prod-logapi. - Supported account types: Accounts in this organizational directory only.
- Redirect URI: leave it empty.
- Select Register.
- Note the Application (client) ID. You enter it in the Nodinite Portal in Step 3.

You register the logApi application. It needs no secret or redirect URI, because it only represents the API.
1.2 Expose the API
Open Expose an API.
Next to Application ID URI, select Add.
Accept the default
api://<logApi-client-id>, then select Save.
1.3 Set the Access Token Version to 2
- Open Manifest.
- Set
requestedAccessTokenVersionto2(in older manifest views,accessTokenAcceptedVersion). - Select Save.

You set requestedAccessTokenVersion to 2 in the logApi manifest.
Warning
Don't skip this step. By default, Entra ID issues version 1 tokens, which have the issuer
https://sts.windows.net/<tenant>/. Nodinite expects the version 2 issuerhttps://login.microsoftonline.com/<tenant>/v2.0, so it rejects every version 1 token with401 Unauthorized.
The logApi application is ready.
Step 2: Register a Logging Client
Create one client app registration per system that sends Log Events. You can then audit and revoke each system on its own.
- Go to Entra ID > App registrations > + New registration.
- Name: a name that identifies the system, for example
logApi-client-orders-integration. - Supported account types: Accounts in this organizational directory only.
- Redirect URI: leave it empty.
- Select Register and note the Application (client) ID.
- Open Certificates & secrets. Upload a certificate (recommended), or select + New client secret.
- If you create a secret, copy the Value immediately, because it is shown only once. Store it in a secret store, for example Azure Key Vault, and note the expiry date. When the secret expires, the client stops sending Log Events.

You create a client secret for the logging client.
Note
The basic setup needs no API permissions on the client. To require them, see Step 5: Harden.
The logging client is registered.
Step 3: Enable Authentication in the Nodinite Portal
- In the Nodinite Portal, open the environment's OpenID settings and scroll to the Log API section.
- Under Audiences, enter the Application (client) ID of the logApi app registration (Step 1.1), then select Add.
- Check Enable Authentication.
- Save the settings and deploy the change to the environment.

You add the logApi audience and enable authentication for the Log API. See OAuth Log API settings.
Important
Enter the plain Application (client) ID, for example
757be812-1f79-4923-9103-16028f6e808a. Don't enter theapi://…URI. A version 2 token (Step 1.3) carries the client ID as its audience (aud).
Warning
From now on, the Log API rejects Log Events without a valid token. Turn this on in a test environment first. Switch production over only after every logging client sends tokens.
The Log API now requires a bearer token.
Step 4: Get a Token and Send a Log Event
| Placeholder | Value |
|---|---|
<tenant-id> |
Your Entra ID Directory (tenant) ID |
<client-id> |
The logging client's Application (client) ID (Step 2) |
<client-secret> |
The logging client's secret (Step 2) |
<logapi-client-id> |
The logApi Application (client) ID (Step 1.1) |
<logapi-base-url> |
The Log API base URL, for example https://nodinite.contoso.com:40002/LogAPI/. See Find the base URL. |
The token request always uses the scope api://<logapi-client-id>/.default.
PowerShell
$body = @{
grant_type = 'client_credentials'
client_id = '<client-id>'
client_secret = '<client-secret>'
scope = 'api://<logapi-client-id>/.default'
}
$token = (Invoke-RestMethod -Method Post `
-Uri 'https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token' `
-Body $body).access_token
$logEvent = Get-Content -Raw .\logevent.json # a Nodinite JSON Log Event
Invoke-RestMethod -Method Post `
-Uri '<logapi-base-url>api/LogEvent' `
-Headers @{ Authorization = "Bearer $token" } `
-ContentType 'application/json' `
-Body $logEvent
curl
TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" \
-d "grant_type=client_credentials" \
-d "client_id=<client-id>" \
--data-urlencode "client_secret=<client-secret>" \
--data-urlencode "scope=api://<logapi-client-id>/.default" | jq -r .access_token)
curl -X POST "<logapi-base-url>api/LogEvent" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @logevent.json
For a JSON formatted Log Event and samples in C#, Python, and Node.js, see Log using REST.
Pickup Service
On the Destination tab of each source configuration in the Pickup Service, check Protected and fill in:
| Field | Value |
|---|---|
| Client ID | The logging client's Application (client) ID (Step 2) |
| Client Secret | The logging client's secret (Step 2) |
| Scope | api://<logapi-client-id>/.default |
| IDP Token Endpoint | https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token |

With Protected checked, the Pickup Service gets a token with the client credentials grant before it calls the Log API.
Endpoints
| Endpoint | Token required |
|---|---|
POST /LogAPI/api/LogEvent |
Yes |
POST /LogAPI/api/LogEvent/Batch |
Yes |
POST /LogAPI/api/LogEvent/Validate |
Yes |
POST /LogAPI/api/LogEvent/Batch/Validate |
Yes |
GET /LogAPI/api/LogEvent/EndPointTypes, EndPointDirection, EventDirection |
No (reference data) |
GET /isalive |
No (health check) |
Tip
To test a token without storing anything,
POSTto/LogAPI/api/LogEvent/Validate. A400or200response means the token was accepted. A401means it was rejected. See Troubleshooting.
Tokens expire after about an hour. Request a new token before it expires, or when the Log API returns 401.
Step 5: Harden: Allow Only Approved Clients
With Steps 1–4, any app registration in your tenant can get a Log API token and send Log Events. That's acceptable in a test environment, but in production you usually want to decide exactly which systems can log.
This step adds an app role to logApi, assigns it to each approved client, and makes Entra ID refuse Log API tokens to every other application. The Log API itself doesn't change: Entra ID simply stops issuing tokens to clients you haven't approved.
5.1 Create an App Role on logApi
- Open the logApi app registration → App roles > + Create app role.
- Fill in the fields:
- Display name:
Log Writer - Allowed member types: Applications
- Value:
AppRole_LogApi_write - Description:
Applications that send log events to the Nodinite Log API
- Display name:
- Select Apply.

You create the AppRole_LogApi_write app role.
5.2 Assign the Role to Each Approved Client
Open the logging client app registration → API permissions > + Add a permission > My APIs > logApi.
Select Application permissions, check AppRole_LogApi_write, then select Add permissions.

You add theAppRole_LogApi_writeapplication permission to the logging client.Select Grant admin consent for <tenant>. The status changes from Not granted to Granted.
Repeat this for every approved logging client.
5.3 Require Assignment
- Go to Entra ID > Enterprise apps > All applications and open logApi.
- Open Properties, set Assignment required? to Yes, then select Save.

You set Assignment required? to Yes on the logApi enterprise application.
From now on, Entra ID issues Log API tokens only to clients that have been assigned the role. Every other application gets the error AADSTS501051 when it requests a token. See Microsoft: Controlling tokens without the roles claim.
Warning
Complete 5.2 for every logging client before you complete 5.3. Once assignment is required, a client without the role can't get a token and stops sending Log Events.
Only approved clients can send Log Events.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Log API returns 401, and the token's iss is https://sts.windows.net/… |
logApi still issues version 1 tokens | Step 1.3: set requestedAccessTokenVersion to 2, then request a new token. |
Log API returns 401, and the token's aud is not the logApi client ID |
Wrong scope, or the Audiences value is wrong | Request the token with api://<logapi-client-id>/.default. In the Portal, Audiences must contain the plain logApi client ID (Step 3). |
Log API returns 401 for a client that worked before |
Authentication was turned on and the client sends no token | Update the client to send a bearer token, see Step 4. |
Token request fails: AADSTS501051 |
Assignment required is on and the client has no role (Step 5) | Step 5.2: add and grant AppRole_LogApi_write for the client. |
Token request fails: AADSTS7000215 |
Wrong client secret | Use the secret Value, not the secret ID. |
Token request fails: AADSTS7000222 |
The client secret has expired | Create a new secret and update the client. |
Tip
To see what a token contains, paste it into jwt.ms, which decodes it in your browser. Check
iss,aud, andexp.
What You've Accomplished
- logApi registered: the Log API has its own identity in Entra ID and issues version 2 tokens.
- Log API protected: the Log API rejects Log Events without a valid token.
- One client per system: each sending system has its own credential that you can audit and revoke.
- Hardened (Step 5): Entra ID issues Log API tokens only to clients you approved.


