OAuth2ApplicationAbstract

Overview #

OAuth2ApplicationAbstract is the base class for applications using OAuth2 authentication. OAuth2 is a standard protocol for authorization that involves redirecting users to authenticate with a third-party service, then receiving access tokens to make API requests on their behalf.

Purpose:

  • Handle OAuth2 authorization flow (authorization code grant)
  • Manage access tokens and refresh tokens
  • Automatically refresh expired tokens
  • Define OAuth2-specific forms with client ID and secret

File location: orchesty-php-sdk/src/Authorization/Base/OAuth2/OAuth2ApplicationAbstract.php

Developer workflow: Use OAuth2ApplicationAbstract when integrating with services like Google, Facebook, GitHub, Salesforce, or any API that uses OAuth2 for authentication.

Class Hierarchy #

ApplicationAbstract
OAuth2ApplicationAbstract

Implements: OAuth2ApplicationInterface, ApplicationInterface

Constructor #

public function __construct(OAuth2Provider $provider)

Parameters #

ParameterTypeDescription
$providerOAuth2ProviderOAuth2 provider for handling auth flow

Note: The provider is automatically injected by Symfony DI.

Abstract Methods #

You must implement these methods:

getAuthUrl() #

abstract public function getAuthUrl(): string

Returns the OAuth2 authorization endpoint URL.

Returns: string - Authorization URL (e.g., https://accounts.google.com/o/oauth2/v2/auth)

Example:

public function getAuthUrl(): string
{
    return 'https://github.com/login/oauth/authorize';
}

getTokenUrl() #

abstract public function getTokenUrl(): string

Returns the OAuth2 token endpoint URL for exchanging authorization codes for access tokens.

Returns: string - Token URL (e.g., https://oauth2.googleapis.com/token)

Example:

public function getTokenUrl(): string
{
    return 'https://github.com/login/oauth/access_token';
}

Standard Abstract Methods #

You must also implement these from ApplicationInterface:

  • getName() - Application unique key
  • getPublicName() - Display name
  • getDescription() - Application description
  • getFormStack() - Form configuration
  • getRequestDto() - Create authenticated requests

Provided Methods #

authorize() #

public function authorize(ApplicationInstall $applicationInstall): string

Generates the OAuth2 authorization URL to redirect users to.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallInstallation with client credentials

Returns: string - Authorization URL with query parameters

Example:

$authUrl = $application->authorize($applicationInstall);
// Returns: https://github.com/login/oauth/authorize?client_id=...&redirect_uri=...&scope=...

isAuthorized() #

public function isAuthorized(ApplicationInstall $applicationInstall): bool

Checks if the application has a valid access token.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallInstallation to check

Returns: bool - True if access token exists

setAuthorizationToken() #

public function setAuthorizationToken(
    ApplicationInstall $applicationInstall,
    array $token
): OAuth2ApplicationInterface

Exchanges authorization code for access token and saves it.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallInstallation to update
$tokenarrayAuthorization code response

Returns: self - For method chaining

getAccessToken() #

public function getAccessToken(ApplicationInstall $applicationInstall): string

Retrieves the current access token.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallInstallation with token

Returns: string - Access token

Throws: ApplicationInstallException - If no access token exists

refreshAuthorization() #

public function refreshAuthorization(ApplicationInstall $applicationInstall): ApplicationInstall

Refreshes the access token using the refresh token.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallInstallation to refresh

Returns: ApplicationInstall - Updated installation with new token

Throws:

  • AuthorizationException - If refresh fails
  • DateTimeException - If date parsing fails

Protected Methods #

getScopes() #

protected function getScopes(ApplicationInstall $applicationInstall): array

Override this to define OAuth2 scopes your application needs.

Parameters:

ParameterTypeDescription
$applicationInstallApplicationInstallCurrent installation

Returns: array - List of scope strings

Example:

protected function getScopes(ApplicationInstall $applicationInstall): array
{
    return ['user:email', 'repo', 'workflow'];
}

Constants #

protected const string SCOPE_SEPARATOR = ScopeFormatter::COMMA;
protected const array CREDENTIALS = [
    OAuth2ApplicationInterface::CLIENT_ID,
    OAuth2ApplicationInterface::CLIENT_SECRET,
];

Usage Examples #

Complete OAuth2 Application (GitHub Example) #

<?php declare(strict_types=1);

namespace YourApp\Application;

use Hanaboso\CommonsBundle\Process\ProcessDtoAbstract;
use Hanaboso\CommonsBundle\Transport\Curl\Dto\RequestDto;
use Hanaboso\PipesPhpSdk\Application\Base\ApplicationInterface;
use Hanaboso\PipesPhpSdk\Application\Document\ApplicationInstall;
use Hanaboso\PipesPhpSdk\Application\Model\Form\Field;
use Hanaboso\PipesPhpSdk\Application\Model\Form\Form;
use Hanaboso\PipesPhpSdk\Application\Model\Form\FormStack;
use Hanaboso\PipesPhpSdk\Authorization\Base\OAuth2\OAuth2ApplicationAbstract;
use Hanaboso\PipesPhpSdk\Authorization\Base\OAuth2\OAuth2ApplicationInterface;

final class GitHubApplication extends OAuth2ApplicationAbstract
{
    public function getName(): string
    {
        return 'github';
    }

    public function getPublicName(): string
    {
        return 'GitHub';
    }

    public function getDescription(): string
    {
        return 'Platform for version control and collaboration';
    }

    public function getAuthUrl(): string
    {
        return 'https://github.com/login/oauth/authorize';
    }

    public function getTokenUrl(): string
    {
        return 'https://github.com/login/oauth/access_token';
    }

    protected function getScopes(ApplicationInstall $applicationInstall): array
    {
        return ['user:email', 'repo'];
    }

    public function getFormStack(): FormStack
    {
        $form = new Form(ApplicationInterface::AUTHORIZATION_FORM, 'OAuth2 Credentials');
        $form
            ->addField(
                new Field(
                    Field::TEXT,
                    OAuth2ApplicationInterface::CLIENT_ID,
                    'Client ID',
                    null,
                    true
                )
            )
            ->addField(
                new Field(
                    Field::TEXT,
                    OAuth2ApplicationInterface::CLIENT_SECRET,
                    'Client Secret',
                    null,
                    true
                )
            );

        $formStack = new FormStack();
        return $formStack->addForm($form);
    }

    public function getRequestDto(
        ProcessDtoAbstract $dto,
        ApplicationInstall $applicationInstall,
        string $method,
        ?string $url = null,
        ?string $data = null
    ): RequestDto
    {
        // Get access token
        $accessToken = $this->getAccessToken($applicationInstall);

        // Create request with OAuth2 bearer token
        $request = new RequestDto($this->getUri($url), $method, $dto);
        $request->setHeaders([
            'Authorization' => sprintf('Bearer %s', $accessToken),
            'Accept' => 'application/vnd.github.v3+json',
            'Content-Type' => 'application/json',
        ]);

        if ($data) {
            $request->setBody($data);
        }

        return $request;
    }
}

Using OAuth2 Application in a Connector #

<?php declare(strict_types=1);

namespace YourApp\Connector;

use Hanaboso\CommonsBundle\Process\ProcessDto;
use Hanaboso\PipesPhpSdk\Connector\ConnectorAbstract;

final class GitHubGetReposConnector extends ConnectorAbstract
{
    public function getName(): string
    {
        return 'github-get-repos';
    }

    public function processAction(ProcessDto $dto): ProcessDto
    {
        $app = $this->getApplication();
        $appInstall = $this->getApplicationInstallFromProcess($dto);

        // Check if authorized
        if (!$app->isAuthorized($appInstall)) {
            $dto->setStopProcess(
                ProcessDto::STOP_AND_FAILED,
                'GitHub application not authorized'
            );
            return $dto;
        }

        // Check if token needs refresh (optional)
        $expires = $appInstall->getExpires();
        if ($expires && $expires < new \DateTime()) {
            $appInstall = $app->refreshAuthorization($appInstall);
            // Save refreshed installation
        }

        // Create authenticated request
        $request = $app->getRequestDto(
            $dto,
            $appInstall,
            'GET',
            '/user/repos'
        );

        // Send request
        $response = $this->getSender()->send($request);
        $this->evaluateStatusCode($response->getStatusCode(), $dto);

        $dto->setData($response->getBody());

        return $dto;
    }
}

OAuth2 Authorization Flow Handler #

<?php declare(strict_types=1);

namespace YourApp\Controller;

use Hanaboso\PipesPhpSdk\Application\Manager\ApplicationManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class OAuth2Controller
{
    public function __construct(
        private ApplicationManager $manager
    ) {}

    /**
     * Step 1: Redirect user to OAuth2 provider
     */
    public function authorize(Request $request): Response
    {
        $appKey = $request->get('app');
        $userId = $request->get('user');

        // Get application and installation
        $application = $this->manager->getApplication($appKey);
        $appInstall = $this->manager->getApplicationInstall($appKey, $userId);

        // Generate authorization URL
        $authUrl = $application->authorize($appInstall);

        // Redirect user to provider
        return new Response('', 302, ['Location' => $authUrl]);
    }

    /**
     * Step 2: Handle OAuth2 callback
     */
    public function callback(Request $request): Response
    {
        $code = $request->get('code');
        $state = $request->get('state'); // Contains app key and user ID

        // Exchange code for token
        $application = $this->manager->getApplication($appKey);
        $appInstall = $this->manager->getApplicationInstall($appKey, $userId);

        $application->setAuthorizationToken($appInstall, ['code' => $code]);

        // Save installation with token
        $this->manager->saveApplicationInstall($appInstall);

        return new Response('Authorization successful!');
    }
}

OAuth2 Flow #

The OAuth2 authorization flow:

  1. User initiates: User clicks "Connect" in UI
  2. Generate auth URL: Call authorize() to get authorization URL
  3. Redirect user: Redirect user to OAuth2 provider
  4. User authorizes: User logs in and grants permissions
  5. Callback: Provider redirects back with authorization code
  6. Exchange code: Call setAuthorizationToken() to exchange code for access token
  7. Store token: Token is saved to ApplicationInstall
  8. Make requests: Use getRequestDto() to create authenticated requests
  9. Refresh: Call refreshAuthorization() when token expires

Service Registration #

# config/services.yaml
services:
    hbpf.application.github:
        class: YourApp\Application\GitHubApplication
        arguments:
            - '@hbpf.authorization.oauth2.provider'
        tags: ['hbpf.application']

Notes #

  • Token Management: Access tokens are automatically stored in ApplicationInstall settings
  • Token Refresh: Implement refresh logic in connectors if provider supports refresh tokens
  • Scopes: Define required scopes in getScopes() method
  • Redirect URL: The redirect URL is automatically added to forms and managed by OAuth2Provider
  • State Parameter: Used for security and to track user/app during OAuth flow
  • Expiration: Token expiration is stored in ApplicationInstall->expires

See Also #

Next Steps:

  1. For OAuth1, see OAuth1ApplicationAbstract
  2. Learn about FormStack for complex forms
  3. Build connectors with ConnectorAbstract
© 2025 Orchesty Solutions. All rights reserved.