@@ -348,15 +348,17 @@ The ``JWTBearer`` security dependency validates the token once per request:
3483482. Performs cryptographic signature validation via ``JWTValidator ``.
3493493. Verifies standard claims (``exp ``, ``iat ``, ``aud `` — ``nbf `` and ``iss `` if configured).
3503504. Defaults the ``scope `` claim to ``"execution" `` if absent.
351- 5. **Validates the task identity claims against a typed Pydantic schema. ** ``TIClaims ``
352- (in ``airflow.api_fastapi.execution_api.datamodels.token ``) enforces that ``scope `` is one
353- of the declared ``TokenScope `` literals (``"execution" `` or ``"workload" ``); ``TIToken ``
354- then parses the ``sub `` claim through a ``UUID `` field, which rejects non-UUID values.
355- A token whose ``scope `` is unknown, or whose ``sub `` is not a valid UUID, is rejected with
356- ``403 Forbidden `` even when the cryptographic signature checks pass. ``TIClaims `` keeps
357- ``extra="allow" `` so auth managers can attach additional, deployment-specific claims
358- without modifying the core schema; only the security-critical fields are typed.
359- 6. Creates a ``TIToken `` object with the task instance ID and validated claims.
351+ 5. **Validates the identity and its scope-specific claims against typed Pydantic schemas. **
352+ ``ExecutionToken `` (in ``airflow.api_fastapi.execution_api.datamodels.token ``) parses ``sub ``
353+ as a UUID. Its claims form a discriminated union selected by ``scope ``: ``TIClaims `` for
354+ ``"execution" ``, ``"workload" ``, and ``"callback" ``; ``DagProcessorSessionClaims `` for
355+ provisioning; ``DagProcessorClaims `` for a registered Job; and ``DagParseClaims `` for a
356+ parsing attempt. Each processor claim type requires expiry and its scope-specific grants
357+ and identity fields. Unknown scopes, invalid subjects, or missing required claims return
358+ ``403 Forbidden `` even when cryptographic validation succeeds. All claim types allow extra
359+ fields so auth managers can attach deployment-specific claims.
360+ 6. Constructs the corresponding token object: ``TIToken ``, ``DagProcessorSessionToken ``,
361+ ``DagProcessorToken ``, or an ``ExecutionToken `` carrying ``DagParseClaims ``.
3603627. Caches the validated token on the ASGI request scope for the duration of the request.
361363
362364Route-level enforcement is handled by ``require_auth ``:
@@ -367,26 +369,32 @@ Route-level enforcement is handled by ``require_auth``:
367369 ``{task_instance_id} `` path parameter, preventing a worker from accessing another task's
368370 endpoints.
369371
372+ The task-only, processor-session, and processor-Job dependencies additionally reject tokens of
373+ the wrong principal type. Endpoints shared by tasks and parsing attempts use the general
374+ ``CurrentExecutionToken `` dependency with their declared route scopes.
375+
370376.. mermaid ::
371377
372378 flowchart TD
373379 REQ([Incoming request<br/>Authorization: Bearer ...])
374380 REQ --> CACHE{Cached on<br/>request.scope?}
375- CACHE -->|yes| RET([Return cached TIToken ])
381+ CACHE -->|yes| RET([Return cached token ])
376382 CACHE -->|no| SIG[JWTValidator:<br/>verify signature]
377383 SIG -->|fail| F1([403 Forbidden])
378384 SIG -->|ok| STD[Verify exp / iat / nbf<br/>aud / iss]
379385 STD -->|fail| F1
380386 STD -->|ok| SCOPE[Default scope to<br/>'execution' if absent]
381- SCOPE --> SCHEMA[TIClaims :<br/>typed Pydantic schema ]
387+ SCOPE --> SCHEMA[ExecutionToken :<br/>UUID identity and<br/>scope-discriminated claims ]
382388 SCHEMA -->|ValidationError| F1
383389 SCHEMA -->|ok| TYP{require_auth:<br/>scope in<br/>route.allowed_token_types?}
384390 TYP -->|no| F1
385391 TYP -->|yes| SELF{ti:self scope<br/>declared?}
386- SELF -->|no| OK([Return TIToken])
392+ SELF -->|no| PRINCIPAL{Typed dependency:<br/>principal type matches?}
387393 SELF -->|yes| MATCH{token.sub ==<br/>task_instance_id?}
388394 MATCH -->|no| F1
389- MATCH -->|yes| OK
395+ MATCH -->|yes| PRINCIPAL
396+ PRINCIPAL -->|no| F1
397+ PRINCIPAL -->|yes or general dependency| OK([Return validated token])
390398
391399 classDef fail fill:#ffcdd2,stroke:#c62828,stroke-width:2px,color:#000
392400 classDef pass fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
@@ -489,9 +497,10 @@ guidance, and the planned strategic and tactical improvements.
489497Dag processor HTTP client credentials
490498-------------------------------------
491499
492- The core ``DagProcessorAPIClient `` supports authenticated access to the Execution API
493- without holding its signing key. This is the client and authentication foundation;
494- ``airflow dag-processor `` still uses its existing database-backed lifecycle.
500+ The core ``DagProcessorAPIClient `` lets processor integrations authenticate to the Execution
501+ API without holding its signing key. The standard ``airflow dag-processor `` command does
502+ not yet use this client. Provisioning a token file alone does not switch that command to
503+ HTTP or remove its need for database access.
495504
496505On a trusted host with the API signing key, provision a session token for the bundles
497506the client may access::
@@ -503,17 +512,24 @@ The command writes the token atomically with owner-only permissions. Keep the pr
503512running and mount its directory rather than a single file so token replacement stays
504513visible. Each processor process needs its own session.
505514
506- The ``dag_processor_session `` token registers a Job through ``POST /jobs ``. The returned
507- ``dag_processor `` token can heartbeat and complete that Job, read Connections and Variables
508- for a granted bundle, and exchange a parsing credential through
509- ``POST /jobs/{job_id}/parse-token ``. Registration retries keep the same registration UUID.
510- A new process uses a new UUID; it cannot replace a session's Job while that Job is alive.
511- Ending or replacing the Job invalidates its runtime credentials.
515+ The three credentials have different issuers and permissions:
516+
517+ - ``dag_processor_session `` is issued by trusted provisioning. It can only register a
518+ Job or renew that Job's credential through ``POST /jobs ``.
519+ - ``dag_processor `` is returned by Job registration. It can heartbeat and complete that
520+ Job, read Connections and Variables for a granted bundle, and exchange a parsing
521+ credential through ``POST /jobs/{job_id}/parse-token ``. It cannot outlive the session
522+ token used to obtain it.
523+ - ``dag_parse `` is returned by the parsing-token exchange for one attempt, bundle, and
524+ relative file location. It permits parse-time requests, including callback-context reads,
525+ but cannot manage Jobs or exchange tokens. It cannot outlive its parent Job credential.
526+
527+ Registration retries keep the same registration UUID. A new process uses a new UUID;
528+ it cannot replace a session's Job while that Job is alive. Ending or replacing the Job
529+ invalidates its runtime credentials.
512530
513531The client selects the bundle with ``use_bundle `` and a parsing attempt with ``use_parse ``.
514- A ``dag_parse `` token binds the attempt UUID, bundle, and relative file location to the Job.
515- It permits parse-time requests for that bundle, including callback-context reads, but cannot
516- manage Jobs or exchange tokens. A request header cannot override the signed bundle.
532+ A request header cannot override the parsing token's signed bundle.
517533Connection and Variable access uses the bundle's current team.
518534
519535The client attempts renewal at 80% of token lifetime. Transient early-renewal failures leave
0 commit comments