Codeception / module-yii2

Codeception module for Yii2 framework
MIT License
16 stars 36 forks source link

REST authorization headers are missing with Yii2 module #35

Closed ddinchev closed 2 years ago

ddinchev commented 6 years ago

What are you trying to achieve?

I want to write RESTful integration tests using Yii2 module (internal browser). I'm authorizing with $I->amBearerAuthenticated('token') but the header is not passed in Yii2's Connector module. The very same test passes when I use PHPBrowser. Examples below.

// $I->haveHttpHeader('Authorization', 'Bearer: sync-fixture-access-token');
$I->amBearerAuthenticated('sync-fixture-access-token');
$I->sendGET($pullEndpoint);
$I->canSeeResponseIsJson();
$I->seeResponseCodeIs(200);

The test successfully hits the yii\filters\auth\HttpHeaderAuth. But here the $request->headers collection is empty, so the auth fails with 401.

I tried to debug the issue - the internal browser creates a $_SERVER['HTTP_AUTHORIZATION'] key with value Bearer: sync-fixture-access-token over here. However, I can not find how the $_SERVER vars are decoded to yii\web\Request headers ever after?

I've provided output and config below.

Provide console output if related. Use -vvv mode for more details.

vagrant@xxxx:/app/tests$ codecept run -c api/ functional sync -vvv
Codeception PHP Testing Framework v2.4.0
Powered by PHPUnit 7.1.5 by Sebastian Bergmann and contributors.

Tests\api.functional Tests (1) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Modules: Asserts, Filesystem, Yii2, REST, \tests\common\_support\FixtureHelper
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PullCest: Test pull
Signature: tests\api\functional\sync\PullCest:testPull
Test: functional/sync/PullCest.php:testPull
Scenario --
  [yii\db\Connection::open] 'Opening DB connection: mysql:host=127.0.0.1;port=3306;dbname=xxxxxxx'
  [Database] Transaction started
 I have http header "Authorization","Bearer: sync-fixture-access-token"
 I send get "http://localhost/api/web/index-test.php/sync/pull/0"
  [Request] GET http://localhost/api/web/index-test.php/sync/pull/0
  [Request Headers] {"Authorization":"Bearer: sync-fixture-access-token"}
  [yii\web\HttpException:401] 'yii\\web\\UnauthorizedHttpException: Your request was made with invalid credentials. in /app/vendor/yiisoft/yii2/filters/auth/AuthMethod.php:93
  Stack trace:
  #0 /app/vendor/yiisoft/yii2/filters/auth/AuthMethod.php(76): yii\\filters\\auth\\AuthMethod->handleFailure(Object(yii\\web\\Response))
  Codeception/Codeception#1 /app/vendor/yiisoft/yii2/filters/auth/CompositeAuth.php(57): yii\\filters\\auth\\AuthMethod->beforeAction(Object(yii\\base\\InlineAction))
  Codeception/Codeception#2 /app/vendor/yiisoft/yii2/base/ActionFilter.php(77): yii\\filters\\auth\\CompositeAuth->beforeAction(Object(yii\\base\\InlineAction))
...
  Codeception/Codeception#39 /app/vendor/codeception/codeception/codecept(42): Codeception\\Application->run()
  Codeception/Codeception#40 {main}'
  [Page] http://localhost/api/web/index-test.php/sync/pull/0
  [Response] 401
  [Request Cookies] []
  [Response Headers] {"www-authenticate":["Bearer realm="api""],"content-type":["application/json; charset=UTF-8"]}
  [Response] {"name":"Unauthorized","message":"Your request was made with invalid credentials.","code":0,"status":401,"type":"yii\\web\\UnauthorizedHttpException"}
 I can see response is json
 I see response code is 200
 FAIL

Provide test source code if related


class PullCest
{
    public function testPull(FunctionalTester $I)
    {
        $pullEndpoint = $this->createUrl(0);
        $I->haveHttpHeader('Authorization', 'Bearer: sync-fixture-access-token');
        $I->sendGET($pullEndpoint);
        $I->canSeeResponseIsJson();
        $I->seeResponseCodeIs(200);
    }

    private function createUrl(int $syncVersion)
    {
        return \Yii::$app->urlManager->createAbsoluteUrl(['sync/pull/' . $syncVersion]);
    }
}

Details

class_name: FunctionalTester
modules:
    enabled:
      - Asserts
      - Filesystem
      - Yii2:
          configFile: ../config/api/functional.php
      - REST:
          depends: Yii2
      - tests\common\_support\FixtureHelper
ddinchev commented 6 years ago

I've changed my authenticator to use composite auth (header and GET param):


    public function behaviors()
    {
        return ArrayHelper::merge(parent::behaviors(), [
            'authenticator' => [
                'class' => CompositeAuth::class,
                'authMethods' => [
                    ['class' => HttpBearerAuth::class],
                    ['class' => QueryParamAuth::class, 'tokenParam' => 'accessToken'],
                ]
            ],
            'corsFilter' => [
                'class' => Cors::class,
            ]
        ]);
    }

Passing the accessToken as GET param works fine for both functional and acceptance tests. Passing the accessToken as Bearer header works for acceptance tests and in production scenario. It only fails with the functional tests.

tahpot commented 5 years ago

I've hit this issue as well.

SamMousa commented 2 years ago

I'm closing this due to its age. If it is still relevant in current versions feel free to create a new issue.