Skip to content

Authentication

This API uses a Client Credentials style system-to-system authentication model.

It is not a full standalone OAuth Authorization Server. It provides a standards-aligned token endpoint and Bearer JWT protection for protected API routes.

First-version model

Decision Value
Flow Client Credentials
Clients Single standard integration client
Credential source Environment variables (.env)
Token request auth HTTP Basic
Access token JWT (HS256)
Default lifetime 60 minutes (expires_in=3600)
Refresh token Not supported
Scopes Not supported
MongoDB client registry Not used

Configuration

Variable Default Notes
AUTH_ENABLED false Enables token endpoint and Bearer protection
AUTH_CLIENT_ID empty Required when enabled
AUTH_CLIENT_SECRET empty Required when enabled, minimum 32 characters
AUTH_JWT_SECRET empty Required when enabled, minimum 32 bytes, must differ from client secret
AUTH_ISSUER iqv-integration-api JWT iss
AUTH_AUDIENCE iqv-integration-api JWT aud
AUTH_ACCESS_TOKEN_TTL 60m Positive, maximum 24h
AUTH_TOKEN_MAX_BODY_BYTES 16384 Token endpoint body limit

AUTH_ENABLED=false

  • Token endpoint is not registered (404)
  • POST /api/v1/inbound/work-orders remains open without Bearer tokens
  • Suitable for local development

AUTH_ENABLED=true

Example:

env AUTH_ENABLED=true AUTH_CLIENT_ID=iqv-standard-integration AUTH_CLIENT_SECRET= AUTH_JWT_SECRET= AUTH_ISSUER=iqv-integration-api AUTH_AUDIENCE=iqv-integration-api AUTH_ACCESS_TOKEN_TTL=60m

Generate secrets locally (do not commit them):

```powershell

48-character random secret example (do not commit the result)

$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' -join (1..48 | ForEach-Object { $alphabet[(Get-Random -Maximum $alphabet.Length)] }) ```

Prefer a cryptographically secure generator in production secret management.

Token endpoint

text POST {PUBLIC_BASE_URL}/api/v1/auth/token

Request

Headers:

http Authorization: Basic BASE64(client_id:client_secret) Content-Type: application/x-www-form-urlencoded Accept: application/json

Body:

text grant_type=client_credentials

Rules:

  • Credentials must come only from the Basic Authorization header
  • Do not send client_id / client_secret in the body or query string
  • JSON request bodies are rejected (415)
  • Token endpoint responses are JSON only

Success response

json { "success": true, "request_id": "uuid", "data": { "access_token": "jwt-token", "token_type": "Bearer", "expires_in": 3600 }, "error": null }

Headers include Cache-Control: no-store and Pragma: no-cache.

Using the access token

Protected endpoints require:

http Authorization: Bearer <access_token>

Example work-order call:

http POST {PUBLIC_BASE_URL}/api/v1/inbound/work-orders Authorization: Bearer <access_token> Content-Type: application/json Accept: application/json

XML requests use the same Authorization header:

http POST {PUBLIC_BASE_URL}/api/v1/inbound/work-orders Authorization: Bearer <access_token> Content-Type: application/xml Accept: application/xml

Client runtime guidance (ERP / cron)

  1. Obtain a token with client credentials.
  2. Store the token in secure memory/cache.
  3. Reuse the token for POST (and future GET) calls while it remains valid.
  4. Do not request a new token on every cron run.
  5. Renew when the token is missing, expired, or will expire within 5 minutes.
  6. Do not use refresh tokens.
  7. If the API returns 401, obtain one new token and retry the request once.

Public vs protected routes

Public:

  • GET /
  • GET /health/live
  • GET /health/ready
  • GET /health/details (existing enablement rules unchanged)
  • POST /api/v1/auth/token (only when auth is enabled)

Protected when AUTH_ENABLED=true:

  • POST /api/v1/inbound/work-orders

Transport security

  • Production must use HTTPS / TLS.
  • Local development may use HTTP on trusted networks.
  • Never send client secrets or access tokens over untrusted cleartext channels.

Error codes

Code HTTP Meaning
INVALID_REQUEST 400 Missing grant_type or malformed token request
UNSUPPORTED_GRANT_TYPE 400 grant_type is not client_credentials
INVALID_CLIENT 401 Basic client authentication failed
AUTHENTICATION_REQUIRED 401 Bearer token missing
INVALID_TOKEN 401 Bearer token invalid or expired
NOT_ACCEPTABLE 406 Unsupported Accept on token endpoint
PAYLOAD_TOO_LARGE 413 Token body exceeds limit
UNSUPPORTED_MEDIA_TYPE 415 Non-form token request Content-Type
INTERNAL_ERROR 500 Unexpected failure

Postman

  1. Create a POST request to {PUBLIC_BASE_URL}/api/v1/auth/token.
  2. Authorization tab: Type Basic Auth, username = client id, password = client secret.
  3. Body: x-www-form-urlencoded, key grant_type = client_credentials.
  4. Headers: Accept: application/json.
  5. Copy data.access_token.
  6. On work-order requests, set Authorization type Bearer Token.

PowerShell example

```powershell $baseUrl = $env:PUBLIC_BASE_URL

Token request via curl.exe to avoid embedding secrets in local scripts

$tokenJson = curl.exe -sS -X POST "$baseUrl/api/v1/auth/token" -u "$($env:AUTH_CLIENT_ID):$($env:AUTH_CLIENT_SECRET)" -H "Content-Type: application/x-www-form-urlencoded" -H "Accept: application/json" -d "grant_type=client_credentials"

$tokenResponse = $tokenJson | ConvertFrom-Json $accessToken = $tokenResponse.data.access_token

curl.exe -sS -X POST "$baseUrl/api/v1/inbound/work-orders" -H "Authorization: Bearer $accessToken" -H "Content-Type: application/json" -H "Accept: application/json" --data-binary "@work-order.json" ```

curl example

```bash BASE_URL="${PUBLIC_BASE_URL}"

curl -sS -X POST "${BASE_URL}/api/v1/auth/token" \ -u "${AUTH_CLIENT_ID}:${AUTH_CLIENT_SECRET}" \ -H "Content-Type: application/x-www-form-urlencoded" \ -H "Accept: application/json" \ -d "grant_type=client_credentials"

curl -sS -X POST "${BASE_URL}/api/v1/inbound/work-orders" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ --data-binary @work-order.json ```

Production hardening follow-ups

Not implemented in this branch, but recommended later:

  • Token endpoint rate limiting
  • Secret rotation procedures
  • Optional multi-client registry (if required by a future release)