PHP Logoleague/oauth2-client

The `league/oauth2-client` is a robust and flexible PHP client library designed for interacting with OAuth 2.0 service providers. Developed by The League of Extraordinary Packages, it aims to standardize the process of consuming various OAuth 2.0 APIs, making it significantly easier for developers to integrate with services like Google, Facebook, GitHub, LinkedIn, and many more.

Key Features and Benefits:
* Standardized Interface: Provides a common API for interacting with different OAuth 2.0 providers, which greatly reduces the learning curve when integrating with multiple services.
* Provider Agnostic: While the library includes several official providers (e.g., Google, Facebook, GitHub), its extensible architecture allows for the easy creation of custom providers for any OAuth 2.0 service.
* Support for OAuth 2.0 Grant Types: Primarily focuses on the Authorization Code Grant flow, which is common for web applications, and also facilitates the use of Refresh Tokens for long-lived access.
* State Parameter Management: Automatically generates and validates the `state` parameter, a crucial security feature that helps prevent Cross-Site Request Forgery (CSRF) attacks.
* Resource Owner Details: After successfully obtaining an access token, the library simplifies fetching details about the resource owner (i.e., the user) from the provider's API.
* Refresh Token Handling: Streamlines the process of refreshing expired access tokens, allowing applications to maintain access to resources without requiring the user to re-authorize.
* Extensible: Built with extensibility in mind, allowing developers to extend existing providers or create entirely new ones to fit specific requirements.

How it Works (Authorization Code Grant Flow):
The typical flow when using `league/oauth2-client` for the Authorization Code Grant involves several steps:
1. Instantiation: You create an instance of a specific `Provider` class (e.g., `League\OAuth2\Client\Provider\Google` or `League\OAuth2\Client\Provider\GenericProvider`) by providing your client ID, client secret, and the registered redirect URI.
2. Authorization Request: Your application generates an authorization URL using the provider instance's `getAuthorizationUrl()` method. This URL includes necessary parameters such as `client_id`, `redirect_uri`, `scope` (permissions requested), and a unique `state` parameter generated by the library.
3. User Redirection: Your application then redirects the user's browser to this authorization URL on the OAuth 2.0 provider's server.
4. User Consent: The user interacts with the provider (logging in if necessary) and decides whether to grant your application the requested permissions to access their data.
5. Callback (Redirect Back): If the user grants permission, the provider redirects the user's browser back to your pre-registered `redirect_uri`. This callback URL will contain an authorization `code` and the `state` parameter in its query string.
6. Code Exchange: Upon receiving the callback, your application first validates the `state` parameter against the one stored in the user's session (which was set in step 2). If the state is valid, it then exchanges this authorization `code` for an `access token` with the OAuth 2.0 provider using the provider's `getAccessToken()` method.
7. Resource Access: With the `access token` now in hand, your application can make authenticated requests to the provider's API on behalf of the user. It can also fetch details about the resource owner (e.g., name, email) using the `getResourceOwner()` method.
8. Token Refresh (Optional): If the access token has an expiration time and the provider issues a `refresh token`, you can use this `refresh token` to obtain a new access token when the current one expires, without requiring the user to re-authorize.

This library significantly simplifies the complex interactions involved in OAuth 2.0, providing a clean, consistent, and secure API for integrating various services into your PHP applications.

Example Code

```php
<?php

require __DIR__ . '/vendor/autoload.php';

session_start();

use League\OAuth2\Client\Provider\Google;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;

// --- Configuration ---
// IMPORTANT: Replace these with your actual credentials obtained from the Google API Console.
// Make sure to register 'http://localhost:8000/oauth_callback.php' (or your actual URL)
// as an authorized redirect URI in your Google API project.
$clientId     = 'YOUR_GOOGLE_CLIENT_ID';
$clientSecret = 'YOUR_GOOGLE_CLIENT_SECRET';
$redirectUri  = 'http://localhost:8000/oauth_callback.php'; // Example local development URI

// --- Instantiate the Provider ---
// This example uses the Google provider. For other providers, use their specific classes
// or the GenericProvider for custom OAuth 2.0 services.
$provider = new Google([
    'clientId'     => $clientId,
    'clientSecret' => $clientSecret,
    'redirectUri'  => $redirectUri,
]);

// --- OAuth 2.0 Flow Logic ---
if (!isset($_GET['code'])) {
    // Phase 1: No authorization code received yet, so initiate the authorization request.
    // This block runs when the user first visits this script.

    // Generate the authorization URL and a unique state parameter to prevent CSRF.
    $authUrl = $provider->getAuthorizationUrl([
        'scope' => [
            'https://www.googleapis.com/auth/userinfo.email',
            'https://www.googleapis.com/auth/userinfo.profile'
        ]
    ]);

    // Store the state parameter in the session for later validation when the provider redirects back.
    $_SESSION['oauth2state'] = $provider->getState();

    // Redirect the user's browser to the OAuth 2.0 provider for authorization.
    header('Location: ' . $authUrl);
    exit;

} elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) {
    // Phase 2: Callback from provider, but the state parameter is missing or doesn't match.
    // This indicates a potential CSRF attack or an invalid request.

    if (isset($_SESSION['oauth2state'])) {
        unset($_SESSION['oauth2state']); // Clear the stored state to prevent replay attacks.
    }
    exit('Invalid state parameter. Possible CSRF attack detected.');

} else {
    // Phase 3: Valid callback from provider with an authorization code and matching state.
    // This block runs after the user has authorized your application on the provider's site.

    try {
        // Try to exchange the authorization code for an access token.
        $accessToken = $provider->getAccessToken('authorization_code', [
            'code' => $_GET['code']
        ]);

        // --- Success: Access Token Obtained ---
        echo '<h2>OAuth 2.0 Authorization Successful!</h2>';
        echo '<h3>Access Token Details:</h3>';
        echo '<ul>';
        echo '<li>Access Token: <code>' . htmlspecialchars($accessToken->getToken()) . '</code></li>';
        if ($accessToken->getRefreshToken()) {
            echo '<li>Refresh Token: <code>' . htmlspecialchars($accessToken->getRefreshToken()) . '</code></li>';
        }
        echo '<li>Expires In: ' . htmlspecialchars($accessToken->getExpires()) . ' seconds (approx. ' . date('Y-m-d H:i:s', $accessToken->getExpires()) . ')</li>';
        echo '<li>Resource Owner ID: ' . htmlspecialchars($accessToken->getResourceOwnerId()) . '</li>';
        echo '</ul>';

        // --- Fetch User Details (Resource Owner) ---
        // Use the obtained access token to get information about the authenticated user.
        $resourceOwner = $provider->getResourceOwner($accessToken);

        echo '<h3>Resource Owner Details:</h3>';
        echo '<ul>';
        echo '<li>Name: ' . htmlspecialchars($resourceOwner->getName()) . '</li>';
        echo '<li>Email: ' . htmlspecialchars($resourceOwner->getEmail()) . '</li>';
        echo '<li>Google ID: ' . htmlspecialchars($resourceOwner->getId()) . '</li>';
        // You can access other details available in the raw response as well:
        // echo '<li>Raw Data: <pre>' . htmlspecialchars(print_r($resourceOwner->toArray(), true)) . '</pre></li>';
        echo '</ul>';

        echo '<p>You have successfully authenticated with Google. You can now use the <strong>Access Token</strong> to make API calls on behalf of the user.</p>';
        echo '<p>Remember to store the <strong>Refresh Token</strong> (if available) securely in a database to obtain new access tokens when the current one expires, without requiring user re-authorization.</p>';

    } catch (IdentityProviderException $e) {
        // --- Error: Failed to get access token or user details ---
        exit('<h3>OAuth Error:</h3><p>' . htmlspecialchars($e->getMessage()) . '</p><p>Please check your client ID, client secret, redirect URI, and network connection.</p>');
    }
}

// --- How to run this example ---
// 1. Install Composer: https://getcomposer.org/
// 2. Open your terminal in the project directory and run:
//    composer require league/oauth2-client google/oauth2-google
// 3. Create a project in Google API Console (console.developers.google.com).
// 4. Enable the 'Google People API'.
// 5. Go to 'Credentials', create 'OAuth client ID' for 'Web application'.
// 6. Set 'Authorized redirect URIs' to 'http://localhost:8000/oauth_callback.php' (or your actual URL).
// 7. Get your Client ID and Client Secret and replace the placeholders above.
// 8. Save this code as 'oauth_callback.php' (or any other name matching your redirect URI).
// 9. Serve the directory using PHP's built-in web server: `php -S localhost:8000`
// 10. Open your browser and navigate to `http://localhost:8000/oauth_callback.php`

?>
```