- 10 minutes to read

OAuth 2.0 Validation Failures During Installation

When a Nodinite v7 Environment uses OAuth2 mode, the installer CLI (Nodinite.Installer.Cli.exe, see Step 7) checks the identity provider values before it changes the server. It runs this pre-flight check in validate, and before every install or update. You may see one or both of these failures:

  • Error [10.3] – OAuth2 client credentials validation failed
  • Error [10.4] – Token claims validation failed for InstallationClient

Both concern the NodiniteInstallationClient, the daemon identity the CLI uses to work against the Web API without user interaction. This guide explains the checks, then gives root causes and fixes for each error.

Understanding OAuth 2.0 Validation Architecture

How Pre-Flight Validation Works

flowchart TB Start["fa:fa-terminal CLI starts validate or deploy"] --> Config{"Installation Client Scopes
and Claims set?"} Config -->|"No"| E104a["Error 10.4
scope or claim not satisfied"] Config -->|"Yes"| Secret{"Installation client
secret supplied?"} Secret -->|"No"| Skip["Warning 10.3
live token test skipped"] Secret -->|"Yes"| Token{"Client credentials
token request succeeds?"} Token -->|"No"| E103["Error 10.3
client credentials failed"] Token -->|"Yes"| Claims{"Token carries the
required role claim?"} Claims -->|"No"| E104b["Error 10.4
claim missing"] Claims -->|"Yes"| Ok["Installation proceeds"] Skip --> Ok style Start fill:#2678BD style E104a fill:#c33d34 style E103 fill:#c33d34 style E104b fill:#c33d34 style Skip fill:#FFD525 style Ok fill:#93d16d

Red nodes stop the installation, the yellow warning means the live test didn't run, so a consent or secret problem can still surface later, and green means the pre-flight check passed. The checked values are the Installation Client Scopes and Installation Client Claims from the Portal Step 2: Auth, and the client secret you pass to the CLI.

OAuth Configuration Components

Component Purpose Configured In Critical?
Installation Client: Client ID Identifies the daemon application to Entra ID Portal OAuth2 settings → Installation Client ✅ Yes
Installation client secret Proves the daemon application's identity Not stored in the Portal: CLI prompt or --oauth2-agentinstall-secret, see Client Secrets ✅ Yes
Installation Client Scopes Requests the webApi application permissions Portal OAuth2 settings → Installation Client ✅ Yes
Installation Client Claims The token claims the check requires Portal OAuth2 settings → Installation Client ✅ Yes
webApi Application ID Identifies the protected API Indirectly, through the scope ✅ Yes
Admin consent Grants the application permission Entra ID admin center ✅ Yes

For each field's meaning and its Entra ID value, see OAuth2 settings: Discovery URL and Installation Client and the OpenID Field Mapping Quick Reference.

Error [10.3] – OAuth2 Client Credentials Validation Failed

What This Error Means

The pre-flight check couldn't obtain an access token from your identity provider with the Installation Client's Client ID and secret. This is a credentials, registration, or connectivity issue.

Common Error Messages

ERROR: [10.3] OAuth2 client credentials validation failed for InstallationClient.
       Response status code does not indicate success: 401 (Unauthorized).

ERROR: [10.3] OAuth2 client credentials validation failed for InstallationClient.
       One or more errors occurred: 'InvalidClientSecret' or 'Unknown_UserType'

Root Cause Analysis

# Root Cause How to Recognize Evidence
1 Installation Client: Client ID is incorrect or missing Copied from the wrong app registration, or a typo 401 Unauthorized every time
2 Client secret is incorrect, expired, or contains extra whitespace Copy/paste added a space, the secret was regenerated, or it expired 401 Unauthorized; a sudden failure after weeks of success
3 NodiniteInstallationClient app registration doesn't exist Never registered, or deleted 401 Unauthorized consistently
4 Installation Client Scopes is malformed Copied without the .default suffix 400 Bad Request, "scope" in the message
5 Discovery URL uses the tenant name or a wrong tenant ID Discovery URL doesn't hold the Directory (tenant) ID GUID 400 or 404
6 Firewall or proxy blocks the identity provider Outbound HTTPS to login.microsoftonline.com blocked Timeout instead of 401
7 Identity provider unavailable Entra ID service issue (rare) Timeout or 5xx server error

Quick Fix Checklist – Error [10.3]

Follow these steps in order. Most cases are resolved by steps 1–3.

Step 1: Verify the Installation Client: Client ID

  1. In the Portal Auth step, open OAuth2 settings → Installation Client → Client ID (see Installation Client: Client ID).
  2. Copy the value into a plain text editor to reveal hidden spaces.
  3. Compare it with Microsoft Entra ID > App registrations > NodiniteInstallationClient > Overview > Application (client) ID.

Typical mistakes are the webClient ID instead of the NodiniteInstallationClient ID, a partial ID copied from a URL, and leading or trailing spaces.

Step 2: Regenerate the Client Secret

Entra ID shows a client secret only once, when you create it. If you don't have it, or it expired:

  1. Microsoft Entra ID > App registrations > NodiniteInstallationClient > Certificates & secrets.
  2. Delete the expired secret under Client secrets (⋯ > Delete).
  3. Click + New client secret, enter a description such as Nodinite Installation Client Secret and an expiry that matches your rotation policy, and click Add.
  4. Copy the Value immediately and store it in your secret vault.
  5. Pass it to the CLI at the prompt or with --oauth2-agentinstall-secret, without leading or trailing spaces; see Step 7: Passing arguments.

Step 3: Verify Installation Client Scopes

  1. Open OAuth2 settings → Installation Client → Installation Client Scopes (see Installation Client Scopes).
  2. Confirm the value is exactly api://<webApi-client-id>/.default, with the Application (client) ID of the webApi app registration, for example api://d731e991-1234-5678-90ab-cdef12345678/.default.

Typical mistakes are a missing .default suffix, only generic scopes such as openid, and an incomplete GUID.

  1. Microsoft Entra ID > App registrations > NodiniteInstallationClient > API permissions.
  2. Find AppRole_WebApi_all from the webApi app and check the Status column:
    • ✅ Granted for [Tenant Name]: correct.
    • ❌ Not granted, or a warning icon: click Grant admin consent for [Tenant Name] and confirm.

Granting tenant-wide admin consent needs an administrator role that is allowed to grant it, such as Global Administrator or Privileged Role Administrator; ask your Entra ID administrator if the button is unavailable.

Step 5: Verify NodiniteInstallationClient Exists

  1. Microsoft Entra ID > App registrations, with the filter set to All applications (not just "Owned by me").
  2. Search for NodiniteInstallationClient. If it doesn't exist, create it with Register Nodinite Applications in Azure AD.
  3. If AppRole_WebApi_all is missing under API permissions, add it: + Add a permission > My APIs > webApi > Application permissions, tick AppRole_WebApi_all, click Add permissions, and grant admin consent.

Step 6: Test Connectivity to the Identity Provider

On the server where you run the CLI, fetch the discovery document from the Discovery URL:

# Expect StatusCode 200 and the token_endpoint of your tenant
$r = Invoke-WebRequest -Uri "https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration"
$r.StatusCode
($r.Content | ConvertFrom-Json).token_endpoint
Result Meaning
✅ 200 with your token endpoint Network and tenant ID are OK; the issue is the credentials
❌ 400 or 404 Wrong tenant ID or tenant name in the Discovery URL
❌ Timeout or connection refused Firewall or proxy blocks outbound HTTPS; see the Network and Firewall Overview and Configure Network / Proxy

Error [10.4] – Token Claims Validation Failed

What This Error Means

The Installation Client Scopes or Installation Client Claims are missing or wrong, or the token the CLI obtained lacks the required scope or role claim. When the credentials work but the claim is missing, admin consent was usually not granted.

Common Error Messages

ERROR: [10.4] Token claims validation failed for InstallationClient.
       Required scope 'api://<webApi-client-id>/.default' not satisfied

ERROR: [10.4] Token claims validation failed for InstallationClient.
       Required claim 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' is missing

ERROR: [10.4] Token claims validation failed for InstallationClient.
       Required claim value 'AppRole_WebApi_all' not found in token

Root Cause Analysis – Error [10.4]

# Root Cause How to Recognize Evidence
1 Admin consent not granted for AppRole_WebApi_all Status shows "Not granted" in Entra ID The role claim is missing from the token
2 Installation Client Claims key/value incorrect Shortened KEY, or the description instead of the value Required claim value not found
3 App role doesn't exist on webApi AppRole_WebApi_all was never created The token can't carry the role
4 Installation Client Scopes lacks .default api://guid instead of api://guid/.default Scope not satisfied
5 webApi issues version 1 tokens requestedAccessTokenVersion isn't 2 Claim format differs

Quick Fix Checklist – Error [10.4]

Entra ID Token Claims Validation walks through these fixes in detail, including the access token version.

This is the most common cause. Check the Status of AppRole_WebApi_all as in Step 4 of the Error [10.3] checklist, grant consent if needed, and wait 1–2 minutes before you rerun the CLI.

Step 2: Verify Installation Client Claims Configuration

Open OAuth2 settings → Installation Client → Installation Client Claims (see Installation Client Claims) and verify the pair:

Field Correct Value
Key http://schemas.microsoft.com/ws/2008/06/identity/claims/role
Value AppRole_WebApi_all

Typical mistakes are a shortened KEY such as roles, the role's description as VALUE (for example "Application permission for…"), and extra spaces.

Step 3: Verify AppRole_WebApi_all Exists on webApi

  1. Microsoft Entra ID > App registrations > webApi > App roles.
  2. Look for AppRole_WebApi_all with Allowed member types Applications, Value AppRole_WebApi_all, and State Enabled.
  3. If it's missing, create it as in Register Nodinite Applications in Azure AD, section 1.3.1, then grant admin consent again on NodiniteInstallationClient > API permissions.

Step 4: Verify Installation Client Scopes

The scope must end with .default (api://<webApi-client-id>/.default); see Step 3 of the Error [10.3] checklist.

Common Mistakes and How to Avoid Them

Mistake Symptom Prevention
Copy-paste adds hidden spaces to an ID or secret Error [10.3], 401 on every attempt Paste into a plain text editor first and trim
webClient ID used as the Installation Client's Client ID Error [10.3], 401 webClient is for interactive users; the Installation Client needs the NodiniteInstallationClient ID
Admin consent skipped Error [10.4], required claim missing Always click Grant admin consent after adding API permissions, then wait 1–2 minutes
Role description used as Claims VALUE Error [10.4], claim value not found Use the role Value: AppRole_WebApi_all
Scope references the wrong webApi ID Error [10.4], scope not satisfied Use the webApi Application (client) ID from its Overview, with .default
Client secret expired Error [10.3] after weeks or months of success Set a calendar reminder 30 days before expiry, create a new secret, and rerun the update
Tenant name instead of tenant ID in the Discovery URL Error [10.3], 400 or 404 Use the Directory (tenant) ID GUID: https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration

Debugging Tips

Get Detailed CLI Output

Run the pre-flight check on its own and write a JSON report you can share with support:

.\Nodinite.Installer.Cli.exe validate --config .\localhost\config.cli.json --output report.json --format json

deploy-environment --verbose gives the same detail during an install or update; see Step 7: Troubleshooting.

Test Token Generation Manually

Request a token for the Installation Client and decode its claims:

$tenantId     = "<tenant-id>"                      # Directory (tenant) ID
$clientId     = "<installation-client-id>"         # NodiniteInstallationClient
$clientSecret = Read-Host "Client secret" -MaskInput
$webApiId     = "<webApi-client-id>"               # webApi Application (client) ID
$body = @{
    grant_type    = "client_credentials"
    client_id     = $clientId
    client_secret = $clientSecret
    scope         = "api://$webApiId/.default"
}
$token = (Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Body $body).access_token
# Decode the JWT payload (base64url) to inspect aud, ver, and roles
$payload = $token.Split('.')[1].Replace('-', '+').Replace('_', '/')
$payload = $payload.PadRight($payload.Length + (4 - $payload.Length % 4) % 4, '=')
$claims = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($payload)) | ConvertFrom-Json
$claims | Select-Object aud, ver, roles
Result Meaning
✅ roles holds AppRole_WebApi_all, ver is 2.0 Entra ID is correct; check the Portal values
❌ The request fails with 401 Error [10.3] causes: client ID or secret
❌ roles is empty Error [10.4] causes: admin consent or app role
⚠️ ver is 1.0 Set requestedAccessTokenVersion to 2 on webApi (section 1.6)

Check Certificate Credentials

If your organization uses a certificate credential for the NodiniteInstallationClient instead of a client secret, verify under Certificates & secrets that it hasn't expired, and that the certificate with its private key is in the LocalMachine certificate store of the server that runs the CLI.

After the Fix

  1. Rerun validate, then the install or update; see Step 7.
  2. Watch the rest of the pre-flight check; other checks may follow.
  3. Verify access to the Web API after installation; see Call the Web API with OAuth 2.0 Client Credentials.
  4. Plan secret rotation before the new secret expires.

Next Steps