Authority DPoP + mTLS Rollout Plan (Sprint 100)

Last updated: 2026-05-30 (reconciled against src/Authority implementation)

This is the rollout plan and reference for sender-constrained tokens in the Stella Ops Authority service: DPoP proof-of-possession and mutual-TLS (mTLS) binding. It is written for Authority and Security Guild engineers driving the rollout, and for operators wiring the config, telemetry, and alerts. The phase checklists below track delivery state; the Verification Matrix, Telemetry, and config tables double as the operational reference once a phase ships.

See also: authority-scopes.md, authority-threat-model.md, and the Authority module docs under docs/modules/authority/.

Objectives

  1. Enforce DPoP sender constraints (AUTH-DPOP-11-001).
  2. Bind high-assurance clients/audiences to mTLS tokens (AUTH-MTLS-11-002).
  3. Provide telemetry + runbooks so plugins (SEC2/SEC3/SEC5) can validate enforcement without regressions.

Implementation note: sender-constraint enforcement is per-client and per-audience, not per-tenant. A client opts into DPoP/mTLS via its senderConstraint property (see etc/authority.yaml), and DPoP/mTLS can additionally be forced for configured audiences (security.senderConstraints.dpop.nonce.requiredAudiences and security.senderConstraints.mtls.enforceForAudiences, defaults signer/attestor and signer).

Phase 1 · Config & Telemetry

Phase 2 · Enforcement & Fallback

Phase 3 · mTLS Binding

NOT VERIFIED IN CODE: this plan previously claimed cert-hash validation on a /fresh-auth endpoint. Authority’s MtlsValidationHandler only runs for the Token and Introspection endpoints (OpenIddictServerEndpointType.Token/Introspection in TokenValidationHandlers); there is no Authority /fresh-auth token endpoint that performs sender-certificate validation. “Fresh auth” in Authority is a Console concept (the stellaops:fresh_auth claim + a 300s window enforced by StellaOpsScopeAuthorizationHandler for obs:incident and pack-approval scopes), unrelated to mTLS binding. Drop the /fresh-auth reference or confirm a planned endpoint before re-asserting it.

Verification Matrix

ScenarioTest/CommandExpected
DPoP required, proof missingValidateDpopProof_IssuesNonceChallenge_WhenNonceMissing (in ClientCredentialsAndTokenHandlersTests)Rejected with invalid_client; WWW-Authenticate: DPoP error="use_dpop_nonce" and a DPoP-Nonce header; authority_dpop_nonce_miss_total increments.
Nonce missing/expired/invalidValidateDpopProof_RequiresSenderConstraint_WhenAudienceMatchesConfiguration + nonce-consume pathsNonce challenge reissued (nonce_missing / nonce_expired / nonce_invalid reason codes); audit event authority.dpop.proof.challenge.
mTLS cert missingValidateAccessTokenHandler_Rejects_WhenMtlsCertificateMissinginvalid_token; authority_mtls_mismatch_total{reason="missing_certificate"} increment.
mTLS cert mismatchValidateAccessTokenHandler_Rejects_WhenMtlsCertificateMismatchinvalid_token; authority_mtls_mismatch_total{reason="thumbprint_mismatch"} increment.
Bypass enabledValidateDpopProof_AllowsBypass_WhenEnabledNot rejected; no cnf; authority.dpop.proof.bypass audit event.

The --filter-style invocation above does not run with this repo’s test host; MTP ignores --filter. Run targeted cases via the test .exe runner against StellaOps.Authority.Tests rather than dotnet test --filter.

Telemetry & Alerting

Dependencies

Communication