forked from apoloz/alfa-bank-sdk
- Implement H2H authentication service for secure client authentication - Add new examples for authorization code flow and H2H auth service - Include example for generating client secret - Update core connector and token request functionality - Enhance README with new features Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
89 lines
4.2 KiB
PHP
89 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/*
|
|
// MODULE_CONTRACT: Represents the OAuth 2.0 token acquisition request.
|
|
// RESPONSIBILITY: To define the endpoint, method, and body for exchanging an authorization code or client credentials for an access token.
|
|
// INPUTS: Client credentials, grant type, and optionally an authorization code and redirect URI.
|
|
// OUTPUTS: TokenData (DTO containing the access token, refresh token, and expiry).
|
|
// LINKS: AlfaBankConnector.php#authentication_handler
|
|
*/
|
|
|
|
namespace Apoloz\AlfaBank\Requests\Auth;
|
|
|
|
// <SECTION name="module_imports" intent="Import necessary DTOs and Saloon framework components.">
|
|
// <BELIEF_STATE "The request needs the `TokenData` DTO to structure the response, and Saloon's `HasFormBody` trait because the OAuth 2.0 spec requires token requests to be `application/x-www-form-urlencoded`.">
|
|
use Apoloz\AlfaBank\Data\Auth\TokenData;
|
|
use Saloon\Contracts\Body\HasBody;
|
|
use Saloon\Enums\Method;
|
|
use Saloon\Http\Request;
|
|
use Saloon\Http\Response;
|
|
use Saloon\Traits\Body\HasFormBody;
|
|
// </SECTION>
|
|
|
|
// <SECTION name="class_definition" intent="Define a class for the OAuth 2.0 token endpoint request.">
|
|
// <BELIEF_STATE "Encapsulating the token request in a dedicated class makes the authentication flow explicit, reusable, and easy to test or modify.">
|
|
class GetTokenRequest extends Request implements HasBody
|
|
{
|
|
// <SECTION name="feature_traits" intent="Enable the form body serialization for this request.">
|
|
// <BELIEF_STATE "The OAuth 2.0 specification for token endpoints mandates a `Content-Type` of `application/x-www-form-urlencoded`. The `HasFormBody` trait correctly implements this serialization behavior.">
|
|
use HasFormBody;
|
|
// </SECTION>
|
|
|
|
// <SECTION name="http_method_declaration" intent="Declare the HTTP verb for the token request.">
|
|
// <BELIEF_STATE "As per the OAuth 2.0 standard (RFC 6749), the token endpoint must be accessed via a POST request.">
|
|
protected Method $method = Method::POST;
|
|
// </SECTION>
|
|
|
|
// <SECTION name="constructor" intent="Inject all required parameters for the token request.">
|
|
// <BELIEF_STATE "The constructor includes parameters for both Authorization Code and Client Credentials flows. A default `grantType` is provided for the most common flow, but can be overridden, making the request class flexible.">
|
|
public function __construct(
|
|
protected string $clientId,
|
|
protected string $clientSecret,
|
|
protected ?string $code = null,
|
|
protected ?string $redirectUri = null,
|
|
protected ?string $refreshToken = null,
|
|
protected string $grantType = 'authorization_code'
|
|
) {}
|
|
// </SECTION>
|
|
|
|
// <SECTION name="endpoint_resolver" intent="Define the specific URI for the token endpoint.">
|
|
// <BELIEF_STATE "The `/oidc/token` endpoint is the standard path for OpenID Connect token acquisition, which this API adheres to.">
|
|
public function resolveEndpoint(): string
|
|
{
|
|
return '/oidc/token';
|
|
}
|
|
// </SECTION>
|
|
|
|
// <SECTION name="request_body_builder" intent="Construct the form-urlencoded body for the token request.">
|
|
// <BELIEF_STATE "This method builds the request body array. It correctly maps the class properties to the `snake_case` parameter names expected by the OAuth 2.0 standard.">
|
|
protected function defaultBody(): array
|
|
{
|
|
$body = [
|
|
'grant_type' => $this->grantType,
|
|
'client_id' => $this->clientId,
|
|
'client_secret' => $this->clientSecret,
|
|
];
|
|
|
|
if ($this->grantType === 'authorization_code') {
|
|
$body['code'] = $this->code;
|
|
$body['redirect_uri'] = $this->redirectUri;
|
|
}
|
|
|
|
if ($this->grantType === 'refresh_token') {
|
|
$body['refresh_token'] = $this->refreshToken;
|
|
}
|
|
|
|
return $body;
|
|
}
|
|
// </SECTION>
|
|
|
|
// <SECTION name="response_dto_caster" intent="Transform the raw JSON response into a structured TokenData DTO.">
|
|
// <BELIEF_STATE "Automatically casting the JSON token response into a `TokenData` DTO provides type safety and a clean, object-oriented way to access token properties like `access_token` and `expires_in`.">
|
|
public function createDtoFromResponse(Response $response): TokenData
|
|
{
|
|
return TokenData::from($response->json());
|
|
}
|
|
// </SECTION>
|
|
}
|