How Airflow 3 REST API authentication with JWT tokens works
A team that needs CI jobs, cron scripts or internal services to call the Airflow 3 REST API usually cannot wait for a person to log in through the UI. The active auth manager issues the token that makes those calls possible. Each auth manager provides a token endpoint, usually POST /auth/token, which accepts credentials and returns a JWT. The Airflow UI receives its own token in an httponly cookie named _token, so browser sessions and scripted calls rely on the same auth manager, but a script does not get that cookie and has to send the token itself as a bearer credential.
The same JWT machinery also authenticates the internal Task Execution API, which tasks use to report state and fetch what they need while running. Those execution tokens are separate from the tokens your scripts obtain, and the security model describes their lifetime and limits. For your purposes, the practical point is that the auth manager is a central control: whatever it issues and validates governs both people and automation. Before you design any service account, confirm with the auth manager documentation which endpoints your chosen auth manager exposes and how it handles refresh.
Airflow 3 uses the Simple auth manager by default, and only one auth manager can be active at a time, set by the auth_manager option. That default is useful for trying Airflow but is not a basis for production access, so plan the auth manager choice before automation depends on it. Changing the active auth manager later changes how tokens are issued and validated for every script and service at once, so inventory which integrations call the API now and test them against the target auth manager in a non-production environment.
Cookie versus bearer credentials: which one each caller should use
People who use the Airflow UI do not handle tokens themselves. After sign-in, the auth manager issues a token that the UI stores in an httponly cookie named _token, and the browser sends it with each request. This cookie exists for the UI session, so it should not be copied into scripts or pipelines.
- Credential: the
_tokensession cookie set by the auth manager at sign-in. - How it is obtained: the user signs in through the UI, so no manual call to the token endpoint is needed.
- Refresh: the UI refreshes expired tokens where the auth manager supports the refresh_user method. Confirm support for your auth manager before relying on long sessions.
- What breaks: a user who runs a script with a stale or invalid bearer header sees that script fail, even though the UI still works. From 3.3.2, an explicit bearer credential takes precedence over the cookie, so the invalid header decides the outcome.
- Expired sessions: when the cookie can no longer be refreshed, the user must sign in again, and any automation that borrowed the cookie stops without a clear message.
Check that a test user can sign in, reach the API from the browser, and keep a working session while a script in the same environment sends its own bearer token.
Scripts and CI jobs should send an explicit bearer token in the Authorization header. The job requests the token from the auth manager's token endpoint, usually POST /auth/token, using credentials stored in the CI secret store, and then calls the REST API with that token. Browser cookies should never be the source of automation credentials.
- Credential: an access token sent as
Authorization: Bearer <token>on every request. - How it is obtained: a POST to the token endpoint with the credentials your auth manager expects. Confirm the request body and field names in the auth manager documentation for your version.
- Lifetime: request a token at the start of each run, so no long-lived token is stored in job definitions or logs.
- What breaks: a job with an expired or mistyped bearer header receives a 401 or 403, even when a valid cookie is present in the same session, because explicit credentials are checked first in 3.3.2.
- Failure handling: make the job stop and report the status code, so a credential problem does not appear as a silent partial run.
In staging, confirm the token request, the API call and the failure path on the exact Airflow patch version you run in production.
Long-running services, such as monitoring integrations, internal controllers and data platform connectors, should authenticate as a dedicated service account. A named account keeps the service's identity stable through staff changes and lets you scope its roles to the calls it actually makes. The service holds a bearer token, refreshes it before expiry, and re-authenticates when a refresh fails.
- Identity: a dedicated account in the auth manager with only the roles the service needs. Ask your auth manager's documentation how service accounts are created and whether they can sign in without a person.
- Credential: a bearer token sent explicitly on every request, never a cookie copied from a browser session.
- Refresh: use the refresh_user path where the auth manager supports it, and fall back to a fresh sign-in when refresh fails.
- Separate token types: execution tokens for the internal Task Execution API default to a 10-minute lifetime with automatic refresh and cannot be revoked. They are not the credentials this service uses, so do not share them with it.
- Expiry handling: confirm the token lifetime configured for your public API tokens, because a service that expects a longer lifetime than the one configured will fail at an unexpected moment.
In a test environment, force a token to expire and confirm that the service re-authenticates and that a persistent 401 or 403 raises an alert for an operator.
Authentication options and when each fits
This table compares the credential and identity options for calling the Airflow 3 REST API and the UI, from the auth manager in use to user tokens, service accounts and the browser cookie. Read each row for when it fits, what it requires and what to confirm before you build on it. The main takeaway is that the auth manager sets which identities exist, so choose it before you design scripts and service accounts around it.
| Option | When it fits | What it requires and what to confirm |
|---|---|---|
| Simple auth manager (default) | Local testing and proof-of-concept work only, not a production identity design | Ships as the default in Airflow 3 with fixed roles and generated passwords. Confirm its limits against the auth manager documentation before any shared or regulated use. |
| FAB auth manager | Teams that want Airflow to manage its own users and roles through the FAB provider | Installed from the FAB provider as the single auth manager set by the auth_manager option. Confirm which token endpoint and role model your provider version exposes. |
| Keycloak auth manager | Organizations that already run Keycloak and want users and roles governed centrally | Requires the Keycloak auth manager package and an existing realm with a client configured for Airflow. Confirm with the Keycloak and Airflow provider docs how roles and tokens map. |
| AWS auth manager | Airflow deployments inside AWS that authorize users through AWS identities | Requires the AWS auth manager package and AWS identity configuration. Confirm how it issues tokens and how service principals are represented in your account setup. |
| User token from the token endpoint | Interactive users or personal scripts that call the public REST API with a bearer header | Each auth manager provides a token endpoint, usually POST /auth/token. Confirm the request body the endpoint expects and the token lifetime in your version. |
| Service account bound to a role | Automated jobs, CI pipelines and integrations that need a non-person identity with narrow permissions | Needs a dedicated account in the auth manager with a role limited to the endpoints the job calls. Confirm whether your auth manager supports non-human accounts and how their credentials are rotated. |
| Browser session cookie (_token) | The Airflow UI only, where the httponly cookie is set after sign-in | Not suitable for scripts or services. The cookie is refreshed through refresh_user where the auth manager supports it. Confirm refresh behavior for your chosen manager. |
| Explicit bearer credential with cookie present (3.3.2 and later) | Clients that send both a browser session and a script header, such as a UI-embedded tool calling the API | From Airflow 3.3.2, an explicit bearer credential takes precedence over the cookie, and invalid explicit credentials return 401 or 403. Test this behavior on your version before you rely on it. |
Setting up token authentication for scripts and services
This sequence takes a script or service from no access to a verified bearer token that reads the Airflow 3 REST API under a dedicated identity. Each step ends with a check that shows whether the token works, fails safely and refreshes as expected.
Confirm the Airflow version and auth manager
The platform engineer checks the running Airflow version and reads the auth_manager setting in the deployed configuration, whether in airflow.cfg, an environment variable or the Helm values. Airflow 3 uses the Simple auth manager by default and allows only one auth manager at a time, so the token endpoint and role model depend on which one is active. Confirm the version against the 3.3.2 patch release if your team is planning around its precedence change. The step is done when you can name the version and the single active auth manager in writing, with the configuration source recorded.
Create a dedicated service identity
An administrator creates a separate user for the script or service instead of reusing a personal account or an existing admin. Assign the narrowest role that covers the calls the client makes, for example read-only access to DAG and run information if that is all it needs. The Simple auth manager uses fixed roles and generated passwords, so a production identity usually requires the auth manager you chose for go-live. The step is done when the identity exists, holds only the intended role, and the role assignment is recorded in your access review system.
Request a token from the token endpoint
The client sends its credentials to the auth manager's token endpoint, usually POST /auth/token, and receives a JWT in the response. Store the returned token in a secrets store or environment variable that the client reads at runtime, never in DAG code or a repository. Confirm the response contains a token and note the expiry time it reports. Then run one read-only call against the REST API, such as listing DAGs, with the token. The step is done when that read-only call returns a success status and the token is absent from logs.
Add the bearer header to the client
Update the script or service so every request sends the token in an Authorization header with the Bearer scheme. Keep the client's credential handling in one place so that a rotated identity or new token requires a change in a single location. Check that the client does not also send a session cookie from another tool unless you intend it to. Run the same read-only call through the client rather than through a manual request. The step is done when the client's call succeeds using only the bearer header and the request log shows the expected identity.
Test invalid and expired tokens
Send requests with a malformed token, a token from a different identity, and an expired token. The API should reject each one with 401 or 403, and it should not fall back to any other credential the client might carry. In Airflow 3.3.2, an invalid explicit bearer credential fails with 401 or 403 even when a valid session cookie is present, so include that case if your tooling uses a browser session on the same host. The step is done when every negative case returns 401 or 403 and the failures appear in the audit log under the expected identity.
Confirm the refresh path
Let a token expire under normal use and confirm how the client obtains a new one. Where the auth manager supports it, the refresh_user method renews expired tokens, so verify that your client either requests a new token from the endpoint or relies on the refresh behavior your auth manager documents. Confirm which refresh method your auth manager supports before depending on it. Do not treat refresh as a way to extend access, because a refreshed token still carries the same role. The step is done when a long-running client keeps working across an expiry boundary and the refreshed token carries the same identity and role.
Record the configuration and review access
The platform team writes down the auth manager, version, service identity, role, token storage location and rotation owner in the team runbook. Ask your security or compliance lead to confirm the identity is listed in the access review and that its audit log entries are retained. Schedule a review of the service identity's role whenever the client's calls change. The step is done when the runbook entry exists, the access review lists the identity, and someone other than the author has checked the entry.
How token refresh and expiry affect long-running scripts
A token is not a session, so any script that runs for hours must plan for its expiry. Each auth manager issues tokens through its token endpoint, and where the auth manager supports it, an expired token is renewed through the auth manager's refresh_user method. Your script should not assume that renewal happens on its own. Wrap every call so that a 401 response triggers one controlled request for a new token, then a retry of the failed call. Log the re-authentication, and stop the job if the retry also fails, since repeated failures usually mean the credential itself is wrong, disabled or out of scope.
Keep user and service tokens separate from the execution tokens that Airflow issues to workers. The execution tokens used by the Task Execution API default to a 10-minute lifetime with automatic refresh, cannot be revoked, and carry no per-DAG authorization. Your scripts do not hold those tokens and should not try to reuse them. Scripts that call the public REST API use credentials you issue deliberately, so you control their lifetime, rotation and revocation through your auth manager and identity provider. Treat a long-lived service credential as a higher-value secret than an execution token, and store it in a secrets manager rather than in a DAG or a shell history.
Confirm the refresh behavior of your chosen auth manager before you write retry logic. Refresh support, token lifetimes, and whether a disabled user loses access immediately depend on the auth manager you select and its configuration. Test an expired token, a revoked user and a deliberately invalid credential in a non-production environment, and record what the API returns in each case. Ask your identity provider team how quickly account disablement takes effect for service accounts, because that timing sets the real exposure window for a leaked token.
Security considerations for JWT-based API access
A bearer token grants whatever the account behind it can do, so the risks sit mostly in where tokens and signing keys live, how long they remain usable, and whose identity they carry. The cards below cover the decisions that connect those risks to your Airflow 3 deployment.
Keep signing keys in secrets management
Signing keys and long-lived credentials used to obtain tokens should live in a secrets manager your platform team controls, not in shell history, cron scripts or repository files. Anyone holding the key or a valid token can call the API as that identity. Check who can read the secret store, how access is logged, and whether rotation is tested before you need it.
Treat tokens as replayable credentials
A bearer token works from any host that presents it until it expires, so a token copied from a CI log or a laptop is as useful to an attacker as the password it came from. Keep token lifetimes short, avoid writing tokens to logs or files, and make sure a leaked token is handled as an incident that ends with the credential being rotated.
Plan around non-revocable execution tokens
Execution tokens used by workers through the Task Execution API default to a 10-minute lifetime, refresh automatically, and cannot be revoked. Compensating controls are short lifetimes, network policies that limit where workers can reach the API server, and restricting who can run or edit tasks. Confirm these behaviors against the security model for your exact release.
Separate service accounts per integration
Give each script, CI pipeline or external service its own Airflow user with the narrowest role that covers its calls, instead of sharing an admin account. When one integration is compromised or retired, you can disable its account without disrupting others. Review which roles each account holds after every upgrade, because role names and permissions can change between releases.
Log API calls to the audit trail
Airflow records UI, API and CLI activity in its audit log, so API calls made with service tokens should appear there under the account that made them. Confirm which events are captured in your version, who can read the log, and how long it is retained before database cleanup removes it. Shipping these records to a central log system is a separate design decision.
Terminate TLS on the API server
Bearer tokens travel in every request header, so the API server endpoint should be reachable only over TLS, with certificates managed by your platform team and clients configured to verify them. Plaintext access on an internal network still exposes tokens to anyone who can observe that network. Check the TLS termination point, whether a reverse proxy or ingress sits in front, and how certificate renewal is handled.
Questions teams ask about Airflow API authentication
Can our own team set up JWT authentication for the Airflow 3 REST API in-house?
Yes, most teams with Airflow operations experience can do it in-house, provided they already run Airflow 3 and understand their identity setup. The work needs someone comfortable with the chosen auth manager's token endpoint, HTTP clients and scripting, plus someone who can manage identity provider settings and secrets storage. The main skill gap is usually secure handling of service credentials across scripts, CI jobs and external services, not the token calls themselves. A partner adds value when the auth manager is still undecided or when the design must be documented for an audit.
How long does a typical JWT authentication setup take?
Duration depends on the auth manager you run, how many scripts and services must authenticate, and how your identity provider and secrets handling are already set up. A team that has only the built-in Simple auth manager in a test environment faces a different task from one that must wire in a production identity provider, service accounts and token refresh in several pipelines. Ask any partner for a timeline that lists each auth manager decision, each client to migrate and each verification step, and check that it matches your environment.
What makes the effort for API authentication go up or down?
The biggest drivers are the number of clients, the diversity of their credential types, and the amount of existing automation that uses cookies or shared logins. Effort also rises when the auth manager needs a custom role mapping, when tokens must be issued to non-human service accounts with separate permissions, or when logs must show who called the API. Work goes down when clients are few, when they share one documented pattern, and when a secrets backend already stores their credentials. Ask for the effort estimate to be split by client type so you can see which items drive the cost.
Is Apache Airflow itself a paid product?
No. Apache Airflow is an Apache Software Foundation project released under the Apache License 2.0 (SPDX identifier Apache-2.0), and the project itself offers no paid edition. Your costs come from the infrastructure you run it on, the people who operate it, and any external services you choose to connect. Any paid cost for authentication work is the professional service scope, not a license fee for Airflow. Check the license of any additional provider package or identity product you add, since those carry their own terms.
What does our team need to provide before authentication work starts?
You need to provide the target Airflow 3 version and deployment, a decision on the auth manager, access to your identity provider or its administrators, and an inventory of every script, CI job and service that calls the REST API today. You also need to name the secrets store where service credentials will live and the owners who approve roles. Early access to a non-production environment lets the design be tested before cutover. Missing inventory is the most common reason the scope grows during the engagement.
Can we revoke an Airflow API token once it has been issued?
It depends on the token type, so confirm this for your version before you rely on revocation. Airflow's security model states that execution tokens used by the internal Task Execution API cannot be revoked, default to a 10-minute lifetime and refresh automatically. For tokens used against the public REST API, check how your chosen auth manager handles expiry, refresh and invalidation, and document the fallback, such as rotating the service account credential or disabling the account. Plan that fallback as part of the incident response design, not as an afterthought.
Why do some API calls fail when a browser session cookie is also present?
In Airflow 3.3.2, an explicit bearer credential takes precedence over the session cookie, so a request that sends an invalid bearer token fails with 401 or 403 even if a valid cookie is present. Scripts that relied on the cookie being used silently in earlier releases can break after an upgrade. Review every client that sends both headers and cookies, and test invalid and expired credentials against a staging environment before upgrading production. Use the release notes to confirm the exact behavior for your target version.
How DeployOpen scopes and delivers API authentication work
DeployOpen plans and implements self-hosted Airflow inside your own infrastructure, including the REST API authentication design covered above. The authentication design is written down as part of the agreed scope before any work starts. That scope names the auth manager you will run, the token issuance path for each caller, which services and scripts get their own service accounts, how long tokens live and how they are refreshed, which explicit bearer credentials are permitted, and how invalid credentials are logged and alerted on. It also records the Airflow version you are targeting, so the design accounts for the 3.3.2 precedence change if your rollout lands on or after that release. Because scope and deliverables are agreed in writing, the quote that follows reflects the specific callers, identity provider integration and verification work you actually need rather than a generic template.
Delivery covers configuration of the chosen auth manager, the token and service account setup, test scripts that confirm each caller authenticates with the intended credential, and documentation for your operators. Ongoing support and upgrade work, and continuous security testing of the API surface, can be added as retainers after go-live. DeployOpen prepares the controls, configuration and evidence that your assessors will ask for, but it does not issue audit reports, attestations or certifications. Independent auditors and certification bodies perform those assessments. Ask your DeployOpen contact to confirm in writing which items are delivered as evidence and which are left for your auditor to review.

