Skip to content

Commit

Permalink
Merge pull request #242 from Sammyjo20/feature/allow-oauth-requests-t…
Browse files Browse the repository at this point in the history
…o-be-overwritten

Feature | Ability to overwrite OAuth2 request classes
  • Loading branch information
Sammyjo20 authored Jun 23, 2023
2 parents 86ec2f7 + 1ac5ad4 commit 54bfd3c
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 4 deletions.
43 changes: 40 additions & 3 deletions src/Traits/OAuth2/AuthorizationCodeGrant.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
use Saloon\Helpers\Str;
use Saloon\Helpers\Date;
use InvalidArgumentException;
use Saloon\Contracts\Request;
use Saloon\Helpers\URLHelper;
use Saloon\Contracts\Response;
use Saloon\Helpers\OAuth2\OAuthConfig;
use Saloon\Http\OAuth2\GetUserRequest;
use Saloon\Contracts\OAuthAuthenticator;
use Saloon\Exceptions\InvalidStateException;
Expand Down Expand Up @@ -94,7 +96,7 @@ public function getAccessToken(string $code, string $state = null, string $expec
throw new InvalidStateException;
}

$request = new GetAccessTokenRequest($code, $this->oauthConfig());
$request = $this->resolveAccessTokenRequest($code, $this->oauthConfig());

$request = $this->oauthConfig()->invokeRequestModifier($request);

Expand Down Expand Up @@ -139,7 +141,7 @@ public function refreshAccessToken(OAuthAuthenticator|string $refreshToken, bool
$refreshToken = $refreshToken->getRefreshToken();
}

$request = new GetRefreshTokenRequest($this->oauthConfig(), $refreshToken);
$request = $this->resolveRefreshTokenRequest($this->oauthConfig(), $refreshToken);

$request = $this->oauthConfig()->invokeRequestModifier($request);

Expand Down Expand Up @@ -203,7 +205,7 @@ protected function createOAuthAuthenticator(string $accessToken, string $refresh
*/
public function getUser(OAuthAuthenticator $oauthAuthenticator, ?callable $requestModifier = null): Response
{
$request = GetUserRequest::make($this->oauthConfig())->authenticate($oauthAuthenticator);
$request = $this->resolveUserRequest($this->oauthConfig())->authenticate($oauthAuthenticator);

if (is_callable($requestModifier)) {
$requestModifier($request);
Expand All @@ -223,4 +225,39 @@ public function getState(): ?string
{
return $this->state;
}

/**
* Resolve the access token request
*
* @param string $code
* @param OAuthConfig $oauthConfig
* @return Request
*/
protected function resolveAccessTokenRequest(string $code, OAuthConfig $oauthConfig): Request
{
return new GetAccessTokenRequest($code, $oauthConfig);
}

/**
* Resolve the refresh token request
*
* @param OAuthConfig $oauthConfig
* @param string $refreshToken
* @return Request
*/
protected function resolveRefreshTokenRequest(OAuthConfig $oauthConfig, string $refreshToken): Request
{
return new GetRefreshTokenRequest($oauthConfig, $refreshToken);
}

/**
* Resolve the user request
*
* @param OAuthConfig $oauthConfig
* @return Request
*/
protected function resolveUserRequest(OAuthConfig $oauthConfig): Request
{
return new GetUserRequest($oauthConfig);
}
}
17 changes: 16 additions & 1 deletion src/Traits/OAuth2/ClientCredentialsGrant.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use DateTimeImmutable;
use Saloon\Helpers\Date;
use Saloon\Contracts\Request;
use Saloon\Contracts\Response;
use Saloon\Helpers\OAuth2\OAuthConfig;
use Saloon\Contracts\OAuthAuthenticator;
use Saloon\Http\Auth\AccessTokenAuthenticator;
use Saloon\Http\OAuth2\GetClientCredentialsTokenRequest;
Expand Down Expand Up @@ -34,7 +36,7 @@ public function getAccessToken(array $scopes = [], string $scopeSeparator = ' ',
{
$this->oauthConfig()->validate(withRedirectUrl: false);

$request = new GetClientCredentialsTokenRequest($this->oauthConfig(), $scopes, $scopeSeparator);
$request = $this->resolveAccessTokenRequest($this->oauthConfig(), $scopes, $scopeSeparator);

$request = $this->oauthConfig()->invokeRequestModifier($request);

Expand Down Expand Up @@ -80,4 +82,17 @@ protected function createOAuthAuthenticator(string $accessToken, ?DateTimeImmuta
{
return new AccessTokenAuthenticator($accessToken, null, $expiresAt);
}

/**
* Resolve the access token request
*
* @param OAuthConfig $oauthConfig
* @param array $scopes
* @param string $scopeSeparator
* @return Request
*/
protected function resolveAccessTokenRequest(OAuthConfig $oauthConfig, array $scopes = [], string $scopeSeparator = ' '): Request
{
return new GetClientCredentialsTokenRequest($oauthConfig, $scopes, $scopeSeparator);
}
}
27 changes: 27 additions & 0 deletions tests/Feature/Oauth2/AuthCodeFlowConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
use Saloon\Exceptions\OAuthConfigValidationException;
use Saloon\Tests\Fixtures\Connectors\OAuth2Connector;
use Saloon\Tests\Fixtures\Connectors\NoConfigAuthCodeConnector;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomOAuthUserRequest;
use Saloon\Tests\Fixtures\Authenticators\CustomOAuthAuthenticator;
use Saloon\Tests\Fixtures\Connectors\CustomRequestOAuth2Connector;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomAccessTokenRequest;
use Saloon\Tests\Fixtures\Connectors\CustomResponseOAuth2Connector;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomRefreshTokenRequest;

test('you can get the redirect url from a connector', function () {
$connector = new OAuth2Connector;
Expand Down Expand Up @@ -387,3 +391,26 @@

$connector->getAccessToken('code');
});

test('on the connector you can overwrite all the request classes', function () {
$mockClient = new MockClient([
CustomAccessTokenRequest::class => MockResponse::make(['access_token' => 'access', 'refresh_token' => 'refresh', 'expires_in' => 3600], 200),
CustomRefreshTokenRequest::class => MockResponse::make(['access_token' => 'access-new', 'refresh_token' => 'refresh-new', 'expires_in' => 3600]),
CustomOAuthUserRequest::class => MockResponse::make(['user' => 'Sam']),
]);

$connector = new CustomRequestOAuth2Connector;
$connector->withMockClient($mockClient);

$accessTokenResponse = $connector->getAccessToken('code', returnResponse: true);

expect($accessTokenResponse->getRequest())->toBeInstanceOf(CustomAccessTokenRequest::class);

$refreshTokenResponse = $connector->refreshAccessToken('howdy', returnResponse: true);

expect($refreshTokenResponse->getRequest())->toBeInstanceOf(CustomRefreshTokenRequest::class);

$userResponse = $connector->getUser(new AccessTokenAuthenticator('howdy', 'partner'));

expect($userResponse->getRequest())->toBeInstanceOf(CustomOAuthUserRequest::class);
});
15 changes: 15 additions & 0 deletions tests/Feature/Oauth2/ClientCredentialsFlowConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Saloon\Exceptions\OAuthConfigValidationException;
use Saloon\Tests\Fixtures\Connectors\ClientCredentialsConnector;
use Saloon\Tests\Fixtures\Connectors\NoConfigClientCredentialsConnector;
use Saloon\Tests\Fixtures\Connectors\CustomRequestClientCredentialsConnector;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomClientCredentialsAccessTokenRequest;

test('you can get the authenticator from the connector', function () {
$mockClient = new MockClient([
Expand Down Expand Up @@ -181,3 +183,16 @@

$connector->getAccessToken();
});

test('on the connector you can overwrite the getAccessToken request', function () {
$mockClient = new MockClient([
CustomClientCredentialsAccessTokenRequest::class => MockResponse::make(['access_token' => 'access', 'expires_in' => 3600], 200),
]);

$connector = new CustomRequestClientCredentialsConnector();
$connector->withMockClient($mockClient);

$accessTokenResponse = $connector->getAccessToken(returnResponse: true);

expect($accessTokenResponse->getRequest())->toBeInstanceOf(CustomClientCredentialsAccessTokenRequest::class);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Connectors;

use Saloon\Contracts\Request;
use Saloon\Helpers\OAuth2\OAuthConfig;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomClientCredentialsAccessTokenRequest;

class CustomRequestClientCredentialsConnector extends ClientCredentialsConnector

/**
* Resolve the access token request
*
* @param OAuthConfig $oauthConfig
* @param array $scopes
* @param string $scopeSeparator
* @return Request
*/
{
protected function resolveAccessTokenRequest(OAuthConfig $oauthConfig, array $scopes = [], string $scopeSeparator = ' '): Request
{
return new CustomClientCredentialsAccessTokenRequest($oauthConfig, $scopes, $scopeSeparator);
}
}
76 changes: 76 additions & 0 deletions tests/Fixtures/Connectors/CustomRequestOAuth2Connector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Connectors;

use Saloon\Http\Connector;
use Saloon\Contracts\Request;
use Saloon\Helpers\OAuth2\OAuthConfig;
use Saloon\Traits\OAuth2\AuthorizationCodeGrant;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomOAuthUserRequest;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomAccessTokenRequest;
use Saloon\Tests\Fixtures\Requests\OAuth\CustomRefreshTokenRequest;

class CustomRequestOAuth2Connector extends Connector
{
use AuthorizationCodeGrant;

/**
* Define the base URL.
*
* @return string
*/
public function resolveBaseUrl(): string
{
return 'https://oauth.saloon.dev';
}

/**
* Define default Oauth config.
*
* @return OAuthConfig
*/
protected function defaultOauthConfig(): OAuthConfig
{
return OAuthConfig::make()
->setClientId('client-id')
->setClientSecret('client-secret')
->setRedirectUri('https://my-app.saloon.dev/auth/callback');
}

/**
* Resolve the access token request
*
* @param string $code
* @param OAuthConfig $oauthConfig
* @return Request
*/
protected function resolveAccessTokenRequest(string $code, OAuthConfig $oauthConfig): Request
{
return new CustomAccessTokenRequest($code, $oauthConfig);
}

/**
* Resolve the refresh token request
*
* @param OAuthConfig $oauthConfig
* @param string $refreshToken
* @return Request
*/
protected function resolveRefreshTokenRequest(OAuthConfig $oauthConfig, string $refreshToken): Request
{
return new CustomRefreshTokenRequest($oauthConfig, $refreshToken);
}

/**
* Resolve the user request
*
* @param OAuthConfig $oauthConfig
* @return Request
*/
protected function resolveUserRequest(OAuthConfig $oauthConfig): Request
{
return new CustomOAuthUserRequest($oauthConfig);
}
}
12 changes: 12 additions & 0 deletions tests/Fixtures/Requests/OAuth/CustomAccessTokenRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Requests\OAuth;

use Saloon\Http\OAuth2\GetAccessTokenRequest;

class CustomAccessTokenRequest extends GetAccessTokenRequest
{
//
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Requests\OAuth;

use Saloon\Http\OAuth2\GetClientCredentialsTokenRequest;

class CustomClientCredentialsAccessTokenRequest extends GetClientCredentialsTokenRequest
{
//
}
12 changes: 12 additions & 0 deletions tests/Fixtures/Requests/OAuth/CustomOAuthUserRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Requests\OAuth;

use Saloon\Http\OAuth2\GetUserRequest;

class CustomOAuthUserRequest extends GetUserRequest
{
//
}
12 changes: 12 additions & 0 deletions tests/Fixtures/Requests/OAuth/CustomRefreshTokenRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Saloon\Tests\Fixtures\Requests\OAuth;

use Saloon\Http\OAuth2\GetRefreshTokenRequest;

class CustomRefreshTokenRequest extends GetRefreshTokenRequest
{
//
}

0 comments on commit 54bfd3c

Please sign in to comment.