feat: update authentication flow and OAuth2 implementation
- Refactor AlfaBankConnector to use Saloon's OAuth2 traits - Update authentication methods to use new OAuth2 implementation - Add tests for authorization URL generation, token exchange, and refresh - Replace custom GetTokenRequest with Saloon's built-in OAuth2 requests Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -101,24 +101,28 @@ class AlfaBankConnector extends Connector implements HasPagination, OAuth2Api
|
||||
// login() kept for ClientCredentials compatibility (legacy/simple flow)
|
||||
public function login(?string $clientId = null, ?string $clientSecret = null): static
|
||||
{
|
||||
// Allow overriding config via method arguments
|
||||
$clientId = $clientId ?? $this->alfaConfig->clientId;
|
||||
$clientSecret = $clientSecret ?? $this->alfaConfig->clientSecret;
|
||||
$oauthConfig = $this->oauthConfig();
|
||||
|
||||
if (!$clientId || !$clientSecret) {
|
||||
// Allow overriding credentials via method arguments
|
||||
if ($clientId) {
|
||||
$oauthConfig->setClientId($clientId);
|
||||
}
|
||||
if ($clientSecret) {
|
||||
$oauthConfig->setClientSecret($clientSecret);
|
||||
}
|
||||
|
||||
if (empty($oauthConfig->getClientId()) || empty($oauthConfig->getClientSecret())) {
|
||||
throw new \RuntimeException("Client ID/Secret not configured.");
|
||||
}
|
||||
|
||||
$request = new GetTokenRequest(
|
||||
clientId: $clientId,
|
||||
clientSecret: $clientSecret,
|
||||
grantType: 'client_credentials'
|
||||
);
|
||||
$request = new \Saloon\Http\OAuth2\GetClientCredentialsTokenRequest($oauthConfig);
|
||||
|
||||
$response = $this->send($request);
|
||||
$data = $response->dto();
|
||||
|
||||
// Use the trait's helper to parse the token
|
||||
$authenticator = $this->createOAuthAuthenticatorFromResponse($response);
|
||||
|
||||
$this->authenticate(new \Saloon\Http\Auth\TokenAuthenticator($data->access_token));
|
||||
$this->authenticate($authenticator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -2,53 +2,104 @@
|
||||
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Core\AlfaConfig;
|
||||
use Apoloz\AlfaBank\Requests\Auth\GetTokenRequest;
|
||||
use Saloon\Http\Faking\MockResponse;
|
||||
use Saloon\Http\OAuth2\GetAccessTokenRequest;
|
||||
use Saloon\Http\OAuth2\GetRefreshTokenRequest;
|
||||
|
||||
test('can authenticate and get token', function () {
|
||||
$mockClient = new \Saloon\Http\Faking\MockClient([
|
||||
GetTokenRequest::class => MockResponse::make([
|
||||
'access_token' => 'test-access-token',
|
||||
'refresh_token' => 'test-refresh-token',
|
||||
'expires_in' => 3600,
|
||||
'token_type' => 'Bearer',
|
||||
], 200),
|
||||
]);
|
||||
|
||||
test('can generate authorization url', function () {
|
||||
$config = new AlfaConfig(
|
||||
baseUrl: 'https://test.com',
|
||||
certificatePath: __DIR__ . '/../../test_key.pem', // Use any existing file
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem'
|
||||
);
|
||||
$connector = new AlfaBankConnector($config);
|
||||
$connector->withMockClient($mockClient);
|
||||
|
||||
$request = new GetTokenRequest('client-id', 'client-secret', null, null, 'client_credentials');
|
||||
$response = $connector->send($request);
|
||||
|
||||
expect($response->status())->toBe(200)
|
||||
->and($response->dto()->access_token)->toBe('test-access-token');
|
||||
});
|
||||
|
||||
test('can login and set token', function () {
|
||||
$mockClient = new \Saloon\Http\Faking\MockClient([
|
||||
GetTokenRequest::class => MockResponse::make([
|
||||
'access_token' => 'test-access-token',
|
||||
'refresh_token' => 'test-refresh-token',
|
||||
'expires_in' => 3600,
|
||||
'token_type' => 'Bearer',
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$config = new AlfaConfig(
|
||||
baseUrl: 'https://test.com',
|
||||
baseUrl: 'https://sandbox.alfabank.ru',
|
||||
certificatePath: __DIR__ . '/../../test_key.pem',
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem'
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem',
|
||||
clientId: 'test-client-id',
|
||||
clientSecret: 'test-client-secret',
|
||||
redirectUri: 'https://callback.url'
|
||||
);
|
||||
$connector = new AlfaBankConnector($config);
|
||||
|
||||
$url = $connector->getAuthorizationUrl(['beneficiaries']);
|
||||
|
||||
expect($url)->toContain('https://id-sandbox.alfabank.ru/oidc/authorize')
|
||||
->toContain('client_id=test-client-id')
|
||||
->toContain('redirect_uri=' . urlencode('https://callback.url'))
|
||||
->toContain('scope=beneficiaries');
|
||||
});
|
||||
|
||||
test('can exchange code for token', function () {
|
||||
$mockClient = new \Saloon\Http\Faking\MockClient([
|
||||
GetAccessTokenRequest::class => MockResponse::make([
|
||||
'access_token' => 'new-access-token',
|
||||
'refresh_token' => 'new-refresh-token',
|
||||
'expires_in' => 3600,
|
||||
'token_type' => 'Bearer',
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$config = new AlfaConfig(
|
||||
baseUrl: 'https://sandbox.alfabank.ru',
|
||||
certificatePath: __DIR__ . '/../../test_key.pem',
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem',
|
||||
clientId: 'test-client-id',
|
||||
clientSecret: 'test-client-secret',
|
||||
redirectUri: 'https://callback.url'
|
||||
);
|
||||
$connector = new AlfaBankConnector($config);
|
||||
$connector->withMockClient($mockClient);
|
||||
|
||||
$connector->login('client-id', 'client-secret');
|
||||
$authenticator = $connector->getAccessToken('auth-code-123');
|
||||
|
||||
expect($connector->getAuthenticator())->not->toBeNull();
|
||||
expect($authenticator->getAccessToken())->toBe('new-access-token')
|
||||
->and($authenticator->getRefreshToken())->toBe('new-refresh-token');
|
||||
});
|
||||
|
||||
test('can refresh token', function () {
|
||||
$mockClient = new \Saloon\Http\Faking\MockClient([
|
||||
GetRefreshTokenRequest::class => MockResponse::make([
|
||||
'access_token' => 'refreshed-access-token',
|
||||
'refresh_token' => 'refreshed-refresh-token',
|
||||
'expires_in' => 3600,
|
||||
'token_type' => 'Bearer',
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$config = new AlfaConfig(
|
||||
baseUrl: 'https://sandbox.alfabank.ru',
|
||||
certificatePath: __DIR__ . '/../../test_key.pem',
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem',
|
||||
clientId: 'test-client-id',
|
||||
clientSecret: 'test-client-secret'
|
||||
);
|
||||
$connector = new AlfaBankConnector($config);
|
||||
$connector->withMockClient($mockClient);
|
||||
|
||||
$authenticator = $connector->refreshAccessToken('old-refresh-token');
|
||||
|
||||
expect($authenticator->getAccessToken())->toBe('refreshed-access-token')
|
||||
->and($authenticator->getRefreshToken())->toBe('refreshed-refresh-token');
|
||||
});
|
||||
|
||||
test('can login with client credentials', function () {
|
||||
$mockClient = new \Saloon\Http\Faking\MockClient([
|
||||
\Saloon\Http\OAuth2\GetClientCredentialsTokenRequest::class => MockResponse::make([
|
||||
'access_token' => 'cc-access-token',
|
||||
'expires_in' => 3600,
|
||||
'token_type' => 'Bearer',
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$config = new AlfaConfig(
|
||||
baseUrl: 'https://sandbox.alfabank.ru',
|
||||
certificatePath: __DIR__ . '/../../test_key.pem',
|
||||
privateKeyPath: __DIR__ . '/../../test_key.pem',
|
||||
clientId: 'test-client-id',
|
||||
clientSecret: 'test-client-secret'
|
||||
);
|
||||
$connector = new AlfaBankConnector($config);
|
||||
$connector->withMockClient($mockClient);
|
||||
|
||||
$connector->login();
|
||||
|
||||
expect($connector->getAuthenticator())->not->toBeNull()
|
||||
->and($connector->getAuthenticator()->getAccessToken())->toBe('cc-access-token');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user