baptistegh opened a new issue, #75560: URL: https://github.com/apache/airflow/issues/75560
### Description ## Proposal Add `airflowctl auth login --sso` for deployments that use the Keycloak auth manager. - If a browser is available, airflowctl opens it and logs in with the authorization code flow + PKCE. - If not (SSH session, container, or `--no-browser`), it falls back to the device code flow: it prints a URL and a code that you open on any other device. In both cases airflowctl gets the same Airflow token as today and stores it the same way. ```text $ airflowctl auth login --sso Opening browser to log in... Login successful! Welcome to airflowctl! $ airflowctl auth login --sso --no-browser Go to https://keycloak.example.com/realms/airflow/device and enter code: WDJB-MJHT Waiting for approval... Login successful! Welcome to airflowctl! ``` ## Why Today the only way to log in to a Keycloak-backed Airflow from airflowctl is a username and password, or a token you got some other way. That does not work when the realm uses MFA, passkeys or an external identity provider like Google or Entra ID. Many companies also don't want SSO passwords typed into a CLI. ## How it works The API server talks to Keycloak, the same way the web login already does. airflowctl only talks to Airflow, so it doesn't need to know the Keycloak URL, realm or client, and the client secret stays on the server. ### Browser login (default) 1. airflowctl creates a PKCE verifier and a `state`, and listens on `127.0.0.1` on a random port. 2. It opens the browser on `/auth/login/cli`, which redirects to Keycloak. 3. You log in on Keycloak. Keycloak redirects back to `http://127.0.0.1:<port>/callback` with a code. 4. airflowctl sends the code and the verifier to `/auth/token/cli`. The API server exchanges them with Keycloak and returns an Airflow token. [embedded content: Browser login with PKCE\] ### Device code (no browser) airflowctl only uses this when `--no-browser` is passed or when it can't open a browser: no display on Linux, `webbrowser` fails, or it runs over SSH (a browser on your laptop can't reach a port on the remote machine). 1. airflowctl calls `/auth/token/cli/device` and gets a URL and a short code. 2. You open the URL on any device and enter the code. 3. airflowctl polls `/auth/token/cli` until you approve, then gets an Airflow token. ## What changes Keycloak provider: - `GET /auth/login/cli` to start the browser login. It only accepts `127.0.0.1` or `[::1]` callback URLs. - `POST /auth/token/cli/device` to start the device login. - Two new grant types on `/auth/token/cli`: `authorization_code` (with `code_verifier`) and `device_code`. `password` stays the default, so current airflowctl versions keep working. - One config option per flow, both off by default. airflowctl: - `--sso`, `--no-browser` and `--timeout` on `auth login` and `auth token`. - A clear error when the server returns 404 (older provider or another auth manager). Nothing changes in `airflow-core`. I'd split it into two PRs: the provider first, then airflowctl. ## Security - PKCE is required (S256 only). `/auth/token/cli` is public and holds the client secret, so without PKCE anyone who grabbed a code could use it. - Only loopback callback URLs are accepted, checked on the redirect and again on the token exchange. - airflowctl checks `state` and stops listening after the first valid callback or the timeout. - The device code flow can be abused for phishing (someone sends you a code to approve). That's one reason it's only the fallback and off by default. - The Airflow token has the same type and lifetime (`jwt_cli_expiration_time`) as with password login, so the security model doesn't change. ## Open questions - Should this become a generic contract that other auth managers can implement later, or stay Keycloak-only for now? - Should `airflowctl auth login` with no arguments use SSO by default when the server supports it? ### Use case/motivation _No response_ ### Related issues _No response_ ### Are you willing to submit a PR? - [x] Yes I am willing to submit a PR! ### Code of Conduct - [x] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
