Skip to content

Commit

Permalink
Merge branch 'master' into 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
ramsey committed Feb 28, 2025
2 parents 4f637ec + 9df2924 commit 0b1d176
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 9 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# OAuth 2.0 Client Changelog

## 2.8.1

_Released: 2025-02-26_

* Only provide scopes in access token when set in options [#1053](/~https://github.com/thephpleague/oauth2-client/pull/1053)
* Add missing `@throws` annotations for Guzzle exceptions [#1055](/~https://github.com/thephpleague/oauth2-client/pull/1055)

## 2.8.0

_Released: 2024-12-11_
Expand Down
2 changes: 1 addition & 1 deletion docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ GEM
minitest (5.25.4)
net-http (0.6.0)
uri
nokogiri (1.17.0)
nokogiri (1.18.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
octokit (4.25.1)
Expand Down
1 change: 1 addition & 0 deletions docs/providers/thirdparty.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Gateway | Composer Package | Maintainer
[Dribbble](/~https://github.com/crewlabs/oauth2-dribbble) | crewlabs/oauth2-dribbble | [Crew Labs](https://crew.co/labs)
[Dropbox](/~https://github.com/stevenmaguire/oauth2-dropbox) | stevenmaguire/oauth2-dropbox | [Steven Maguire](/~https://github.com/stevenmaguire)
[Drupal](/~https://github.com/chrishemmings/oauth2-drupal) | chrishemmings/oauth2-drupal | [Chris Hemmings](/~https://github.com/chrishemmings)
[Ebay](/~https://github.com/Gugiman/oauth2-ebay) | gugiman/oauth2-ebay | [Dennis Steffen](/~https://github.com/gugiman)
[Ecwid](/~https://github.com/mugnate/oauth2-ecwid) | mugnate/oauth2-ecwid | [Nikolay Votintsev](/~https://github.com/votintsev)
[Edenred](/~https://github.com/jzecca/oauth2-edenred) | jzecca/oauth2-edenred | [Jérôme Zecca](/~https://github.com/jzecca)
[Elance](/~https://github.com/stevenmaguire/oauth2-elance) | stevenmaguire/oauth2-elance | [Steven Maguire](/~https://github.com/stevenmaguire)
Expand Down
11 changes: 6 additions & 5 deletions src/Provider/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
namespace League\OAuth2\Client\Provider;

use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Grant\GrantFactory;
Expand Down Expand Up @@ -621,16 +622,13 @@ protected function getAccessTokenRequest(array $params): RequestInterface
* @throws ClientExceptionInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/
public function getAccessToken(mixed $grant, array $options = []): AccessTokenInterface
{
$grant = $this->verifyGrant($grant);

if (!isset($options['scope'])) {
$options['scope'] = $this->getDefaultScopes();
}

if (is_array($options['scope'])) {
if (isset($options['scope']) && is_array($options['scope'])) {
$separator = $this->getScopeSeparator();
$options['scope'] = implode($separator, $options['scope']);
}
Expand Down Expand Up @@ -758,6 +756,7 @@ public function getResponse(RequestInterface $request): ResponseInterface
* @throws ClientExceptionInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/
public function getParsedResponse(RequestInterface $request): array
{
Expand Down Expand Up @@ -914,6 +913,7 @@ abstract protected function createResourceOwner(array $response, AccessToken $to
* @throws ClientExceptionInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/
public function getResourceOwner(AccessToken $token): ResourceOwnerInterface
{
Expand All @@ -930,6 +930,7 @@ public function getResourceOwner(AccessToken $token): ResourceOwnerInterface
* @throws ClientExceptionInterface
* @throws IdentityProviderException
* @throws UnexpectedValueException
* @throws GuzzleException
*/
protected function fetchResourceOwnerDetails(AccessToken $token): array
{
Expand Down
3 changes: 1 addition & 2 deletions test/src/Grant/PasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ protected function getParamExpectation(): Closure
return fn (array $body) => isset($body['grant_type'])
&& $body['grant_type'] === 'password'
&& isset($body['username'])
&& isset($body['password'])
&& isset($body['scope']);
&& isset($body['password']);
}

public function testToString(): void
Expand Down
57 changes: 56 additions & 1 deletion test/src/Provider/AbstractProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ public function testGetAccessToken(string $method): void
->once()
->with(
['client_id' => 'mock_client_id', 'client_secret' => 'mock_secret', 'redirect_uri' => 'none'],
['code' => 'mock_authorization_code', 'scope' => 'test'],
['code' => 'mock_authorization_code'],
)
->andReturn([]);

Expand Down Expand Up @@ -755,6 +755,61 @@ public function testGetAccessToken(string $method): void
&& (string) $request->getUri() === $provider->getBaseAccessTokenUrl([]));
}

#[DataProvider('getAccessTokenMethodProvider')]
public function testGetAccessTokenWithScope(string $method): void
{
$provider = $this->getMockProvider();
$provider->setAccessTokenMethod($method);

$rawResponse = ['access_token' => 'okay', 'expires' => time() + 3600, 'resource_owner_id' => 3];

$grant = Mockery::mock(AbstractGrant::class);
$grant
->shouldReceive('prepareRequestParameters')
->once()
->with(
['client_id' => 'mock_client_id', 'client_secret' => 'mock_secret', 'redirect_uri' => 'none'],
['code' => 'mock_authorization_code', 'scope' => 'foo,bar'],
)
->andReturn([]);

$stream = Mockery::mock(StreamInterface::class);
$stream
->shouldReceive('__toString')
->once()
->andReturn(json_encode($rawResponse));

$response = Mockery::mock(ResponseInterface::class);
$response
->shouldReceive('getBody')
->once()
->andReturn($stream);
$response
->shouldReceive('getHeader')
->once()
->with('content-type')
->andReturn(['application/json']);

$client = Mockery::spy(ClientInterface::class, [
'sendRequest' => $response,
]);

$provider->setHttpClient($client);
$token = $provider->getAccessToken($grant, ['code' => 'mock_authorization_code', 'scope' => ['foo', 'bar']]);

$this->assertInstanceOf(ResourceOwnerAccessTokenInterface::class, $token);

$this->assertSame($rawResponse['resource_owner_id'], $token->getResourceOwnerId());
$this->assertSame($rawResponse['access_token'], $token->getToken());
$this->assertSame($rawResponse['expires'], $token->getExpires());

$client
->shouldHaveReceived('sendRequest')
->once()
->withArgs(fn (RequestInterface $request) => $request->getMethod() === $provider->getAccessTokenMethod()
&& (string) $request->getUri() === $provider->getBaseAccessTokenUrl([]));
}

public function testGetAccessTokenWithNonJsonResponse(): void
{
$provider = $this->getMockProvider();
Expand Down

0 comments on commit 0b1d176

Please sign in to comment.