baptistegh opened a new pull request, #75913: URL: https://github.com/apache/airflow/pull/75913
Command-line clients can only log in to the Keycloak auth manager with a username and password, which doesn't work for users who sign in through SSO or with a second factor. This lets them log in through Keycloak in their browser, and refresh the CLI token's short-lived Keycloak tokens. Keycloak advertises both through the CLI login discovery route from #75672. This is the provider side only. The airflowctl side (`auth login --sso`) follows in #75804, which also shows the whole flow end to end. related: #75560 ### Changes - `get_cli_login_methods()` always advertises `password` and `refresh_token`. It adds `authorization_code` with `S256` only when `[keycloak_auth_manager] cli_authorization_code_enabled` is on (default `False`). - `/auth/token/cli` gets its own body: `password` (the default, so existing clients are unaffected), `refresh_token` or `authorization_code`. `client_credentials` and `jwt-bearer` stay on `/auth/token` only. - `GET /auth/login/cli` requires a loopback `redirect_uri` (`http://127.0.0.1` or `[::1]`, any port, path `/callback`) and an `S256` challenge, then forwards both to Keycloak. Airflow enforces PKCE here rather than on the Keycloak client, because the web login doesn't use it. - **Refresh:** the new token keeps the expiry of the old one, so a refresh never extends a CLI session. Expired and revoked tokens are refused through the auth manager's own `get_user_from_token`. - Keycloak clients with "Use Refresh Tokens" turned off are handled the same way as in #75871. - Bumps `python-keycloak>=6.0.0` for PKCE support. - On Airflow versions without CLI login discovery, the new hook is never called, so no version gate is needed. ### Trying it without airflowctl With `cli_authorization_code_enabled = True` and `http://127.0.0.1/callback` in the Keycloak client's valid redirect URIs: ```bash # 1. Discover the login methods curl "${AIRFLOW_URL}/api/v2/auth/cli/metadata" # 2. Open in a browser. After login, Keycloak redirects to # http://127.0.0.1:8765/callback?code=...&state=xyz (nothing needs to listen; copy the code from the address bar) VERIFIER=$(openssl rand -base64 48 | tr -d '=+/\n' | cut -c1-64) CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=\n') echo "${AIRFLOW_URL}/auth/login/cli?redirect_uri=http://127.0.0.1:8765/callback&state=xyz&code_challenge=${CHALLENGE}&code_challenge_method=S256" # 3. Exchange the code for a CLI token curl -X POST "${AIRFLOW_URL}/auth/token/cli" -H 'Content-Type: application/json' \ -d "{\"grant_type\": \"authorization_code\", \"code\": \"<code>\", \"code_verifier\": \"${VERIFIER}\", \"redirect_uri\": \"http://127.0.0.1:8765/callback\"}" # 4. Refresh it curl -X POST "${AIRFLOW_URL}/auth/token/cli" -H 'Content-Type: application/json' \ -d '{"grant_type": "refresh_token", "token": "<CLI token>"}' ``` --- ##### Was generative AI tooling used to co-author this PR? - [X] Yes (please specify the tool below) Generated-by: Claude Code (Opus 5.5) following [the guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions) -- 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]
