Skip to main content

Chapter 4 — Architecture and Authentication

This chapter describes the authentication and authorization model used across the entire BR-UTM ecosystem, including how your USS obtains tokens, uses them to call DECEA's APIs, validates tokens received from other USSs, and authenticates peer-to-peer calls.


4.1 Authentication Architecture Overview

BR-UTM uses OAuth2 Client Credentials flow with JWT (JSON Web Token) access tokens, signed using RS256 (RSA SHA-256). This is a stateless, distributed authentication model where:

  1. Your USS presents its API Key to DECEA's Auth Server to obtain a signed JWT.
  2. The JWT is included as a Bearer token in every API request (to the DSS, to DECEA's USS, or to other USSs).
  3. The receiving server validates the JWT locally using DECEA's public key — it does not need to call the Auth Server again.

This architecture is critical for the distributed, peer-to-peer nature of the system: there is no central session state, and any server can independently validate any token.

┌──────────────────┐   1. POST /token?apikey=...&scope=...&intended_audience=...
│   Your USS       │──────────────────────────────────────────────────────────────►│ Auth Server │
│                  │◄──────────────────────────────── 2. JWT (signed RS256) ───────│             │
│                  │
│                  │   3. Authorization: Bearer <JWT>
│                  │──────────────────────────────────────────────────────────────►│ DSS / USS   │
│                  │◄──────────────────────────────── 4. Response ────────────────│             │
└──────────────────┘

4.2 Obtaining a JWT Token

To obtain a JWT, send an HTTP GET or POST request to the Auth Server token endpoint:

Endpoint: http://api.sandbox.brutm.dcta.mil.br/token

Query parameters (or request body):

ParameterDescriptionExample
apikeyYour company's API Key, obtained from the Portal UTM. Can also be sent as an HTTP header.abc123...
scopeThe OAuth2 scope(s) you need for the operation. Space-separated for multiple scopes.utm.strategic_coordination utm.constraint_processing
intended_audienceThe FQDN (domain name only, no path) of the server this token will be sent to.api.sandbox.brutm.dcta.mil.br or uss-b.yourpartner.com

Example request:

GET /token?scope=utm.strategic_coordination&intended_audience=api.sandbox.brutm.dcta.mil.br
Authorization: ApiKey abc123yourapikey

Example response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

4.3 JWT Token Structure

Every token issued by DECEA's Auth Server is a signed JWT containing the following claims:

ClaimDescriptionExample
issThe URL of the Auth Server that issued the token.http://api.sandbox.brutm.dcta.mil.br/token
expToken expiration timestamp (Unix epoch). Maximum 1 hour from issuance.1751327400
subYour USS's unique identifier — the manager identifier in DSS records."my-company-uss"
scopeGranted scopes, space-separated."utm.strategic_coordination utm.constraint_processing"
jtiUnique token ID for replay protection (RFC 7519)."d3e8f921-..."
audThe FQDN of the intended recipient server."api.sandbox.brutm.dcta.mil.br"

Token Validity

  • Tokens are valid for up to 1 hour (inspect the exp claim for the exact expiry time).
  • Cache and reuse tokens until they are near expiry. Requesting a new token on every API call is wasteful and may cause rate limiting.
  • A single token can carry multiple scopes (space-separated in the scope claim), so you can request all the scopes you need for a workflow in one token request.

4.4 Available Scopes

UTM API (utm.yaml)

ScopePurpose
utm.strategic_coordinationCreate, update, delete, and query OIRs in the DSS. Notify subscriber USSs. Fetch OIR details from other USSs. Required for all standard flight operations.
utm.constraint_processingQuery constraint references in the DSS and fetch constraint details from DECEA's USS. Required if your area may have constraints.
utm.conformance_monitoring_saQuery OIRs and fetch telemetry for off-nominal situations. Used by DECEA's monitoring systems.
utm.constraint_managementCreate, update, and delete constraints. DECEA only.
utm.availability_arbitrationSet USS availability state in the DSS. Not required in Phase 1.
utm.aviation_authorityAccess flight authorization details. DECEA only.

Remote ID API (remoteid.yaml)

ScopePurpose
rid.service_providerCreate, update, and delete ISAs in the Remote ID DSS. Required when activating/deactivating flights.
rid.display_providerQuery ISAs and telemetry from other USSs. Required for situational awareness.

Automated Testing APIs

ScopePurpose
interuss.flight_planning.direct_automated_testUsed by DECEA's test framework when calling your flights.yaml endpoints during homologation.
interuss.flight_planning.planUsed by DECEA's test framework to simulate user flight plan actions.
rid.inject_test_dataUsed by DECEA's test framework when calling your injection.yaml endpoints during homologation.
interuss.versioning.read_system_versionsUsed by DECEA's test framework when calling your versioning.yaml endpoint.

Day-to-Day Scope Requirements

For normal production operations, your USS will primarily need:

utm.strategic_coordination
utm.constraint_processing
rid.service_provider
rid.display_provider

4.5 The intended_audience Parameter — Peer-to-Peer Calls

The intended_audience parameter (which becomes the aud claim in the JWT) is critical for peer-to-peer security. It binds a token to a specific recipient, preventing token replay attacks.

Rules:

  • When calling DECEA's DSS or Auth Server: use the domain of the DSS (e.g., api.sandbox.brutm.dcta.mil.br).
  • When calling another USS (e.g., to fetch OIR details): use only the domain of that USS's uss_base_url — no path, no port (unless non-standard).

Example:

If USS B's uss_base_url in the DSS is https://uss-b.partnercompany.com/api/utm, then when USS A wants to call USS B:

intended_audience = "uss-b.partnercompany.com"

USS A requests a fresh token with this audience and includes it in the Authorization header when calling GET https://uss-b.partnercompany.com/api/utm/uss/v1/operational_intents/{id}.

USS B, upon receiving this request, validates that the token's aud claim matches its own domain (uss-b.partnercompany.com). If it doesn't match, it rejects the request with HTTP 401.


4.6 Using the Token

Include the token in every outgoing HTTP request:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

This applies to calls to:

  • DECEA's DSS (/dss/v1/...)
  • DECEA's Remote ID DSS (/dss/identification_service_areas/...)
  • Any peer USS's endpoints (/uss/v1/...)

4.7 Validating Incoming Tokens (Inbound Requests)

Your USS must validate every inbound request — whether from DECEA's systems or from other USSs. Failing to do so is a security vulnerability and a homologation failure.

The validation steps are:

Step 1 — Extract the Token

Extract the JWT from the Authorization header:
Authorization: Bearer <token>

Step 2 — Verify the RS256 Signature

Verify the token's digital signature using DECEA's public RSA key (obtained from the Portal UTM during onboarding). The signing algorithm is RS256.

If the signature is invalid → reject with HTTP 401.

Step 3 — Verify Token Expiry

Check that the exp claim is greater than the current UTC timestamp.

If the token is expired → reject with HTTP 401.

Step 4 — Verify the Audience

Check that the aud claim matches your own server's FQDN. This prevents a token intended for another USS from being replayed against your server.

If aud doesn't match your domain → reject with HTTP 401.

Step 5 — Verify the Scope

Check that the scope claim contains the scope required by the specific endpoint being called. Different endpoints require different scopes (see the OpenAPI specifications for each endpoint's required scope).

If the scope is insufficient → reject with HTTP 403.

Go implementation reference (from the BR-UTM workshop):

func verifyToken(token string, publicKeyFile string) (bool, error) {
    bytes, _ := os.ReadFile(publicKeyFile)
    publicKey, _ := jwt.ParseRSAPublicKeyFromPEM(bytes)
    parts := strings.Split(token, ".")
    err := jwt.SigningMethodRS256.Verify(
        strings.Join(parts[0:2], "."), parts[2], publicKey,
    )
    return err == nil, err
}

4.8 Token Caching Strategy

For optimal performance:

  1. Cache the token after obtaining it.
  2. Reuse it for all requests to the same audience with the same scopes, until it's within a safety margin of expiry (e.g., 60 seconds before exp).
  3. Request a new token when the cached one is near expiry or when you need a different scope/audience combination.

You may maintain multiple cached tokens simultaneously — one per (scope, audience) combination that your USS needs.


4.9 Architecture Diagram — Full Authentication Flow

                          ┌─────────────────────────────────────────────┐
                          │              DECEA Infrastructure            │
  ┌──────────────┐        │  ┌──────────────┐    ┌────────────────────┐ │
  │              │──────► │  │  Auth Server  │    │        DSS         │ │
  │   Your USS   │ token  │  │  /token       │    │  /dss/v1/...       │ │
  │              │◄─────  │  └──────────────┘    └────────────────────┘ │
  │              │        │                                              │
  │              │─────────────────── Bearer JWT ──────────────────────►│
  │              │◄──────────────────── Response ──────────────────────  │
  └──────┬───────┘        └─────────────────────────────────────────────┘
         │
         │  Peer-to-Peer (with audience-specific token)
         │
         ▼
  ┌──────────────┐
  │  Partner USS │  validates JWT: sig + exp + aud + scope
  │  /uss/v1/... │
  └──────────────┘

4.10 Security Principles

  • Principle of least privilege: Request only the scopes your operation actually needs. Avoid requesting all scopes in every token.
  • No token sharing: Tokens are bound to a specific audience (aud). A token obtained to talk to the DSS cannot be used to call another USS, and vice versa.
  • Time synchronization: Your system clock must be synchronized with DECEA's NTP server (ntp.decea.gov.br) to ensure token expiry calculations are accurate. See Chapter 7 — Non-Functional Requirements.