Skip to content

feat(request): auto-inject dummy credentials for non-bearer auth schemes#180

Merged
wadakatu merged 2 commits intomainfrom
feat/auto-inject-dummy-credentials
May 8, 2026
Merged

feat(request): auto-inject dummy credentials for non-bearer auth schemes#180
wadakatu merged 2 commits intomainfrom
feat/auto-inject-dummy-credentials

Conversation

@wadakatu
Copy link
Copy Markdown
Collaborator

@wadakatu wadakatu commented May 8, 2026

Summary

Generalises auto_inject_dummy_bearer into a superset config
auto_inject_dummy_credentials that also fills dummy values for apiKey
schemes (header / cookie / query) in the validator's view. The legacy flag
stays as a bearer-only alias for v1.x consumers and is bypassed when the new
flag is on.

Why

Fixes #178.

When auto_validate_request: true is enabled in a consumer test suite, tests
that authenticate via actingAs() (or auth middleware bypass) currently
false-fail on every endpoint whose spec security uses cookie / apiKey-in-header
schemes — there is no synthetic equivalent to the bearer inject for those.
Reproduced in studio-design/studio-api PR #6617 with 250+ false-fails
across CookieAuth, JWT-style apiKey-in-header, and similar requirements.

The new flag fills the gap without touching the Symfony Request bag, so the
inject path stays consistent with existing behaviour: only the validator's
view is rewritten, and only when the test did not supply a real credential.

Verification

  • composer test passes (1285 tests, 3070 assertions)
  • composer stan passes (PHPStan level 6 over src/ + tests/)
  • composer cs-check passes

Failing-test-first workflow:

  1. Wrote injectable_credentials_for_* cases in
    SecuritySchemeIntrospectorTest — confirmed red, then implemented.
  2. Wrote ValidatesOpenApiSchemaAutoInjectCredentialsTest covering apiKey
    header / cookie / query, bearer upward-compat, AND-entry, existing-value
    pass-through, empty-string-as-absent, no-mutation guarantee, loud-fail
    on non-bool, and legacy flag interactions — confirmed red, then implemented.
  3. Existing ValidatesOpenApiSchemaAutoInjectBearerTest continues to pass
    unmodified, confirming legacy auto_inject_dummy_bearer is byte-for-byte
    preserved.

Notes for reviewers

  • SecurityValidator::classifyScheme() was promoted from private to
    public static so SecuritySchemeIntrospector::injectableCredentialsFor()
    reuses the exact classification rules. Kept @internalValidation/Request/
    is not part of the SemVer surface.
  • SecuritySchemeIntrospector::endpointAcceptsBearer() is preserved for the
    legacy auto_inject_dummy_bearer path and now delegates to
    injectableCredentialsFor() for consistency.
  • slotIsAlreadyPopulated() treats empty-string as "absent" to match
    SecurityValidator::checkApiKeySatisfied()'s missing-value definition; this
    is a marginal tightening over the legacy bearer check (which used a looser
    !== '' && !== [] test) but the existing bearer test suite does not exercise
    the divergent case, and the new behaviour is the more correct of the two.
  • AND-entry semantics are intentionally not modelled in the introspector —
    every supported scheme in the requirement is listed, and the trait writes
    all of them. Over-injection on an OR-endpoint is harmless; under-injection
    on an AND-endpoint would re-introduce the false-fail this feature exists
    to prevent.
  • Issue feature — auto-inject for non-Bearer auth schemes (cookie / apiKey-in-header) #178 also proposes scheme→value-map (case B) and
    skip_security_validation (case C). Both are deferred to follow-up issues
    to keep this PR focused on the case A default.

wadakatu added 2 commits May 8, 2026 19:32
Generalises `auto_inject_dummy_bearer` into `auto_inject_dummy_credentials`,
which fills dummy values for `apiKey` schemes (header / cookie / query) in
addition to bearer. The legacy flag stays as a bearer-only alias for v1.x
consumers and is bypassed when the new flag is on.

Tests using `actingAs()` against endpoints whose spec declares cookie / apiKey
authentication no longer false-fail under `auto_validate_request: true` — the
validator's view receives synthetic credentials while the Symfony Request bag
remains untouched, matching the existing bearer behaviour.

Refs #178
Reviewer feedback follow-up:

- Lift `in` and `name` onto the `apiKey()` factory of SchemeClassification
  so SecuritySchemeIntrospector reads the validated payload from the
  classification rather than re-validating $schemeDef. Drops the defensive
  literal-string guard that only existed to keep the array-shape return
  type provable.
- Tighten test coverage: header/query empty-string-as-absent parity,
  multi-apiKey AND end-to-end via new petstore-3.0 fixture endpoint, and
  RuntimeException swallow contract pinned for the credentials path.
- Comment cleanup: drop "byte-for-byte preserved" claim that no longer
  matches the delegated implementation, drop redundant restatements,
  abstract caller-name references that would rot on refactor, and add the
  missing notes on `security: []` opt-out and `_credentials` precedence.
@wadakatu wadakatu merged commit 14e560f into main May 8, 2026
13 checks passed
@wadakatu wadakatu deleted the feat/auto-inject-dummy-credentials branch May 8, 2026 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature — auto-inject for non-Bearer auth schemes (cookie / apiKey-in-header)

1 participant