Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ env:
CLIENT_ID: '${{ secrets.CLIENT_ID }}'
CLIENT_SECRET: '${{ secrets.CLIENT_SECRET }}'
REFRESH_TOKEN: '${{ secrets.REFRESH_TOKEN }}'
SERVICE_ACCOUNT_JSON: '${{ secrets.SERVICE_ACCOUNT_JSON }}'
jobs:
tests:
runs-on: ubuntu-latest
Expand All @@ -31,4 +32,5 @@ jobs:
-e CLIENT_ID \
-e CLIENT_SECRET \
-e REFRESH_TOKEN \
${{env.APP_IMAGE}} composer ci
-e SERVICE_ACCOUNT_JSON \
${{env.APP_IMAGE}} composer ci
182 changes: 179 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,183 @@
# Keboola Google API Client
# Keboola Google Client Bundle

Basic client for Google APIs
Keboola Google API Client with OAuth 2.0 and Service Account authentication support.

## Installation

```bash
composer require keboola/google-client-bundle
```

## Usage

This library supports two types of authentication:

1. **OAuth 2.0** - for applications that need access to user data
2. **Service Account** - for server-to-server communication without user intervention

### OAuth 2.0 Authentication

#### Classic approach

```php
use Keboola\Google\ClientBundle\Google\RestApi;

$api = new RestApi($logger); // Optional logger parameter
$api->setAppCredentials($clientId, $clientSecret);
$api->setCredentials($accessToken, $refreshToken);

// Get authorization URL
$authUrl = $api->getAuthorizationUrl(
'http://localhost/callback',
'https://www.googleapis.com/auth/drive.readonly',
'force',
'offline'
);

// Authorize using code
$tokens = $api->authorize($code, 'http://localhost/callback');

// API calls
$response = $api->request('/drive/v2/files');
```

#### New factory approach

```php
use Keboola\Google\ClientBundle\Google\RestApi;

$api = RestApi::createWithOAuth(
$clientId,
$clientSecret,
$accessToken,
$refreshToken
);

// Usage same as above
$response = $api->request('/drive/v2/files');
```

### Service Account Authentication

```php
use Keboola\Google\ClientBundle\Google\RestApi;

// Service account JSON configuration (from Google Cloud Console)
$serviceAccountConfig = [
'type' => 'service_account',
'project_id' => 'your-project-id',
'private_key_id' => 'key-id',
'private_key' => '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
'client_email' => 'your-service-account@your-project.iam.gserviceaccount.com',
'client_id' => '123456789',
'auth_uri' => 'https://accounts.google.com/o/oauth2/auth',
'token_uri' => 'https://oauth2.googleapis.com/token',
'auth_provider_x509_cert_url' => 'https://www.googleapis.com/oauth2/v1/certs',
'client_x509_cert_url' => 'https://www.googleapis.com/robot/v1/metadata/x509/your-service-account%40your-project.iam.gserviceaccount.com'
];

// Scope definitions
$scopes = [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/drive.readonly'
];

// Create API client
$api = RestApi::createWithServiceAccount(
$serviceAccountConfig,
$scopes
);

// API calls
$response = $api->request('/drive/v2/files');
```

#### Loading Service Account from JSON file

```php
use Keboola\Google\ClientBundle\Google\RestApi;

// Load from JSON file
$serviceAccountConfig = json_decode(
file_get_contents('/path/to/service-account-key.json'),
true
);

$scopes = ['https://www.googleapis.com/auth/cloud-platform'];

$api = RestApi::createWithServiceAccount($serviceAccountConfig, $scopes);
$response = $api->request('/your-api-endpoint');
```

## Differences between OAuth and Service Account

| Property | OAuth 2.0 | Service Account |
|----------|-----------|-----------------|
| Authentication type | User-based | Server-to-server |
| Refresh token | ✅ Yes | ❌ No (not needed) |
| Authorization | Requires user consent | Automatic |
| Usage | Access to user data | Access to application data |
| Token expiration | Based on refresh token | Automatic renewal |

## Advanced Usage

### Retry and Backoff

```php
$api->setBackoffsCount(10); // Number of retries
$api->setDelayFn(function($retries) {
return 1000 * pow(2, $retries); // Exponential backoff
});
```

### Logging

```php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('google-api');
$logger->pushHandler(new StreamHandler('php://stdout'));

$api = RestApi::createWithServiceAccount(
$serviceAccountConfig,
$scopes,
$logger
);
```

### Custom HTTP Options

```php
$response = $api->request('/endpoint', 'POST', [
'Content-Type' => 'application/json'
], [
'json' => ['key' => 'value'],
'timeout' => 30
]);
```

## Testing

```bash
# OAuth tests (require environment variables)
export CLIENT_ID="your-client-id"
export CLIENT_SECRET="your-client-secret"
export REFRESH_TOKEN="your-refresh-token"

# Service Account tests (optional)
export SERVICE_ACCOUNT_JSON='{"type":"service_account","project_id":"your-project",...}'

# Run tests
composer tests
```

## Requirements

- PHP ^7.1
- guzzlehttp/guzzle ^6.0
- google/auth ^1.26

## License

MIT licensed, see [LICENSE](./LICENSE) file.
MIT
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.0",
"monolog/monolog": "^2.1"
"monolog/monolog": "^2.1",
"google/auth": "^1.26"
},
"require-dev": {
"keboola/coding-standard": "^15.0",
"phpstan/phpstan": "^1.4",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^9.5"
},
"minimum-stability": "stable",
Expand All @@ -28,7 +29,7 @@
}
},
"scripts": {
"tests": "phpunit",
"tests": "phpunit --testdox",
"phpstan": "phpstan analyse ./src ./tests --level=max --no-progress -c phpstan.neon",
"phpcs": "phpcs -n --ignore=vendor --extensions=php .",
"phpcbf": "phpcbf -n --ignore=vendor --extensions=php .",
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ services:
- CLIENT_ID
- CLIENT_SECRET
- REFRESH_TOKEN
- SERVICE_ACCOUNT_JSON

dev:
build: .
Expand All @@ -21,3 +22,4 @@ services:
- CLIENT_ID
- CLIENT_SECRET
- REFRESH_TOKEN
- SERVICE_ACCOUNT_JSON
Loading