/**
 * @link https://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license https://www.yiiframework.com/license/
 */

namespace yii\filters\auth;

use Yii;
use yii\base\ActionFilter;
use yii\base\Controller;
use yii\base\InvalidConfigException;

/**
 * CompositeAuth is an action filter that supports multiple authentication methods at the same time.
 *
 * The authentication methods contained by CompositeAuth are configured via [[authMethods]],
 * which is a list of supported authentication class configurations.
 *
 * The following example shows how to support three authentication methods:
 *
 * ```php
 * public function behaviors()
 * {
 *     return [
 *         'compositeAuth' => [
 *             'class' => \yii\filters\auth\CompositeAuth::class,
 *             'authMethods' => [
 *                 \yii\filters\auth\HttpBasicAuth::class,
 *                 \yii\filters\auth\QueryParamAuth::class,
 *             ],
 *         ],
 *     ];
 * }
 * ```
 *
 * @author Qiang Xue <<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>>
 * @since 2.0
 */
class CompositeAuth extends AuthMethod
{
    /**
     * @var array the supported authentication methods. This property should take a list of supported
     * authentication methods, each represented by an authentication class or configuration.
     *
     * If this property is empty, no authentication will be performed.
     *
     * Note that an auth method class must implement the [[\yii\filters\auth\AuthInterface]] interface.
     */
    public $authMethods = [];


    /**
     * {@inheritdoc}
     */
    public function beforeAction($action)
    {
        return empty($this->authMethods) ? true : parent::beforeAction($action);
    }

    /**
     * {@inheritdoc}
     */
    public function authenticate($user, $request, $response)
    {
        foreach ($this->authMethods as $i => $auth) {
            if (!$auth instanceof AuthInterface) {
                $this->authMethods[$i] = $auth = Yii::createObject($auth);
                if (!$auth instanceof AuthInterface) {
                    throw new InvalidConfigException(get_class($auth) . ' must implement yii\filters\auth\AuthInterface');
                }
            }

            if (
                $this->owner instanceof Controller
                && (
                    !isset($this->owner->action)
                    || (
                        $auth instanceof ActionFilter
                        && !$auth->isActive($this->owner->action)
                    )
                )
            ) {
                continue;
            }

            $authUser = $auth->user;
            if ($authUser != null && !$authUser instanceof \yii\web\User) {
                throw new InvalidConfigException(get_class($authUser) . ' must implement yii\web\User');
            } elseif ($authUser != null) {
                $user = $authUser;
            }

            $authRequest = $auth->request;
            if ($authRequest != null && !$authRequest instanceof \yii\web\Request) {
                throw new InvalidConfigException(get_class($authRequest) . ' must implement yii\web\Request');
            } elseif ($authRequest != null) {
                $request = $authRequest;
            }

            $authResponse = $auth->response;
            if ($authResponse != null && !$authResponse instanceof \yii\web\Response) {
                throw new InvalidConfigException(get_class($authResponse) . ' must implement yii\web\Response');
            } elseif ($authResponse != null) {
                $response = $authResponse;
            }

            $identity = $auth->authenticate($user, $request, $response);
            if ($identity !== null) {
                return $identity;
            }
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function challenge($response)
    {
        foreach ($this->authMethods as $method) {
            /** @var AuthInterface $method */
            $method->challenge($response);
        }
    }
}

/**
 * @link https://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license https://www.yiiframework.com/license/
 */

namespace yii\filters\auth;

use Yii;
use yii\base\Action;
use yii\base\ActionFilter;
use yii\helpers\StringHelper;
use yii\web\Request;
use yii\web\Response;
use yii\web\UnauthorizedHttpException;
use yii\web\User;

/**
 * AuthMethod is a base class implementing the [[AuthInterface]] interface.
 *
 * @author Qiang Xue <<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>>
 * @since 2.0
 */
abstract class AuthMethod extends ActionFilter implements AuthInterface
{
    /**
     * @var User|null the user object representing the user authentication status. If not set, the `user` application component will be used.
     */
    public $user;
    /**
     * @var Request|null the current request. If not set, the `request` application component will be used.
     */
    public $request;
    /**
     * @var Response|null the response to be sent. If not set, the `response` application component will be used.
     */
    public $response;
    /**
     * @var array list of action IDs that this filter will be applied to, but auth failure will not lead to error.
     * It may be used for actions, that are allowed for public, but return some additional data for authenticated users.
     * Defaults to empty, meaning authentication is not optional for any action.
     * Since version 2.0.10 action IDs can be specified as wildcards, e.g. `site/*`.
     * @see isOptional()
     * @since 2.0.7
     */
    public $optional = [];


    /**
     * {@inheritdoc}
     */
    public function beforeAction($action)
    {
        $response = $this->response ?: Yii::$app->getResponse();

        try {
            $identity = $this->authenticate(
                $this->user ?: Yii::$app->getUser(),
                $this->request ?: Yii::$app->getRequest(),
                $response
            );
        } catch (UnauthorizedHttpException $e) {
            if ($this->isOptional($action)) {
                return true;
            }

            throw $e;
        }

        if ($identity !== null || $this->isOptional($action)) {
            return true;
        }

        $this->challenge($response);
        $this->handleFailure($response);

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function challenge($response)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function handleFailure($response)
    {
        throw new UnauthorizedHttpException('Your request was made with invalid credentials.');
    }

    /**
     * Checks, whether authentication is optional for the given action.
     *
     * @param Action $action action to be checked.
     * @return bool whether authentication is optional or not.
     * @see optional
     * @since 2.0.7
     */
    protected function isOptional($action)
    {
        $id = $this->getActionId($action);
        foreach ($this->optional as $pattern) {
            if (StringHelper::matchWildcard($pattern, $id)) {
                return true;
            }
        }

        return false;
    }
}


My behavior:

	$behaviors['authenticator'] =
		[
			'class' => CompositeAuth::class,
			'except' => ['options'],
			'authMethods' => [
				\app\components\CookieJwtAuth::class,// Cookie based for browsers - Check 'access_token' cookie
				 \yii\filters\auth\HttpBasicAuth::class,// Header based for native app/api clients
			],
		];

namespace app\components;

use yii\filters\auth\AuthMethod;
use yii\web\UnauthorizedHttpException;

use app\helpers\JwtHelper;
use app\helpers\JwtCookieHelper;

/**
* CookieJwtAuth handles user authentication via a JWT stored in a cookie.
*
* This class extends Yii's AuthMethod to implement an authentication mechanism
* where the JWT (JSON Web Token) is extracted from a cookie named 'access_token'.
*
* The token is validated using a helper class JwtHelper. If the token is valid,
* it delegates to the user component to log in the user based on this token.
*
* If the token is missing, authentication is skipped (returns null).
* If the token is invalid, an UnauthorizedHttpException is thrown, resulting
* in a 401 Unauthorized HTTP response.
*/
class CookieJwtAuth extends AuthMethod
{
	/**
	* Authenticates a user based on JWT stored in the 'access_token' cookie.
	* @param \yii\web\User $user The user component that manages authentication state and identity.
	* @param \yii\web\Request $request The current request object.
	* @param \yii\web\Response $response The current response object.
	* @return \yii\web\IdentityInterface|null Returns the user identity if authentication is successful,
	*  null if there is no token in the cookie (meaning no authentication attempted).
	* @throws UnauthorizedHttpException if the JWT token is invalid or cannot be verified.
	*/
	public function authenticate($user, $request, $response)
	{
		file_put_contents(__DIR__ . '/debug_authenticate_called.log', date('c') . " authenticate called\n", FILE_APPEND);
	
		//die('CookieJwtAuth called');
	
		// Look for Jwt token in the 'access_token' cookie
		$cookieName = JwtCookieHelper::getAccessCookie();
		$rawCookie = $_COOKIE[$cookieName] ?? '(not set)';
		$token = $request->cookies->getValue($cookieName);
		
		//\Yii::debug("Authenticating JWT from cookie '{$cookieName}': " . ($token ?? 'none'), __METHOD__);
		\Yii::debug("Raw cookie (from \$_COOKIE): " . $rawCookie, __METHOD__);
		\Yii::debug("Cookie value (from Yii request): " . ($token ?? 'none'), __METHOD__);
		
		// If no token was found, skip authentication (other auth methods can be tried)
		if (!$token)
		{
			return null;
		}
		
		/** 
		* TODO - When we check the $payload =... we are decoding the JWT token, we also 
		* do this by $identity =... and isn't needed to decode JWT token twice.
		*
		* Validate the token using JwtHelper; returns payload array on success, false on failure
		*
		$payload = JwtHelper::validateToken($token);
		
		if ($payload === false)
		{
			\Yii::debug('JWT validation failed for token: ' . $token, __METHOD__);
			
			throw new UnauthorizedHttpException('Invalid token.');
		}
		
		// @see app\models\User $user->loginByAccessToken(); to return an identity
		//return $user->loginByAccessToken($token, get_class($this));//*/
		
		$identity = $user->loginByAccessToken($token, get_class($this));
		if ($identity === null)
		{
			//\Yii::debug('User not found for user_key: ' . $payload->sub, __METHOD__);
			
			throw new UnauthorizedHttpException('User not found.');
		
		}
		
		//\Yii::debug('User found: ' . $identity->id, __METHOD__);
		
		return $identity;//*/
	}
}

cant seem to get my CookieJwtAuth to work.