From 7efb47bf39bbf5b2bdc83e75332bc49e5e40fdd6 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 4 Sep 2014 15:34:19 -0400 Subject: [PATCH] Fixes #4920: `yii\filters\auth\CompositeAuth` should not trigger error as long as one of the methods succeeds Fixes #3177: `yii\filters\auth\CompositeAuth` will send out challenges from all auth methods --- framework/CHANGELOG.md | 2 ++ framework/filters/auth/AuthInterface.php | 7 ++++++- framework/filters/auth/AuthMethod.php | 14 ++++++++++++-- framework/filters/auth/CompositeAuth.php | 17 +++++++++++------ framework/filters/auth/HttpBasicAuth.php | 6 +----- framework/filters/auth/HttpBearerAuth.php | 6 +----- framework/filters/auth/QueryParamAuth.php | 11 ----------- 7 files changed, 33 insertions(+), 30 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index b11f673..4faefa6 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -88,6 +88,7 @@ Yii Framework 2 Change Log - Bug #4755: `yii\test\BaseActiveFixture::unload()` does not clean up the internal cached data (qiangxue) - Bug #4813: Fixed MSSQL schema that was getting incorrect info about constraints (samdark, SerjRamone, o-rey) - Bug #4880: Return value of yii\web\Request::getPrefferedLanguage() was a normalized value instead of a valid language value from the input array (cebe) +- Bug #4920: `yii\filters\auth\CompositeAuth` should not trigger error as long as one of the methods succeeds (qiangxue) - Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark) - Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul) - Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue) @@ -113,6 +114,7 @@ Yii Framework 2 Change Log - Enh #3108: Added `yii\debug\Module::enableDebugLogs` to disable logging debug logs by default (qiangxue) - Enh #3132: `yii\rbac\PhpManager` now supports more compact data file format (qiangxue) - Enh #3154: Added validation error display for `GridView` filters (ivan-kolmychek) +- Enh #3177: `yii\filters\auth\CompositeAuth` will send out challenges from all auth methods (qiangxue) - Enh #3196: Masked input upgraded to use jquery.inputmask plugin with more features. (kartik-v) - Enh #3220: Added support for setting transaction isolation levels (cebe) - Enh #3221: Added events for DB transaction commit/rollback (drcypher, qiangxue) diff --git a/framework/filters/auth/AuthInterface.php b/framework/filters/auth/AuthInterface.php index 3591c87..66235a4 100644 --- a/framework/filters/auth/AuthInterface.php +++ b/framework/filters/auth/AuthInterface.php @@ -23,7 +23,6 @@ interface AuthInterface { /** * Authenticates the current user. - * * @param User $user * @param Request $request * @param Response $response @@ -32,6 +31,12 @@ interface AuthInterface */ public function authenticate($user, $request, $response); /** + * Generates challenges upon authentication failure. + * For example, some appropriate HTTP headers may be generated. + * @param Response $response + */ + public function challenge($response); + /** * Handles authentication failure. * The implementation should normally throw UnauthorizedHttpException to indicate authentication failure. * @param Response $response diff --git a/framework/filters/auth/AuthMethod.php b/framework/filters/auth/AuthMethod.php index 7675749..1ec8a60 100644 --- a/framework/filters/auth/AuthMethod.php +++ b/framework/filters/auth/AuthMethod.php @@ -41,16 +41,19 @@ abstract class AuthMethod extends ActionFilter implements AuthInterface */ public function beforeAction($action) { + $response = $this->response ? : Yii::$app->getResponse(); + $identity = $this->authenticate( $this->user ? : Yii::$app->getUser(), $this->request ? : Yii::$app->getRequest(), - $this->response ? : Yii::$app->getResponse() + $response ); if ($identity !== null) { return true; } else { - $this->handleFailure($this->response ? : Yii::$app->getResponse()); + $this->challenge($response); + $this->handleFailure($response); return false; } } @@ -58,6 +61,13 @@ abstract class AuthMethod extends ActionFilter implements AuthInterface /** * @inheritdoc */ + public function challenge($response) + { + } + + /** + * @inheritdoc + */ public function handleFailure($response) { throw new UnauthorizedHttpException('You are requesting with an invalid credential.'); diff --git a/framework/filters/auth/CompositeAuth.php b/framework/filters/auth/CompositeAuth.php index 90ca6ae..bfc24a1 100644 --- a/framework/filters/auth/CompositeAuth.php +++ b/framework/filters/auth/CompositeAuth.php @@ -74,12 +74,17 @@ class CompositeAuth extends AuthMethod } } - if (!empty($this->authMethods)) { - /* @var $auth AuthInterface */ - $auth = reset($this->authMethods); - $auth->handleFailure($response); - } - return null; } + + /** + * @inheritdoc + */ + public function challenge($response) + { + foreach ($this->authMethods as $method) { + /** @var $method AuthInterface */ + $method->challenge($response); + } + } } diff --git a/framework/filters/auth/HttpBasicAuth.php b/framework/filters/auth/HttpBasicAuth.php index 5fbdeda..a8795e1 100644 --- a/framework/filters/auth/HttpBasicAuth.php +++ b/framework/filters/auth/HttpBasicAuth.php @@ -7,9 +7,6 @@ namespace yii\filters\auth; -use Yii; -use yii\web\UnauthorizedHttpException; - /** * HttpBasicAuth is an action filter that supports the HTTP Basic authentication method. * @@ -90,9 +87,8 @@ class HttpBasicAuth extends AuthMethod /** * @inheritdoc */ - public function handleFailure($response) + public function challenge($response) { $response->getHeaders()->set('WWW-Authenticate', "Basic realm=\"{$this->realm}\""); - throw new UnauthorizedHttpException('You are requesting with an invalid access token.'); } } diff --git a/framework/filters/auth/HttpBearerAuth.php b/framework/filters/auth/HttpBearerAuth.php index f8fe5cd..0aece20 100644 --- a/framework/filters/auth/HttpBearerAuth.php +++ b/framework/filters/auth/HttpBearerAuth.php @@ -7,9 +7,6 @@ namespace yii\filters\auth; -use Yii; -use yii\web\UnauthorizedHttpException; - /** * HttpBearerAuth is an action filter that supports the authentication method based on HTTP Bearer token. * @@ -57,9 +54,8 @@ class HttpBearerAuth extends AuthMethod /** * @inheritdoc */ - public function handleFailure($response) + public function challenge($response) { $response->getHeaders()->set('WWW-Authenticate', "Bearer realm=\"{$this->realm}\""); - throw new UnauthorizedHttpException('You are requesting with an invalid access token.'); } } diff --git a/framework/filters/auth/QueryParamAuth.php b/framework/filters/auth/QueryParamAuth.php index 25548a0..cd7888b 100644 --- a/framework/filters/auth/QueryParamAuth.php +++ b/framework/filters/auth/QueryParamAuth.php @@ -7,9 +7,6 @@ namespace yii\filters\auth; -use Yii; -use yii\web\UnauthorizedHttpException; - /** * QueryParamAuth is an action filter that supports the authentication based on the access token passed through a query parameter. * @@ -42,12 +39,4 @@ class QueryParamAuth extends AuthMethod return null; } - - /** - * @inheritdoc - */ - public function handleFailure($response) - { - throw new UnauthorizedHttpException(Yii::t('yii', 'You are requesting with an invalid access token.')); - } }