Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Yii Auth Change Log

## 3.3.2 under development
## 4.0.0 under development

- no changes in this release.
- Enh #122: Remove AuthenticationMethodInterface and challenge() methods in classes that not implement AuthenticatorWithChallengeInterface (@klsoft-web)

## 3.3.1 August 11, 2026

Expand Down
6 changes: 3 additions & 3 deletions config/params.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

declare(strict_types=1);

use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\Debug\AuthenticationMethodInterfaceProxy;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\Debug\AuthenticatorWithChallengeInterfaceProxy;
use Yiisoft\Auth\Debug\IdentityCollector;

return [
Expand All @@ -12,7 +12,7 @@
IdentityCollector::class,
],
'trackedServices' => [
AuthenticationMethodInterface::class => [AuthenticationMethodInterfaceProxy::class, IdentityCollector::class],
AuthenticatorWithChallengeInterface::class => [AuthenticatorWithChallengeInterfaceProxy::class, IdentityCollector::class],
],
],
];
11 changes: 0 additions & 11 deletions src/AuthenticationMethodInterface.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\IdentityInterface;

/**
* @psalm-suppress DeprecatedInterface
*/
final class AuthenticationMethodInterfaceProxy implements AuthenticationMethodInterface
final class AuthenticatorWithChallengeInterfaceProxy implements AuthenticatorWithChallengeInterface
{
public function __construct(private readonly AuthenticationMethodInterface $decorated, private readonly IdentityCollector $collector) {}
public function __construct(private readonly AuthenticatorWithChallengeInterface $decorated, private readonly IdentityCollector $collector) {}

public function authenticate(ServerRequestInterface $request): ?IdentityInterface
{
Expand Down
5 changes: 1 addition & 4 deletions src/Method/Composite.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\IdentityInterface;
use RuntimeException;

/**
* Composite allows multiple authentication methods at the same time.
*
* @psalm-suppress DeprecatedInterface
*/
final class Composite implements AuthenticationMethodInterface, AuthenticatorWithChallengeInterface
final class Composite implements AuthenticatorWithChallengeInterface
{
/**
* @param AuthenticatorInterface[] $methods
Expand All @@ -30,7 +27,7 @@
{
foreach ($this->methods as $method) {
if (!$method instanceof AuthenticatorInterface) {
throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.');

Check warning on line 30 in src/Method/Composite.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": @@ @@ { foreach ($this->methods as $method) { if (!$method instanceof AuthenticatorInterface) { - throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.'); + throw new RuntimeException('Authentication method must be an instance of ' . '.' . AuthenticatorInterface::class); } $identity = $method->authenticate($request);

Check warning on line 30 in src/Method/Composite.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": @@ @@ { foreach ($this->methods as $method) { if (!$method instanceof AuthenticatorInterface) { - throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.'); + throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class); } $identity = $method->authenticate($request);

Check warning on line 30 in src/Method/Composite.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": @@ @@ { foreach ($this->methods as $method) { if (!$method instanceof AuthenticatorInterface) { - throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.'); + throw new RuntimeException('Authentication method must be an instance of ' . '.'); } $identity = $method->authenticate($request);

Check warning on line 30 in src/Method/Composite.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": @@ @@ { foreach ($this->methods as $method) { if (!$method instanceof AuthenticatorInterface) { - throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.'); + throw new RuntimeException(AuthenticatorInterface::class . '.'); } $identity = $method->authenticate($request);

Check warning on line 30 in src/Method/Composite.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": @@ @@ { foreach ($this->methods as $method) { if (!$method instanceof AuthenticatorInterface) { - throw new RuntimeException('Authentication method must be an instance of ' . AuthenticatorInterface::class . '.'); + throw new RuntimeException(AuthenticatorInterface::class . 'Authentication method must be an instance of ' . '.'); } $identity = $method->authenticate($request);
}

$identity = $method->authenticate($request);
Expand Down
5 changes: 1 addition & 4 deletions src/Method/HttpBasic.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\IdentityInterface;
use Yiisoft\Auth\IdentityWithTokenRepositoryInterface;
Expand All @@ -29,11 +28,9 @@
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
* ```
*
* @psalm-suppress DeprecatedInterface
*
* @psalm-type TAuthenticationCallback = callable(?string, ?string, IdentityWithTokenRepositoryInterface): (?IdentityInterface)
*/
final class HttpBasic implements AuthenticationMethodInterface, AuthenticatorWithChallengeInterface
final class HttpBasic implements AuthenticatorWithChallengeInterface
{
private string $realm = 'api';
private ?string $tokenType = null;
Expand Down Expand Up @@ -184,7 +181,7 @@
{
return array_map(
static fn($value) => $value === '' ? null : $value,
explode(':', base64_decode(substr($authToken, 6)), 2),

Check warning on line 184 in src/Method/HttpBasic.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": @@ @@ { return array_map( static fn($value) => $value === '' ? null : $value, - explode(':', base64_decode(substr($authToken, 6)), 2), + explode(':', base64_decode(substr($authToken, 5)), 2), ); }
);
}

Expand Down
14 changes: 1 addition & 13 deletions src/Method/HttpCookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\IdentityInterface;
use Yiisoft\Auth\IdentityWithTokenRepositoryInterface;
Expand All @@ -15,10 +14,8 @@
* HTTP cookie authentication method.
*
* @see https://tools.ietf.org/html/rfc6265
*
* @psalm-suppress DeprecatedInterface
*/
final class HttpCookie implements AuthenticationMethodInterface, AuthenticatorInterface
final class HttpCookie implements AuthenticatorInterface
{
private string $cookieName = 'access-token';
private ?string $tokenType = null;
Expand All @@ -38,15 +35,6 @@ public function authenticate(ServerRequestInterface $request): ?IdentityInterfac
return $this->identityRepository->findIdentityByToken($authToken, $this->tokenType);
}

/**
* @deprecated No-op kept only for compatibility with the deprecated {@see AuthenticationMethodInterface}.
* HTTP cookie authentication does not need a challenge.
*/
public function challenge(ResponseInterface $response): ResponseInterface
{
return $response;
}

/**
* @psalm-immutable
*/
Expand Down
14 changes: 1 addition & 13 deletions src/Method/HttpHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use JetBrains\PhpStorm\Language;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\IdentityInterface;
use Yiisoft\Auth\IdentityWithTokenRepositoryInterface;
Expand All @@ -20,10 +19,8 @@
* The default implementation of HttpHeader uses the
* {@see IdentityWithTokenRepositoryInterface::findIdentityByToken()}
* and passes the value of the `X-Api-Key` header. This implementation is used mainly for authenticating API clients.
*
* @psalm-suppress DeprecatedInterface
*/
class HttpHeader implements AuthenticationMethodInterface, AuthenticatorInterface
class HttpHeader implements AuthenticatorInterface
{
protected string $headerName = 'X-Api-Key';

Expand All @@ -46,15 +43,6 @@
return null;
}

/**
* @deprecated No-op kept only for compatibility with the deprecated {@see AuthenticationMethodInterface}.
* HTTP header authentication does not need a challenge.
*/
public function challenge(ResponseInterface $response): ResponseInterface
{
return $response;
}

/**
* @param string $name The HTTP header name.
*
Expand Down Expand Up @@ -98,7 +86,7 @@
return $new;
}

protected function getAuthenticationToken(ServerRequestInterface $request): ?string

Check warning on line 89 in src/Method/HttpHeader.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ProtectedVisibility": @@ @@ return $new; } - protected function getAuthenticationToken(ServerRequestInterface $request): ?string + private function getAuthenticationToken(ServerRequestInterface $request): ?string { $authHeaders = $request->getHeader($this->headerName); $authHeader = reset($authHeaders);
{
$authHeaders = $request->getHeader($this->headerName);
$authHeader = reset($authHeaders);
Expand Down
14 changes: 1 addition & 13 deletions src/Method/QueryParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\IdentityInterface;
use Yiisoft\Auth\IdentityWithTokenRepositoryInterface;
Expand All @@ -15,10 +14,8 @@

/**
* QueryParameter supports the authentication based on the access token passed through a query parameter.
*
* @psalm-suppress DeprecatedInterface
*/
final class QueryParameter implements AuthenticationMethodInterface, AuthenticatorInterface
final class QueryParameter implements AuthenticatorInterface
{
private string $parameterName = 'access-token';
private ?string $tokenType = null;
Expand All @@ -35,15 +32,6 @@ public function authenticate(ServerRequestInterface $request): ?IdentityInterfac
return null;
}

/**
* @deprecated No-op kept only for compatibility with the deprecated {@see AuthenticationMethodInterface}.
* Query parameter authentication does not need a challenge.
*/
public function challenge(ResponseInterface $response): ResponseInterface
{
return $response;
}

/**
* @param string $name The parameter name for passing the access token.
*
Expand Down
3 changes: 1 addition & 2 deletions src/Middleware/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\Handler\AuthenticationFailureHandler;
Expand Down Expand Up @@ -37,7 +36,7 @@ final class Authentication implements MiddlewareInterface
private array $wildcards = [];

public function __construct(
private AuthenticatorInterface|AuthenticationMethodInterface $authenticationMethod,
private AuthenticatorInterface $authenticationMethod,
ResponseFactoryInterface $responseFactory,
?RequestHandlerInterface $authenticationFailureHandler = null,
) {
Expand Down
8 changes: 4 additions & 4 deletions tests/AuthenticationMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\IdentityInterface;
use Yiisoft\Auth\Middleware\Authentication;
use Yiisoft\Http\Status;
Expand All @@ -23,13 +23,13 @@ final class AuthenticationMiddlewareTest extends TestCase
{
private ResponseFactoryInterface $responseFactory;

/** @var AuthenticationMethodInterface|MockObject */
private AuthenticationMethodInterface $authenticationMethod;
/** @var AuthenticatorWithChallengeInterface|MockObject */
private AuthenticatorWithChallengeInterface $authenticationMethod;

protected function setUp(): void
{
$this->responseFactory = new Psr17Factory();
$this->authenticationMethod = $this->createMock(AuthenticationMethodInterface::class);
$this->authenticationMethod = $this->createMock(AuthenticatorWithChallengeInterface::class);
}

public function testShouldAuthenticateAndSetAttribute(): void
Expand Down
9 changes: 0 additions & 9 deletions tests/Method/HttpCookieTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ public function testIdentityNotFoundByToken(): void
);
}

public function testChallengeImmutabilityStatus(): void
{
$response = new Response(400);
$identityRepository = new FakeIdentityRepository($this->createIdentity());
$authenticationMethod = new HttpCookie($identityRepository);

$this->assertSame($response, $authenticationMethod->challenge($response));
}

public function testCustomTokenParam(): void
{
$identityRepository = new FakeIdentityRepository($this->createIdentity());
Expand Down
14 changes: 0 additions & 14 deletions tests/Method/HttpHeaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,6 @@ public function testIdentityNotFoundByToken(): void
);
}

public function testChallengeIsCorrect(): void
{
$response = new Response(400);
$identityRepository = new FakeIdentityRepository($this->createIdentity());
$authenticationMethod = new HttpHeader($identityRepository);

$this->assertEquals(
400,
$authenticationMethod
->challenge($response)
->getStatusCode(),
);
}

public function testEmptyTokenHeader(): void
{
$identityRepository = new FakeIdentityRepository($this->createIdentity());
Expand Down
11 changes: 0 additions & 11 deletions tests/Method/QueryParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,6 @@ public function testInvalidTypeToken(): void
$this->assertEmpty($identityRepository->getCallParams());
}

public function testChallengeIsCorrect(): void
{
$response = new Response(400);
$identityRepository = new FakeIdentityRepository($this->createIdentity());
$authenticationMethod = new QueryParameter($identityRepository);

$this->assertEquals(400, $authenticationMethod
->challenge($response)
->getStatusCode());
}

public function testCustomTokenParam(): void
{
$identityRepository = new FakeIdentityRepository($this->createIdentity());
Expand Down
Loading