Skip to content
Merged
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

## 3.2.2 under development

- New #113: Split `AuthenticationMethodInterface` into focused authentication and challenge interfaces (@samdark, @vjik)
- Bug #116: Fix authentication scheme in `HttpBearer` challenge according to RFC 6750 (@samdark)
- Chg #104: Bump minimal PHP version to 8.1 (@vjik)
- Enh #104: Explicitly mark readonly properties (@vjik)
- Enh #105: Explicitly import classes and functions in "use" section (@mspirkov)
- Enh #107: Remove unnecessary files from Composer package (@mspirkov)
- Enh #113: Split `AuthenticationMethodInterface` into focused authentication and challenge interfaces (@samdark)

## 3.2.1 December 17, 2025

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ $authenticationMethod = new \Yiisoft\Auth\Method\Composite([
- `\Yiisoft\Auth\IdentityWithTokenRepositoryInterface` could be additionally implemented by your application
identity repository class in case token-based authentication is needed. Typically, that is `UserIdentity`.
- `\Yiisoft\Auth\AuthenticatorInterface` should be implemented to provide your own authenticator.
- `\Yiisoft\Auth\ChallengeInterface` could be additionally implemented by an authenticator that needs to modify the
authentication failure response, for example, to add an HTTP authentication challenge.
- `\Yiisoft\Auth\AuthenticationMethodInterface` combines both interfaces and is deprecated. Existing implementations
remain compatible; new implementations should use the focused interfaces.
- `\Yiisoft\Auth\AuthenticatorWithChallengeInterface` could be implemented instead by an authenticator that also
needs to modify the authentication failure response, for example, to add an HTTP authentication challenge.
- `\Yiisoft\Auth\AuthenticationMethodInterface` is equivalent to `AuthenticatorWithChallengeInterface` and is
deprecated. Existing implementations remain compatible; new implementations should use the focused interfaces.

## Documentation

Expand Down
5 changes: 3 additions & 2 deletions src/AuthenticationMethodInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Auth;

/**
* @deprecated Implement {@see AuthenticatorInterface} and, if a challenge is needed, {@see ChallengeInterface}.
* @deprecated Implement {@see AuthenticatorInterface} or, if a challenge is needed,
* {@see AuthenticatorWithChallengeInterface}.
*/
interface AuthenticationMethodInterface extends AuthenticatorInterface, ChallengeInterface {}
interface AuthenticationMethodInterface extends AuthenticatorWithChallengeInterface {}
3 changes: 3 additions & 0 deletions src/AuthenticatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

/**
* Authenticates an identity using information available in a request.
*
* Implement this interface only if the authenticator does not need to add a challenge to the response upon
* authentication failure. Otherwise, implement {@see AuthenticatorWithChallengeInterface} instead.
*/
interface AuthenticatorInterface
{
Expand Down
23 changes: 23 additions & 0 deletions src/AuthenticatorWithChallengeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Auth;

use Psr\Http\Message\ResponseInterface;

/**
* Authenticates an identity using information available in a request and adds an authentication challenge
* to a response upon failure.
*/
interface AuthenticatorWithChallengeInterface extends AuthenticatorInterface
Comment thread
vjik marked this conversation as resolved.
{
/**
* Adds an authentication challenge to the response.
*
* @param ResponseInterface $response Response to modify.
*
* @return ResponseInterface Modified response.
*/
public function challenge(ResponseInterface $response): ResponseInterface;
}
18 changes: 0 additions & 18 deletions src/ChallengeInterface.php

This file was deleted.

6 changes: 3 additions & 3 deletions src/Method/Composite.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Auth\AuthenticationMethodInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\ChallengeInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\IdentityInterface;
use RuntimeException;

/**
* Composite allows multiple authentication methods at the same time.
*/
final class Composite implements AuthenticationMethodInterface
final class Composite implements AuthenticationMethodInterface, AuthenticatorWithChallengeInterface
Comment thread
vjik marked this conversation as resolved.
{
/**
* @param AuthenticatorInterface[] $methods
Expand Down Expand Up @@ -43,7 +43,7 @@ public function authenticate(ServerRequestInterface $request): ?IdentityInterfac
public function challenge(ResponseInterface $response): ResponseInterface
{
foreach ($this->methods as $method) {
if ($method instanceof ChallengeInterface) {
if ($method instanceof AuthenticatorWithChallengeInterface) {
$response = $method->challenge($response);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Method/HttpBasic.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
use Yiisoft\Http\Header;
Expand All @@ -28,7 +29,7 @@
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
* ```
*/
final class HttpBasic implements AuthenticationMethodInterface
final class HttpBasic implements AuthenticationMethodInterface, AuthenticatorWithChallengeInterface
{
private string $realm = 'api';
private ?string $tokenType = null;
Expand Down
3 changes: 2 additions & 1 deletion src/Method/HttpBearer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
namespace Yiisoft\Auth\Method;

use Psr\Http\Message\ResponseInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Http\Header;

/**
* Authentication method based on HTTP Bearer token.
*
* @see https://tools.ietf.org/html/rfc6750
*/
final class HttpBearer extends HttpHeader
final class HttpBearer extends HttpHeader implements AuthenticatorWithChallengeInterface
Comment thread
vjik marked this conversation as resolved.
{
protected string $headerName = Header::AUTHORIZATION;

Expand Down
7 changes: 6 additions & 1 deletion src/Method/HttpCookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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,7 +16,7 @@
*
* @see https://tools.ietf.org/html/rfc6265
*/
final class HttpCookie implements AuthenticationMethodInterface
final class HttpCookie implements AuthenticationMethodInterface, AuthenticatorInterface
Comment thread
vjik marked this conversation as resolved.
{
private string $cookieName = 'access-token';
private ?string $tokenType = null;
Expand All @@ -35,6 +36,10 @@ 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;
Expand Down
7 changes: 6 additions & 1 deletion src/Method/HttpHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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,7 +21,7 @@
* {@see IdentityWithTokenRepositoryInterface::findIdentityByToken()}
* and passes the value of the `X-Api-Key` header. This implementation is used mainly for authenticating API clients.
*/
class HttpHeader implements AuthenticationMethodInterface
class HttpHeader implements AuthenticationMethodInterface, AuthenticatorInterface
Comment thread
vjik marked this conversation as resolved.
{
protected string $headerName = 'X-Api-Key';

Expand All @@ -43,6 +44,10 @@ public function authenticate(ServerRequestInterface $request): ?IdentityInterfac
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;
Expand Down
7 changes: 6 additions & 1 deletion src/Method/QueryParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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,7 +16,7 @@
/**
* QueryParameter supports the authentication based on the access token passed through a query parameter.
*/
final class QueryParameter implements AuthenticationMethodInterface
final class QueryParameter implements AuthenticationMethodInterface, AuthenticatorInterface
Comment thread
vjik marked this conversation as resolved.
{
private string $parameterName = 'access-token';
private ?string $tokenType = null;
Expand All @@ -32,6 +33,10 @@ 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;
Expand Down
4 changes: 2 additions & 2 deletions src/Middleware/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Auth\AuthenticatorInterface;
use Yiisoft\Auth\ChallengeInterface;
use Yiisoft\Auth\AuthenticatorWithChallengeInterface;
use Yiisoft\Auth\Handler\AuthenticationFailureHandler;
use Yiisoft\Strings\WildcardPattern;

Expand Down Expand Up @@ -53,7 +53,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
if ($identity === null && !$this->isOptional($request)) {
$response = $this->failureHandler->handle($request);

return $this->authenticationMethod instanceof ChallengeInterface
return $this->authenticationMethod instanceof AuthenticatorWithChallengeInterface
? $this->authenticationMethod->challenge($response)
: $response;
}
Expand Down
Loading