mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-02 13:02:24 +08:00
fix composite auth ignore only/except filters of auth methods (#19418)
* fix compositeAuth ignore only/except filters of child auth methods * fix * add tests for wrong token * fix * update changelog * Update CHANGELOG.md Co-authored-by: Bizley <pawel@positive.codes>
This commit is contained in:
@ -29,6 +29,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #19368: Fix PHP 8.1 error when `$fileMimeType` is `null` in `yii\validators\FileValidator::validateMimeType()` (bizley)
|
||||
- Enh #19384: Normalize `setBodyParams()` and `getBodyParam()` in `yii\web\Request` (WinterSilence, albertborsos)
|
||||
- Bug #19386: Fix recursive calling `yii\helpers\BaseArrayHelper::htmlDecode()` (WinterSilence)
|
||||
- Bug #19418: Fix `yii\filters\auth\CompositeAuth` ignoring `only` and `except` options (lesha724)
|
||||
- Enh #19401: Delay `exit(1)` in `yii\base\ErrorHandler::handleFatalError` (arrilot)
|
||||
- Bug #19402: Add shutdown event and fix working directory in `yii\base\ErrorHandler` (WinterSilence)
|
||||
- Enh #19416: Update and improve configurations for `yii\console\controllers\MessageController` (WinterSilence)
|
||||
|
||||
@ -70,9 +70,11 @@ class CompositeAuth extends AuthMethod
|
||||
}
|
||||
}
|
||||
|
||||
$identity = $auth->authenticate($user, $request, $response);
|
||||
if ($identity !== null) {
|
||||
return $identity;
|
||||
if (isset($this->owner->action) && $auth->isActive($this->owner->action)) {
|
||||
$identity = $auth->authenticate($user, $request, $response);
|
||||
if ($identity !== null) {
|
||||
return $identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,21 +8,40 @@
|
||||
namespace yiiunit\framework\filters\auth;
|
||||
|
||||
use Yii;
|
||||
use yii\filters\auth\AuthMethod;
|
||||
use yii\filters\auth\CompositeAuth;
|
||||
use yii\filters\auth\HttpBearerAuth;
|
||||
use yii\filters\auth\HttpHeaderAuth;
|
||||
use yii\rest\Controller;
|
||||
use yii\web\UnauthorizedHttpException;
|
||||
use yiiunit\framework\web\UserIdentity;
|
||||
|
||||
/**
|
||||
* @author Ezekiel Fernandez <ezekiel_p_fernandez@yahoo.com>
|
||||
*/
|
||||
class TestAuth extends AuthMethod
|
||||
class TestAuth extends HttpHeaderAuth
|
||||
{
|
||||
public function authenticate($user, $request, $response)
|
||||
{
|
||||
return $user;
|
||||
$authHeader = $request->getHeaders()->get($this->header);
|
||||
|
||||
if ($authHeader !== null) {
|
||||
if ($this->pattern !== null) {
|
||||
if (preg_match($this->pattern, $authHeader, $matches)) {
|
||||
$authHeader = $matches[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$identity = \yiiunit\framework\filters\stubs\UserIdentity::findIdentity($authHeader);
|
||||
if ($identity === null) {
|
||||
$this->challenge($response);
|
||||
$this->handleFailure($response);
|
||||
}
|
||||
|
||||
return $identity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +49,8 @@ class TestController extends Controller
|
||||
{
|
||||
public $authMethods = [];
|
||||
|
||||
public $optional = [];
|
||||
|
||||
public function actionA()
|
||||
{
|
||||
return 'success';
|
||||
@ -73,6 +94,7 @@ class TestController extends Controller
|
||||
'authMethods' => $this->authMethods ?: [
|
||||
TestAuth::className(),
|
||||
],
|
||||
'optional' => $this->optional
|
||||
],
|
||||
];
|
||||
}
|
||||
@ -107,6 +129,7 @@ class CompositeAuthTest extends \yiiunit\TestCase
|
||||
public function testCallingRunWithCompleteRoute()
|
||||
{
|
||||
/** @var TestController $controller */
|
||||
Yii::$app->request->headers->set('X-Api-Key', 'user1');
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$this->assertEquals('success', $controller->run('test/d'));
|
||||
}
|
||||
@ -117,6 +140,7 @@ class CompositeAuthTest extends \yiiunit\TestCase
|
||||
public function testRunAction()
|
||||
{
|
||||
/** @var TestController $controller */
|
||||
Yii::$app->request->headers->set('X-Api-Key', 'user1');
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$this->assertEquals('success', $controller->run('b'));
|
||||
}
|
||||
@ -124,22 +148,123 @@ class CompositeAuthTest extends \yiiunit\TestCase
|
||||
public function testRunButWithActionIdOnly()
|
||||
{
|
||||
/** @var TestController $controller */
|
||||
Yii::$app->request->headers->set('X-Api-Key', 'user1');
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$this->assertEquals('success', $controller->run('c'));
|
||||
}
|
||||
|
||||
public function testCompositeAuth()
|
||||
public function testRunWithWrongToken()
|
||||
{
|
||||
Yii::$app->request->headers->set('Authorization', base64_encode("foo:bar"));
|
||||
/** @var TestAuthController $controller */
|
||||
/** @var TestController $controller */
|
||||
Yii::$app->request->headers->set('X-Api-Key', 'wrong-user');
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$controller->authMethods = [
|
||||
HttpBearerAuth::className(),
|
||||
TestAuth::className(),
|
||||
$this->expectException('yii\web\UnauthorizedHttpException');
|
||||
$controller->run('a');
|
||||
}
|
||||
|
||||
public function testRunWithoutAuthHeader()
|
||||
{
|
||||
/** @var TestController $controller */
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$this->expectException('yii\web\UnauthorizedHttpException');
|
||||
$controller->run('a');
|
||||
}
|
||||
|
||||
public function testRunWithOptionalAction()
|
||||
{
|
||||
/** @var TestController $controller */
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$controller->optional = ['a'];
|
||||
$this->assertEquals('success', $controller->run('a'));
|
||||
}
|
||||
|
||||
public function compositeAuthDataProvider()
|
||||
{
|
||||
return [
|
||||
//base usage
|
||||
[
|
||||
[
|
||||
HttpBearerAuth::className(),
|
||||
TestAuth::className(),
|
||||
],
|
||||
'b',
|
||||
true
|
||||
],
|
||||
//empty auth methods
|
||||
[
|
||||
[],
|
||||
'b',
|
||||
true
|
||||
],
|
||||
//only "a", run "b"
|
||||
[
|
||||
[
|
||||
HttpBearerAuth::className(),
|
||||
[
|
||||
'class' => TestAuth::className(),
|
||||
'only' => ['a']
|
||||
],
|
||||
],
|
||||
'b',
|
||||
false
|
||||
],
|
||||
//only "a", run "a"
|
||||
[
|
||||
[
|
||||
HttpBearerAuth::className(),
|
||||
[
|
||||
'class' => TestAuth::className(),
|
||||
'only' => ['a']
|
||||
],
|
||||
],
|
||||
'a',
|
||||
true
|
||||
],
|
||||
//except "b", run "a"
|
||||
[
|
||||
[
|
||||
HttpBearerAuth::className(),
|
||||
[
|
||||
'class' => TestAuth::className(),
|
||||
'except' => ['b']
|
||||
],
|
||||
],
|
||||
'a',
|
||||
true
|
||||
],
|
||||
//except "b", run "b"
|
||||
[
|
||||
[
|
||||
HttpBearerAuth::className(),
|
||||
[
|
||||
'class' => TestAuth::className(),
|
||||
'except' => ['b']
|
||||
],
|
||||
],
|
||||
'b',
|
||||
false
|
||||
]
|
||||
];
|
||||
try {
|
||||
$this->assertEquals('success', $controller->run('b'));
|
||||
} catch (UnauthorizedHttpException $e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $authMethods
|
||||
* @param string $actionId
|
||||
* @param bool $expectedAuth
|
||||
*
|
||||
* @dataProvider compositeAuthDataProvider
|
||||
*/
|
||||
public function testCompositeAuth($authMethods, $actionId, $expectedAuth)
|
||||
{
|
||||
Yii::$app->request->headers->set('X-Api-Key', 'user1');
|
||||
/** @var TestController $controller */
|
||||
$controller = Yii::$app->createController('test')[0];
|
||||
$controller->authMethods = $authMethods;
|
||||
if( $expectedAuth)
|
||||
$this->assertEquals('success', $controller->run($actionId));
|
||||
else {
|
||||
$this->expectException('yii\web\UnauthorizedHttpException');
|
||||
$controller->run($actionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user