Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oauth2 Oro Provider Laravel Package

diglin/oauth2-oro-provider

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require diglin/oauth2-oro-provider:^1.0
    
  2. Configure the Bundle Add to config/packages/diglin_oauth2_oro.yaml:

    diglin_oauth2_oro:
        api:
            url: "https://your-oro-app.com"  # Required (no trailing slash)
            client_id: "your_client_id"       # Required
            client_secret: "your_secret"     # Required
    
  3. First Use Case: Fetching an Access Token

    use Diglin\OAuth2OroBundle\OAuth2\OroProvider;
    
    $provider = new OroProvider([
        'url' => 'https://your-oro-app.com',
        'client_id' => 'your_client_id',
        'client_secret' => 'your_secret',
    ]);
    
    // For password grant (if enabled on Oro side)
    $token = $provider->getAccessToken('username', 'password', 'password');
    
    // For authorization code grant (redirect flow)
    $authUrl = $provider->getAuthorizationUrl();
    // Redirect user to $authUrl, then handle callback with:
    $token = $provider->getAccessToken('authorization_code', ['code' => $code]);
    

Implementation Patterns

Common Workflows

1. Authorization Code Flow (Recommended for SPAs/Web Apps)

// Step 1: Generate auth URL
$provider = new OroProvider(config());
$authUrl = $provider->getAuthorizationUrl([
    'scope' => ['api', 'read', 'write'], // Customize scopes as needed
]);

// Step 2: Handle callback (e.g., in a Symfony controller)
public function callback(Request $request)
{
    $provider = new OroProvider(config());
    $token = $provider->getAccessToken('authorization_code', [
        'code' => $request->query->get('code'),
    ]);

    // Store token (e.g., in session or database)
    $this->storeToken($token);

    return redirect()->route('dashboard');
}

2. Password Grant (For Server-to-Server or Trusted Clients)

$provider = new OroProvider(config());
$token = $provider->getAccessToken('username', 'password', 'password');

// Use token to fetch API data
$client = $provider->getRegisteredClient();
$response = $client->get('api/rest/v1/users', [
    'headers' => ['Authorization' => 'Bearer ' . $token->getToken()]
]);

3. Refreshing Tokens

$provider = new OroProvider(config());
$newToken = $provider->getAccessToken('refresh_token', [
    'refresh_token' => $storedRefreshToken,
]);

4. Integrating with Symfony’s HTTP Client

use Symfony\Contracts\HttpClient\HttpClientInterface;

public function __construct(HttpClientInterface $client, OroProvider $provider)
{
    $this->client = $client;
    $this->provider = $provider;
}

public function fetchUserData()
{
    $response = $this->client->request('GET', 'https://your-oro-app.com/api/rest/v1/users/me', [
        'auth_bearer' => $this->provider->getLastAccessToken()->getToken(),
    ]);
    return $response->toArray();
}

5. Customizing Scopes

OroPlatform supports custom scopes. Extend the provider to add dynamic scopes:

$provider = new OroProvider(config());
$provider->setScopes(['api', 'custom_scope1', 'custom_scope2']);
$authUrl = $provider->getAuthorizationUrl();

Integration Tips

Leveraging League OAuth2 Client Features

The underlying league/oauth2-client provides additional utilities:

  • Token Storage: Use League\OAuth2\Client\Provider\Token\AccessToken to persist tokens.
  • Token Validation: Validate tokens before use:
    if (!$token->validate()) {
        throw new \RuntimeException('Invalid token');
    }
    
  • Custom Requests: Extend the provider for custom API endpoints:
    $client = $provider->getRegisteredClient();
    $response = $client->post('api/rest/v1/custom-endpoint', [
        'json' => ['data' => 'value'],
        'headers' => ['Authorization' => 'Bearer ' . $token->getToken()]
    ]);
    

Symfony Dependency Injection

Register the provider as a service in services.yaml:

services:
    App\Service\OroAuthService:
        arguments:
            $provider: '@diglin_oauth2_oro.provider'

Then inject it into controllers/services:

use Diglin\OAuth2OroBundle\OAuth2\OroProvider;

class OroAuthService
{
    public function __construct(private OroProvider $provider) {}
}

Gotchas and Tips

Pitfalls

1. Missing Trailing Slash in url Config

  • Issue: OroPlatform’s API endpoints are relative (e.g., /api/rest/v1/users). If the url config has a trailing slash (e.g., https://app.com/), requests will fail.
  • Fix: Ensure url is configured without a trailing slash:
    url: "https://your-oro-app.com"  # Correct
    # url: "https://your-oro-app.com/"  # Incorrect
    

2. Incorrect Grant Type

  • Issue: Using password grant without enabling it on the OroPlatform side or without providing username/password in config.
  • Fix:
    • Ensure password grant is enabled in OroPlatform’s OAuth settings.
    • Provide username and password in config or use authorization_code flow.

3. Scope Mismatches

  • Issue: OroPlatform may reject requests if scopes are not whitelisted or malformed.
  • Fix:
    • Verify scopes in OroPlatform’s API documentation.
    • Use exact scope names (e.g., api instead of API).

4. Token Expiry Handling

  • Issue: Tokens expire, and refresh tokens may not be stored or reused.
  • Fix:
    • Always store the refresh_token alongside the access_token.
    • Implement a refresh logic before making API calls:
      try {
          $token = $this->provider->getLastAccessToken();
          if (!$token->hasExpired()) {
              return $token;
          }
      } catch (\League\OAuth2\Client\Provider\Exception\ExpiredTokenException $e) {
          $token = $this->provider->getAccessToken('refresh_token', [
              'refresh_token' => $storedRefreshToken,
          ]);
      }
      

5. CSRF Token Mismatch (Authorization Code Flow)

  • Issue: OroPlatform may return a CSRF error if the state parameter is not handled.
  • Fix:
    • Generate and validate a state parameter in the authorization flow:
      $state = bin2hex(random_bytes(32));
      $authUrl = $provider->getAuthorizationUrl(['state' => $state]);
      // Store $state in session
      $request->getSession()->set('oauth_state', $state);
      
      // In callback, validate:
      if ($request->query->get('state') !== $request->getSession()->get('oauth_state')) {
          throw new \RuntimeException('CSRF state mismatch');
      }
      

Debugging Tips

1. Enable League OAuth2 Debugging

Add this to your config to log OAuth2 requests/responses:

$provider = new OroProvider(config());
$provider->getRegisteredClient()->setDebug(true);
$provider->getRegisteredClient()->setDebugFile('/tmp/oauth2.log');

2. Validate OroPlatform OAuth Settings

  • Ensure the OAuth Server is enabled in OroPlatform:
    • Go to System > Configuration > API > OAuth Authentication.
    • Verify client_id and client_secret match those in your config.
    • Check Allowed Grant Types (e.g., authorization_code, password).

3. Test with Postman or cURL

Before integrating, test the OAuth flow manually:

curl -X POST "https://your-oro-app.com/oauth/v2/token" \
     -d "grant_type=password&username=test&password=test&client_id=your_id&client_secret=your_secret"

4. Handle OroPlatform-Specific Errors

OroPlatform may return custom error responses. Catch and parse them:

try {
    $token = $provider->getAccessToken('password', ['username' => 'user', 'password' => 'pass']);
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
    $error = json_decode($e->getResponseBody(), true);
    // Handle Oro-specific errors (e.g., $error['error'] === 'invalid_grant')
}

Extension Points

1. Custom Provider Extensions

Extend the provider to add OroPlatform-specific logic:

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime