Skip to content

Commit

Permalink
Fix #388: Added support to configure the OAuth2 access token location…
Browse files Browse the repository at this point in the history
… in requests and added a generic OAuth2 client
  • Loading branch information
rhertogh committed Mar 26, 2024
1 parent 1677120 commit b9f753f
Show file tree
Hide file tree
Showing 18 changed files with 391 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Yii Framework 2 authclient extension Change Log
------------------------

- Enh #387: Use appropriate exception if client does not exist (eluhr)
- Enh #388: Added support to configure the OAuth2 access token location in requests and added a generic OAuth2 client (rhertogh)


2.2.15 December 16, 2023
Expand Down
38 changes: 35 additions & 3 deletions src/OAuth2.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace yii\authclient;

use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\web\HttpException;
Expand Down Expand Up @@ -37,6 +38,18 @@
*/
abstract class OAuth2 extends BaseOAuth
{
/**
* Apply the access token to the request header
* @since 2.2.16
*/
const ACCESS_TOKEN_LOCATION_HEADER = 'header';

/**
* Apply the access token to the request body
* @since 2.2.16
*/
const ACCESS_TOKEN_LOCATION_BODY = 'body';

/**
* @var string protocol version.
*/
Expand Down Expand Up @@ -71,6 +84,15 @@ abstract class OAuth2 extends BaseOAuth
*/
public $enablePkce = false;

/**
* @var string The location of the access token when it is applied to the request.
* NOTE: According to the OAuth2 specification this should be `header` by default,
* however, for backwards compatibility the default value used here is `body`.
* @since 2.2.16
*
* @see https://datatracker.ietf.org/doc/html/rfc6749#section-7
*/
public $accessTokenLocation = self::ACCESS_TOKEN_LOCATION_BODY;

/**
* Composes user authorization URL.
Expand Down Expand Up @@ -167,12 +189,22 @@ public function fetchAccessToken($authCode, array $params = [])

/**
* {@inheritdoc}
* @throws InvalidConfigException
*/
public function applyAccessTokenToRequest($request, $accessToken)
{
$data = $request->getData();
$data['access_token'] = $accessToken->getToken();
$request->setData($data);
switch($this->accessTokenLocation) {
case self::ACCESS_TOKEN_LOCATION_BODY:
$data = $request->getData();
$data['access_token'] = $accessToken->getToken();
$request->setData($data);
break;
case self::ACCESS_TOKEN_LOCATION_HEADER:
$request->getHeaders()->set('Authorization', 'Bearer ' . $accessToken->getToken());
break;
default:
throw new InvalidConfigException('Unknown access token location: ' . $this->accessTokenLocation);
}
}

/**
Expand Down
16 changes: 6 additions & 10 deletions src/OpenIdConnect.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

namespace yii\authclient;

use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Checker\AlgorithmChecker;
use Jose\Component\Checker\HeaderCheckerManager;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\JWSLoader;
use Jose\Component\Signature\JWSTokenSupport;
Expand Down Expand Up @@ -76,6 +76,11 @@
*/
class OpenIdConnect extends OAuth2
{
/**
* {@inheritdoc}
*/
public $accessTokenLocation = OAuth2::ACCESS_TOKEN_LOCATION_HEADER;

/**
* @var array Predefined OpenID Connect Claims
* @see https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.2
Expand Down Expand Up @@ -352,15 +357,6 @@ protected function initUserAttributes()
return $idTokenData;
}

/**
* {@inheritdoc}
*/
public function applyAccessTokenToRequest($request, $accessToken)
{
// OpenID Connect requires bearer token auth for the user info endpoint
$request->getHeaders()->set('Authorization', 'Bearer ' . $accessToken->getToken());
}

/**
* {@inheritdoc}
*/
Expand Down
5 changes: 5 additions & 0 deletions src/clients/GitHub.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
*/
class GitHub extends OAuth2
{
/**
* {@inheritdoc}
*/
public $accessTokenLocation = OAuth2::ACCESS_TOKEN_LOCATION_HEADER;

/**
* {@inheritdoc}
*/
Expand Down
55 changes: 55 additions & 0 deletions src/clients/Oauth2Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/

namespace yii\authclient\clients;

use yii\authclient\OAuth2;

/**
* Generic client that allows authentication via OAuth 2.0.
*
* Example application configuration:
*
* ```php
* 'components' => [
* 'authClientCollection' => [
* 'class' => 'yii\authclient\Collection',
* 'clients' => [
* 'oauth2' => [
* 'class' => 'yii\authclient\clients\Oauth2Client',
* 'authUrl' => 'https://oauth2service.com/oauth2/authorize',
* 'tokenUrl' => 'https://oauth2service.com/oauth2/authorize',
* 'apiBaseUrl' => 'https://oauth2service.com/api',
* 'clientId' => 'your_app_client_id',
* 'clientSecret' => 'your_app_client_secret',
* 'name' => 'custom name',
* 'title' => 'custom title'
* ],
* ],
* ]
* // ...
* ]
* ```
*
* @since 2.2.16
*/
class Oauth2Client extends OAuth2
{

/**
* {@inheritdoc}
*/
public $accessTokenLocation = self::ACCESS_TOKEN_LOCATION_HEADER;

/**
* {@inheritdoc}
*/
protected function initUserAttributes()
{
return []; // Plain Oauth 2.0 doesn't specify user attributes.
}
}
15 changes: 6 additions & 9 deletions src/clients/TwitterOAuth2.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
*/
class TwitterOAuth2 extends OAuth2
{
/**
* {@inheritdoc}
*/
public $accessTokenLocation = OAuth2::ACCESS_TOKEN_LOCATION_HEADER;

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -64,12 +69,4 @@ protected function defaultTitle()
{
return 'Twitter';
}

/**
* {@inheritdoc}
*/
public function applyAccessTokenToRequest($request, $accessToken)
{
$request->getHeaders()->set('Authorization', 'Bearer '. $accessToken->getToken());
}
}
}
20 changes: 20 additions & 0 deletions tests/clients/FacebookTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\Facebook;
use yii\authclient\OAuth2;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;

class FacebookTest extends BaseOauth2ClientTestCase
{
protected function createClient()
{
return new Facebook();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_BODY;
}
}
25 changes: 25 additions & 0 deletions tests/clients/GitHubTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\GitHub;
use yii\authclient\OAuth2;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;

class GitHubTest extends BaseOauth2ClientTestCase
{
protected function createClient()
{
return new GitHub();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_HEADER;
}

protected function getAccessTokenHeaderTypeName()
{
return 'token';
}
}
10 changes: 8 additions & 2 deletions tests/clients/GoogleHybridTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\GoogleHybrid;
use yiiunit\extensions\authclient\TestCase;
use yii\authclient\OAuth2;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;
use yiiunit\extensions\authclient\traits\OAuthDefaultReturnUrlTestTrait;

class GoogleHybridTest extends TestCase
class GoogleHybridTest extends BaseOauth2ClientTestCase
{
use OAuthDefaultReturnUrlTestTrait;

Expand All @@ -15,6 +16,11 @@ protected function createClient()
return new GoogleHybrid();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_BODY;
}

/**
* Data provider for [[testDefaultReturnUrl]].
* @return array test data.
Expand Down
27 changes: 10 additions & 17 deletions tests/clients/GoogleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,27 @@
namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\Google;
use yii\authclient\OAuth2;
use yii\authclient\OAuthToken;
use yii\authclient\signature\RsaSha;
use yiiunit\extensions\authclient\TestCase;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;
use yiiunit\extensions\authclient\traits\OAuthDefaultReturnUrlTestTrait;

/**
* @group google
*/
class GoogleTest extends TestCase
class GoogleTest extends BaseOauth2ClientTestCase
{
use OAuthDefaultReturnUrlTestTrait;

protected function setUp()
protected function createClient()
{
$config = [
'components' => [
'request' => [
'hostInfo' => 'http://testdomain.com',
'scriptUrl' => '/index.php',
],
]
];
$this->mockApplication($config, '\yii\web\Application');
return new Google();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_BODY;
}

public function testAuthenticateUserJwt()
Expand All @@ -45,11 +43,6 @@ public function testAuthenticateUserJwt()
$this->assertNotEmpty($token->getToken());
}

protected function createClient()
{
return new Google();
}

/**
* Data provider for [[testDefaultReturnUrl]].
* @return array test data.
Expand Down
25 changes: 25 additions & 0 deletions tests/clients/LinkedInTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\LinkedIn;
use yii\authclient\OAuth2;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;

class LinkedInTest extends BaseOauth2ClientTestCase
{
protected function createClient()
{
return new LinkedIn();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_BODY;
}

protected function getAccessTokenBodyParamName()
{
return 'oauth2_access_token';
}
}
20 changes: 20 additions & 0 deletions tests/clients/LiveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace yiiunit\extensions\authclient\clients;

use yii\authclient\clients\Live;
use yii\authclient\OAuth2;
use yiiunit\extensions\authclient\clients\base\BaseOauth2ClientTestCase;

class LiveTest extends BaseOauth2ClientTestCase
{
protected function createClient()
{
return new Live();
}

protected function getExpectedTokenLocation()
{
return OAuth2::ACCESS_TOKEN_LOCATION_BODY;
}
}
Loading

0 comments on commit b9f753f

Please sign in to comment.