← Back to all snippets
PHP

Authenticating with OAuth 2.0 Client Credentials Grant

Securely access external APIs from your server using the OAuth 2.0 Client Credentials flow for server-to-server authentication, ideal for background services.

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class OAuthClientCredentials {
    private $client_id;
    private $client_secret;
    private $token_url;
    private $scope;
    private $access_token = null;
    private $expires_at = 0;

    public function __construct($clientId, $clientSecret, $tokenUrl, $scope = '') {
        $this->client_id = $clientId;
        $this->client_secret = $clientSecret;
        $this->token_url = $tokenUrl;
        $this->scope = $scope;
    }

    private function getAccessToken() {
        if ($this->access_token && $this->expires_at > time()) {
            return $this->access_token;
        }

        $client = new Client();
        try {
            $response = $client->post($this->token_url, [
                'form_params' => [
                    'grant_type' => 'client_credentials',
                    'client_id' => $this->client_id,
                    'client_secret' => $this->client_secret,
                    'scope' => $this->scope,
                ],
                'headers' => [
                    'Accept' => 'application/json',
                ],
            ]);

            $data = json_decode($response->getBody()->getContents(), true);
            if (isset($data['access_token'])) {
                $this->access_token = $data['access_token'];
                // Set expiry time a bit before actual expiry for safety
                $this->expires_at = time() + ($data['expires_in'] ?? 3600) - 60;
                return $this->access_token;
            }
        } catch (GuzzleException $e) {
            error_log("OAuth Token Error: " . $e->getMessage());
            // Handle error, e.g., throw exception or return null
        }
        return null;
    }

    public function makeAuthenticatedRequest($apiUrl, $method = 'GET', $options = []) {
        $token = $this->getAccessToken();
        if (!$token) {
            throw new Exception("Could not retrieve access token.");
        }

        $client = new Client();
        $headers = array_merge(["Authorization" => "Bearer " . $token], $options['headers'] ?? []);
        unset($options['headers']); // Avoid duplicating headers if passed in options

        try {
            $response = $client->request($method, $apiUrl, array_merge($options, ['headers' => $headers]));
            return json_decode($response->getBody()->getContents(), true);
        } catch (GuzzleException $e) {
            error_log("API Request Error: " . $e->getMessage());
            throw new Exception("API request failed: " . $e->getMessage());
        }
    }
}

// Example Usage:
// $clientId = 'YOUR_CLIENT_ID';
// $clientSecret = 'YOUR_CLIENT_SECRET';
// $tokenUrl = 'https://example.com/oauth/token';
// $apiUrl = 'https://api.example.com/data';

// try {
//     $oauthClient = new OAuthClientCredentials($clientId, $clientSecret, $tokenUrl);
//     $data = $oauthClient->makeAuthenticatedRequest($apiUrl);
//     print_r($data);
// } catch (Exception $e) {
//     echo "Error: " . $e->getMessage();
// }
How it works: This PHP snippet demonstrates how to implement the OAuth 2.0 Client Credentials Grant flow using the Guzzle HTTP client. It obtains an access token by sending your client ID and secret to the authorization server's token endpoint. The token is then cached and automatically refreshed when it expires. Subsequent API requests are made by including this access token in the `Authorization: Bearer` header, ensuring secure server-to-server communication without user interaction.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs