Summary
Yiisoft\Auth\Method\Composite::challenge() uses withHeader() for each method. When multiple authentication methods are configured, only the last WWW-Authenticate value remains.
Expected
Multiple challenges should be returned, e.g.:
WWW-Authenticate: Bearer realm="api"
WWW-Authenticate: Basic realm="api"
Actual
Only the last method's challenge survives:
WWW-Authenticate: Basic realm="api"
Reproduce
$composite = new Composite([
new HttpBearer($repository),
new HttpBasic($repository),
]);
$response = $composite->challenge($responseFactory->createResponse(401));
// count($response->getHeader('WWW-Authenticate')) === 1
// value: "Basic realm=\"api\"" (or "Authorization realm=\"api\"" on 3.2.1, see #116)
HTTP check without credentials against a route protected by this Composite:
curl -sI https://example.test/protected | grep -i www-authenticate
# WWW-Authenticate: Basic realm="api"
Cause
foreach ($this->methods as $method) {
$response = $method->challenge($response); // uses withHeader() → overwrites
}
Suggested fix
Accumulate challenges with withAddedHeader() (or equivalent), so each method can add its own WWW-Authenticate value.
Environment
Package: yiisoft/auth
Version: 3.2.1
Class: Yiisoft\Auth\Method\Composite
Summary
Yiisoft\Auth\Method\Composite::challenge()useswithHeader()for each method. When multiple authentication methods are configured, only the lastWWW-Authenticatevalue remains.Expected
Multiple challenges should be returned, e.g.:
Actual
Only the last method's challenge survives:
Suggested fix
Accumulate challenges with withAddedHeader() (or equivalent), so each method can add its own WWW-Authenticate value.
Environment
Package: yiisoft/auth
Version: 3.2.1
Class: Yiisoft\Auth\Method\Composite