Decide how the auth plugin contract expresses redirects and other response-producing outcomes
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
Decide how the authentication plugin contract expresses an outcome that has to produce a response — a redirect above all, and the challenge shape next to it. The contract as it stands cannot express either, and the way an integration would reach for instinctively fails silently.
### What the code does today
- **The new contract has no response-returning path.** All three methods answer with lookup data or nothing: `generate_lookup_data() -> UserLookupData | None`, and both callbacks return `None`.
- **Existing webapp plugins emit redirects by returning them.** All 13 redirect sites across the in-tree and out-of-tree webapp plugins are `return web.HTTPFound(...)`; none raise. This works because aiohttp's `HTTPException` is also a `Response` (`HTTPFound → HTTPMove → HTTPRedirection → HTTPException → Response`), so a returned redirect never reaches an exception handler.
- **Raising one is swallowed.** The REST exception middleware catches `web.HTTPException`, special-cases 404 and 405, and turns everything else into `GenericBadRequest`. A raised 3xx therefore becomes a 400 and the `Location` header is lost. Verified by driving the middleware directly.
- **Challenges take the other shape.** The two-factor flow returns a `web.StreamResponse` from the existing `POST_AUTHORIZE` hook; the service carries it out as the action result. That path is out of scope for the epic but is the same underlying question.
So an integration author with no place to return a response may reach for `raise`, and get a 400 with no diagnostic. The gap is in the contract, not in the middleware — the middleware's behaviour is correct for every caller that exists today.
### Options to evaluate
1. **Leave it out and say so.** Document that the identity contract cannot produce a response, and that redirects belong to the webapp surface. Cheapest; leaves integrations that want a redirect mid-authorize with nowhere to go.
1. **A framework-neutral outcome type.** The plugin answers with an outcome — resolved identity, redirect, challenge, decline — and the manager renders it. Covers the two-factor case too, and keeps aiohttp out of the plugin contract.
1. **Let the middleware pass 3xx through.** Smallest diff, but it changes behaviour for every REST route, not just this one, and nothing raises a 3xx today.
### Done when
- The decision is recorded on the epic, with the reasoning.
- The abstract plugin's docstrings and the epic's contract wording state what a plugin may and may not answer with.
- If an outcome type is chosen, its shape is specified for a follow-up issue to implement.
JIRA Issue: BA-7506
Contributor guide
Research direction
Start by reading the abstract authentication plugin contract and its docstrings, then inspect the REST exception middleware and the existing POST_AUTHORIZE hook. Compare the documented redirect and challenge behavior with the listed webapp plugin redirect sites. Done means recording a contract decision, updating the contract wording and docstrings, and specifying the shape of any follow-up outcome type.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authentication, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100