potiuk opened a new pull request, #72647:
URL: https://github.com/apache/airflow/pull/72647

   > **Draft — opening this to settle one product question before finishing it.
   > See "Question for maintainers" below.**
   
   The AWS auth manager's SAML login flow does not bind the authentication
   response to the browser that started it.
   
   `login()` discards the AuthnRequest id that `saml_auth.login()` generates, 
and
   `login_callback()` calls `process_response()` with no `request_id`. 
python3-saml
   only validates `InResponseTo` when it is given that id, so the check is 
skipped
   and any assertion the IdP has signed is accepted.
   
   A signed assertion authenticates *the identity in the response*; it does not
   establish *which browser asked*. An attacker can therefore complete a login 
in a
   victim's browser using their own assertion, silently logging the victim into 
the
   attacker's account — any work the victim then does lands in a session the
   attacker controls. `RelayState` only selects the return mode and arrives in 
the
   same form, so the response could choose that too.
   
   ### The change
   
   Remember the AuthnRequest id and the return mode when the flow starts, in a
   short-lived cookie (`HttpOnly`, `SameSite=Lax`, `Secure` behind TLS, 10 
minutes).
   At the callback, require `InResponseTo` to match it and `RelayState` to be 
the
   one the browser asked for. The state is cleared once consumed — on both the
   redirect and the token paths — so a request id cannot be reused for a second
   response.
   
   ## Question for maintainers
   
   **Is IdP-initiated SSO a supported way to reach Airflow with this auth 
manager?**
   
   This is the reason the PR is a draft. Binding the response to an SP-initiated
   request is what distinguishes a genuine login from a replayed assertion — 
but it
   means a SAML POST that did not start at this browser's `/login` is refused. 
That
   includes clicking the Airflow tile in the AWS Identity Center access portal,
   which is a normal way to use it.
   
   There is no version of this fix that keeps unsolicited assertions working 
*and*
   closes the issue: accepting an assertion nobody asked for is the defect. So 
the
   options are:
   
   1. **Accept the trade** — IdP-initiated SSO stops working, documented as a
      deliberate breaking change with a newsfragment. This PR as it stands.
   2. **Keep it working behind an opt-in** — a config flag that permits 
unsolicited
      assertions, defaulting to off, for deployments that need the access-portal
      flow and accept the risk.
   
   I did not want to decide that unilaterally.
   
   Two further points, if option 1 or 2 is chosen, that I would fold in before
   marking this ready:
   
   * **State should move server-side, keyed by an opaque nonce.** The cookie is
     currently the state authority. Signing it would *not* close the injection 
path
     — an attacker who can write cookies for this origin can start a real login 
and
     plant genuinely-signed state — but server-side state does, and it also 
fixes
     concurrent logins in two tabs, where the single cookie is currently 
overwritten
     by the most recent AuthnRequest.
   * **Tests for tampering and concurrent flows** are not here yet, pending the
     design decision above.
   
   ### Testing note
   
   The route tests in this branch could not be executed locally —
   `providers/amazon/tests/unit/amazon/aws/auth_manager/routes/test_login.py`
   collects zero items in my environment, on unmodified `main` as well, so this 
is
   pre-existing and not caused by the change. The new login-state helpers were
   exercised directly instead. **CI is the first real run of the route tests 
here**,
   which is part of why this is a draft.
   
   The test module's import of the new constant is placed after the existing
   `pytest.importorskip`, so the lowest-dependency check keeps skipping cleanly.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes (please specify the tool below)
   
   Generated-by: Claude Code 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]

Reply via email to