PHPackages                             impression/laravel-google-passport-oauth - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. impression/laravel-google-passport-oauth

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

impression/laravel-google-passport-oauth
========================================

Google OAuth token exchange for Passport personal access tokens

v1.0.0(2mo ago)038[1 issues](https://github.com/JamesImpression/Laravel-Google-Passport-OAuth/issues)MITPHPPHP ^8.1

Since Apr 28Pushed 1mo agoCompare

[ Source](https://github.com/JamesImpression/Laravel-Google-Passport-OAuth)[ Packagist](https://packagist.org/packages/impression/laravel-google-passport-oauth)[ RSS](/packages/impression-laravel-google-passport-oauth/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (7)Versions (3)Used By (0)

Laravel Google Passport OAuth
=============================

[](#laravel-google-passport-oauth)

Exchange Google OAuth access tokens for Laravel Passport personal access tokens. Enables seamless authentication from external applications (like better-chatbot) to your Laravel MCP server.

Features
--------

[](#features)

- ✅ Validate Google OAuth tokens
- ✅ Refresh expired tokens server-side
- ✅ Find existing users by email (pre-provisioning required)
- ✅ Issue Passport personal access tokens
- ✅ **OAuth 2.1 MCP HTTP Registry Integration** — Register organization OAuth metadata for Alexis discovery
- ✅ **Fallback Authentication** — Seamlessly fallback to parent app authentication when Google token unavailable
- ✅ **Confirmation Workflow** — Simple confirmation page for org OAuth connection registration
- ✅ Configurable per-app (column mapping, domain whitelist)
- ✅ No auto-user-creation (prevents account enumeration)
- ✅ Rate limiting built-in (60 requests/minute)
- ✅ Comprehensive error handling with specific status codes
- ✅ Full test coverage (18 passing tests)

Installation
------------

[](#installation)

### Step 1: Install via Composer

[](#step-1-install-via-composer)

```
composer require impression/laravel-google-passport-oauth
```

### Step 2: Publish Configuration

[](#step-2-publish-configuration)

```
php artisan vendor:publish --provider="Impression\GooglePassportOAuth\GoogleOAuthServiceProvider" --tag="google-oauth-config"
```

This creates `config/google-oauth.php` with sensible defaults.

### Step 3: Set Environment Variables

[](#step-3-set-environment-variables)

Add to `.env`:

```
GOOGLE_OAUTH_CLIENT_ID=your-google-client-id-from-console
GOOGLE_OAUTH_CLIENT_SECRET=your-google-client-secret
GOOGLE_OAUTH_USER_MODEL=App\Models\User  # optional, defaults to App\Models\User
GOOGLE_OAUTH_GOOGLE_ID_COLUMN=google_id  # optional, for custom column name
GOOGLE_OAUTH_EMAIL_COLUMN=email          # optional, for custom column name
GOOGLE_OAUTH_DOMAIN_WHITELIST=your-company.com,partner.com  # optional, comma-separated
```

### Step 4: Ensure Users Table Has Required Columns

[](#step-4-ensure-users-table-has-required-columns)

If you need to store Google user IDs, add a migration:

```
Schema::table('users', function (Blueprint $table) {
    $table->string('google_id')->nullable()->unique();
});
```

Run migrations:

```
php artisan migrate
```

MCP OAuth 2.1 Registry Setup
----------------------------

[](#mcp-oauth-21-registry-setup)

This package supports OAuth 2.1 MCP HTTP Registry integration, allowing organizations to register protected resource metadata (PRM), authorization servers, and callback URLs for Alexis discovery. End users still sign in separately via their MCP connections (PKCE); org-level metadata is static and managed server-side.

### Step 1: Publish MCP Migrations

[](#step-1-publish-mcp-migrations)

```
php artisan vendor:publish --provider="Impression\GooglePassportOAuth\GoogleOAuthServiceProvider" --tag="google-oauth-migrations"
```

### Step 2: Set MCP Environment Variables

[](#step-2-set-mcp-environment-variables)

Add to `.env`:

```
# MCP OAuth 2.1 Registry Configuration
MCP_OAUTH_PARENT_GUARD=web                    # Auth guard for parent app (default: web)
MCP_OAUTH_ISSUER_URL=https://your-app.com    # Base URL identifying your OAuth provider
MCP_OAUTH_DISCOVERY_ENDPOINT=/oauth/mcp/discovery  # MCP discovery endpoint (optional)
```

### Step 3: Run Migrations

[](#step-3-run-migrations)

```
php artisan migrate
```

This creates the `mcp_oauth_connections` table for storing org-level OAuth metadata.

### Step 4: Register MCP Routes (Optional)

[](#step-4-register-mcp-routes-optional)

If you want to expose MCP endpoints in your parent app, update `routes/api.php` or `routes/web.php`:

```
use Impression\GooglePassportOAuth\Http\Controllers\MCPTokenController;
use Impression\GooglePassportOAuth\Http\Controllers\MCPConfirmController;
use Impression\GooglePassportOAuth\Http\Controllers\MCPConnectionController;
use Impression\GooglePassportOAuth\Http\Middleware\EnsureOAuthAuthenticated;

Route::middleware(['throttle:60,1', EnsureOAuthAuthenticated::class])->group(function () {
    // Exchange auth token for Passport token (Google or fallback parent app auth)
    Route::post('/oauth/mcp/token', [MCPTokenController::class, 'exchange']);

    // Show confirmation page with existing connections
    Route::get('/oauth/mcp/confirm', [MCPConfirmController::class, 'show']);

    // Register new MCP OAuth connection
    Route::post('/oauth/mcp/connections', [MCPConnectionController::class, 'store']);
});
```

Configuration
-------------

[](#configuration)

The package exposes configuration in `config/google-oauth.php`:

```
return [
    // Google OAuth credentials (from Google Cloud Console)
    'google_client_id' => env('GOOGLE_OAUTH_CLIENT_ID'),
    'google_client_secret' => env('GOOGLE_OAUTH_CLIENT_SECRET'),

    // Which user model to query for authentication
    'user_model' => env('GOOGLE_OAUTH_USER_MODEL', 'App\Models\User'),

    // Column mapping for flexible schema
    'column_mapping' => [
        'email' => env('GOOGLE_OAUTH_EMAIL_COLUMN', 'email'),
        'google_id' => env('GOOGLE_OAUTH_GOOGLE_ID_COLUMN', 'google_id'),
    ],

    // Whitelist by domain (null = allow all domains)
    'domain_whitelist' => env('GOOGLE_OAUTH_DOMAIN_WHITELIST')
        ? explode(',', env('GOOGLE_OAUTH_DOMAIN_WHITELIST'))
        : null,

    // Passport token expiry (seconds)
    'token_expires_in' => env('GOOGLE_OAUTH_TOKEN_EXPIRES_IN', 31536000), // 1 year

    // MCP OAuth 2.1 Registry configuration
    'mcp_registry' => [
        'parent_app_guard' => env('MCP_OAUTH_PARENT_GUARD', 'web'),
        'discovery_endpoint' => env('MCP_OAUTH_DISCOVERY_ENDPOINT', '/oauth/mcp/discovery'),
        'issuer_url' => env('MCP_OAUTH_ISSUER_URL'),
    ],
```

### Column Mapping

[](#column-mapping)

If your users table uses different column names:

```
# For a table with: google_user_id, employee_email
GOOGLE_OAUTH_GOOGLE_ID_COLUMN=google_user_id
GOOGLE_OAUTH_EMAIL_COLUMN=employee_email
```

### Domain Whitelist

[](#domain-whitelist)

Restrict authentication to specific email domains:

```
GOOGLE_OAUTH_DOMAIN_WHITELIST=company.com,partner.com
```

Only users with email addresses ending in these domains can authenticate. Leave empty/null to allow all domains.

Usage
-----

[](#usage)

### Google OAuth Token Exchange (Existing Flow)

[](#google-oauth-token-exchange-existing-flow)

#### Authentication Flow

[](#authentication-flow)

1. **External app** (e.g., chatbot) obtains Google OAuth token from user
2. **External app** sends token to your Laravel endpoint: `POST /oauth/google-token`
3. **Your package** validates token with Google, finds user by email
4. **Your package** issues Passport personal access token
5. **External app** uses Passport token for subsequent API calls

#### HTTP Endpoint

[](#http-endpoint)

**POST** `/oauth/google-token`

##### Request

[](#request)

```
curl -X POST http://localhost:8000/oauth/google-token \
  -H "Content-Type: application/json" \
  -d '{
    "access_token": "ya29.a0AfH6SMBx...",
    "refresh_token": "1//0gx..."
  }'
```

**Parameters:**

- `access_token` (required): Google OAuth access token
- `refresh_token` (optional): Google OAuth refresh token (used if access token is expired)

##### Success Response (200 OK)

[](#success-response-200-ok)

```
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 31536000
}
```

Use the `access_token` as a Bearer token in subsequent API requests:

```
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \
  http://localhost:8000/api/protected-endpoint
```

##### Error Responses

[](#error-responses)

**400 Bad Request** — Validation failed

```
{
  "error": "invalid_request",
  "message": {
    "access_token": ["The access_token field is required."]
  }
}
```

**401 Unauthorized** — Token invalid, expired, or user not found

```
{
  "error": "invalid_grant",
  "message": "The provided token is invalid or tampered with."
}
```

Other 401 errors:

- `token_expired`: Token is expired (no refresh token provided)
- `user_not_found`: User email not in database
- `domain_not_allowed`: User email domain not whitelisted

**503 Service Unavailable** — Google API error

```
{
  "error": "service_unavailable",
  "message": "Google API returned status 503"
}
```

### MCP OAuth 2.1 Registry Flow (New)

[](#mcp-oauth-21-registry-flow-new)

The MCP OAuth 2.1 flow allows organizations to register OAuth metadata for protected resource discovery. Organizations authenticate via either Google OAuth or fallback to parent app authentication, then register their OAuth 2.1 server details.

#### Authentication Flow

[](#authentication-flow-1)

1. **Organization user** is already authenticated in parent app (Laravel session)
2. **Organization user** calls MCP endpoints without Google token (fallback to parent auth)
3. **Package middleware** checks parent app session via configured guard
4. **Package** issues Passport token for the authenticated user
5. **Organization** visits confirmation page to review and register OAuth metadata
6. **Organization** submits OAuth 2.1 metadata (PRM, authorization server URL, callback URL)
7. **Package** stores metadata in `mcp_oauth_connections` table
8. **Alexis** queries discovery endpoint to find registered OAuth configurations

#### MCP Token Exchange Endpoint

[](#mcp-token-exchange-endpoint)

**POST** `/oauth/mcp/token`

This endpoint accepts both Google tokens and relies on parent app authentication.

##### Request (with Google token):

[](#request-with-google-token)

```
curl -X POST http://localhost:8000/oauth/mcp/token \
  -H "Authorization: Bearer ya29.a0AfH6SMBx..." \
  -H "Content-Type: application/json"
```

##### Request (fallback to parent app auth):

[](#request-fallback-to-parent-app-auth)

```
# User must be authenticated in parent app session
curl -X POST http://localhost:8000/oauth/mcp/token \
  -H "Content-Type: application/json" \
  -b "LARAVEL_SESSION=..." # Session cookie from parent app
```

##### Success Response (200 OK)

[](#success-response-200-ok-1)

```
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 31536000
}
```

#### MCP Confirmation Endpoint

[](#mcp-confirmation-endpoint)

**GET** `/oauth/mcp/confirm`

Shows existing MCP OAuth connections and prompts for new metadata.

##### Request

[](#request-1)

```
curl http://localhost:8000/oauth/mcp/confirm \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
```

##### Success Response (200 OK)

[](#success-response-200-ok-2)

```
{
  "message": "Confirm MCP OAuth connection registration",
  "issuer_url": "https://your-app.com",
  "discovery_endpoint": "/oauth/mcp/discovery",
  "existing_connections": [
    {
      "id": 1,
      "name": "Acme Corp OAuth",
      "authorization_server_url": "https://auth.acme.com/oauth/authorize",
      "callback_url": "https://acme.com/oauth/callback",
      "status": "active"
    }
  ]
}
```

#### MCP Connection Registration Endpoint

[](#mcp-connection-registration-endpoint)

**POST** `/oauth/mcp/connections`

Register a new OAuth 2.1 connection for the organization.

##### Request

[](#request-2)

```
curl -X POST http://localhost:8000/oauth/mcp/connections \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "connection_name": "Acme Corp OAuth",
    "authorization_server_url": "https://auth.acme.com/oauth/authorize",
    "callback_url": "https://acme.com/oauth/callback",
    "protected_resource_metadata": {
      "scopes": ["openid", "profile", "email"],
      "endpoints": {
        "userinfo": "https://api.acme.com/userinfo",
        "resource": "https://api.acme.com/resource"
      }
    },
    "oauth_client_id": "acme-client-id",
    "oauth_client_secret": "acme-client-secret"
  }'
```

**Parameters:**

- `connection_name` (required): Friendly name for this OAuth connection
- `authorization_server_url` (required): URL of the OAuth 2.1 authorization server
- `callback_url` (required): Redirect URI for OAuth callback
- `protected_resource_metadata` (optional): JSON with scopes, endpoints, etc.
- `oauth_client_id` (optional): Static OAuth 2.1 client ID
- `oauth_client_secret` (optional): Static OAuth 2.1 client secret (encrypted server-side)

##### Success Response (201 Created)

[](#success-response-201-created)

```
{
  "message": "MCP OAuth connection registered successfully",
  "connection": {
    "id": 1,
    "name": "Acme Corp OAuth",
    "authorization_server_url": "https://auth.acme.com/oauth/authorize",
    "callback_url": "https://acme.com/oauth/callback",
    "status": "active"
  },
  "issuer_url": "https://your-app.com",
  "discovery_endpoint": "/oauth/mcp/discovery"
}
```

#### Error Responses

[](#error-responses-1)

**401 Unauthorized**

```
{
  "error": "unauthorized",
  "message": "Unauthorized. Provide a valid Google token or authenticate with the parent application."
}
```

**422 Unprocessable Entity** — Validation failed

```
{
  "message": "The connection_name field is required.",
  "errors": {
    "connection_name": ["The connection_name field is required."]
  }
}
```

Integrating with Parent Laravel Application
-------------------------------------------

[](#integrating-with-parent-laravel-application)

To integrate this package as a sub-package in a larger Laravel application:

### 1. Install and Configure

[](#1-install-and-configure)

```
composer require impression/laravel-google-passport-oauth
php artisan vendor:publish --provider="Impression\GooglePassportOAuth\GoogleOAuthServiceProvider" --tag="google-oauth-config"
php artisan vendor:publish --provider="Impression\GooglePassportOAuth\GoogleOAuthServiceProvider" --tag="google-oauth-migrations"
php artisan migrate
```

### 2. Set Environment Variables

[](#2-set-environment-variables)

```
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
MCP_OAUTH_PARENT_GUARD=web
MCP_OAUTH_ISSUER_URL=https://your-app.com
```

### 3. Register Routes in Parent App

[](#3-register-routes-in-parent-app)

In your parent app's `routes/api.php`:

```
Route::name('mcp.')->prefix('oauth')->group(function () {
    // Google OAuth endpoint (existing)
    Route::post('google-token', [\Impression\GooglePassportOAuth\Http\Controllers\GoogleTokenController::class, 'exchange'])
        ->middleware('throttle:60,1');

    // MCP OAuth 2.1 endpoints (new)
    Route::middleware(['throttle:60,1', \Impression\GooglePassportOAuth\Http\Middleware\EnsureOAuthAuthenticated::class])
        ->group(function () {
            Route::post('mcp/token', [\Impression\GooglePassportOAuth\Http\Controllers\MCPTokenController::class, 'exchange']);
            Route::get('mcp/confirm', [\Impression\GooglePassportOAuth\Http\Controllers\MCPConfirmController::class, 'show']);
            Route::post('mcp/connections', [\Impression\GooglePassportOAuth\Http\Controllers\MCPConnectionController::class, 'store']);
        });
});
```

### 4. Access MCP Models in Your App

[](#4-access-mcp-models-in-your-app)

```
use Impression\GooglePassportOAuth\Models\MCPOAuthConnection;

// Get all active connections for a user
$connections = MCPOAuthConnection::where('user_id', $user->id)->active()->get();

// Find a specific connection
$connection = MCPOAuthConnection::findOrFail($id);

// Update connection status
$connection->update(['status' => 'inactive']);
```

### 5. Share User Model Configuration

[](#5-share-user-model-configuration)

Ensure your parent app's User model is properly configured:

```
GOOGLE_OAUTH_USER_MODEL=App\Models\User
```

### 6. Trusted Proxies (If Behind Load Balancer)

[](#6-trusted-proxies-if-behind-load-balancer)

If your parent app is behind a load balancer, configure `config/trustedproxy.php` to properly detect authenticated sessions.

---

User Provisioning
-----------------

[](#user-provisioning)

Users **must exist** in your database before authenticating. The package does not auto-create users to prevent account enumeration attacks.

### Provisioning Workflow

[](#provisioning-workflow)

1. **Add user to database** (via admin panel, bulk import, or migration):

```
User::create([
    'name' => 'John Doe',
    'email' => 'john@company.com',
    'google_id' => 'google-user-id-123',  // optional, from Google tokeninfo
    'password' => Hash::make(Str::random(32)), // optional, can be dummy
]);
```

2. **User authenticates** via `POST /oauth/google-token`
3. **Package validates** email matches (finds user)
4. **Package issues** Passport token

### Pre-provisioning at Scale

[](#pre-provisioning-at-scale)

For bulk onboarding:

```
# CSV import
php artisan import:users users.csv --from-google

# Sync from directory (LDAP, Entra, etc.)
php artisan sync:users --provider=entra
```

Security Considerations
-----------------------

[](#security-considerations)

### Production Checklist

[](#production-checklist)

- ✅ Use HTTPS only (enforce via middleware or load balancer)
- ✅ Store credentials in `.env` (never commit to version control)
- ✅ Pre-provision users carefully (audit logging recommended)
- ✅ Monitor rate limiting (`/oauth/google-token` max 60 requests/minute per IP)
- ✅ Use domain whitelist in production
- ✅ Rotate Google OAuth credentials regularly

### How It Works

[](#how-it-works)

1. **No token storage** — Tokens validated in-memory, never persisted
2. **Server-side refresh** — If token expired but refresh token provided, package refreshes silently
3. **Email-based lookup** — User identity determined by email (not Google ID)
4. **Pre-provisioning only** — Prevents account enumeration
5. **Signed Passport tokens** — Subsequent API calls verified with Passport

Configuration Per Application
-----------------------------

[](#configuration-per-application)

Each Laravel app using this package can customize the configuration independently:

**MCP Server** (`config/google-oauth.php`):

```
'column_mapping' => ['email' => 'email', 'google_id' => 'google_user_id'],
'domain_whitelist' => ['company.com'],
```

**Internal App** (`config/google-oauth.php`):

```
'column_mapping' => ['email' => 'work_email', 'google_id' => 'gid'],
'domain_whitelist' => ['company.com', 'internal.company.com'],
```

**Partner Portal** (`config/google-oauth.php`):

```
'column_mapping' => ['email' => 'contact_email', 'google_id' => null],
'domain_whitelist' => ['partner1.com', 'partner2.com'],
```

Testing
-------

[](#testing)

### Running Tests

[](#running-tests)

```
# All tests
vendor/bin/phpunit tests/

# Unit tests only
vendor/bin/phpunit tests/Unit/

# Feature tests only
vendor/bin/phpunit tests/Feature/

# Specific test
vendor/bin/phpunit tests/Unit/GoogleTokenValidatorTest.php
```

### Test Coverage

[](#test-coverage)

- **18 tests passing** (9 skipped for Passport integration)
- Unit tests for token validation and user resolution
- Feature tests for controller behavior
- Integration tests for end-to-end flow
- HTTP mocking for Google API (no external dependencies)

### Writing Integration Tests

[](#writing-integration-tests)

In your app, add integration tests:

```
use Illuminate\Support\Facades\Http;

public function test_google_oauth_integration()
{
    Http::fake([
        'https://www.googleapis.com/oauth2/v3/tokeninfo' => Http::response([
            'email' => 'test@company.com',
            'user_id' => 'google-123',
            'expires_in' => 3600,
        ]),
    ]);

    // Create user
    $user = User::factory()->create(['email' => 'test@company.com']);

    // Exchange token
    $response = $this->postJson('/oauth/google-token', [
        'access_token' => 'test-token',
    ]);

    $response->assertStatus(200)
        ->assertJsonStructure(['access_token', 'token_type', 'expires_in']);
}
```

Quality Checks
--------------

[](#quality-checks)

The package includes code quality tools:

```
# Code style (PSR-12)
vendor/bin/pint src tests

# Static analysis (PHPStan level 5)
vendor/bin/phpstan analyse src
```

All quality gates pass:

- ✅ Pint (0 style issues)
- ✅ PHPStan (0 errors)
- ✅ PHPUnit (18 passing tests)

Troubleshooting
---------------

[](#troubleshooting)

### "User not found" (401)

[](#user-not-found-401)

- Verify user exists: `User::where('email', 'test@company.com')->first()`
- Check column mapping: `GOOGLE_OAUTH_EMAIL_COLUMN`
- Verify email matches exactly (case-sensitive)

### "Domain not allowed" (401)

[](#domain-not-allowed-401)

- Check whitelist: `config('google-oauth.domain_whitelist')`
- Verify user's email domain is whitelisted
- To disable: `GOOGLE_OAUTH_DOMAIN_WHITELIST=` (empty value)

### "Token expired" (401)

[](#token-expired-401)

- Provide `refresh_token` in request body
- Ensure Google OAuth credentials are correct
- Verify token is actually expired (check `expires_in`)

### "Service unavailable" (503)

[](#service-unavailable-503)

- Check Google API status:
- Verify `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`
- Check network connectivity to `https://www.googleapis.com`

### Tests Failing

[](#tests-failing)

- Ensure Composer dev dependencies installed: `composer install`
- Run with clean cache: `vendor/bin/phpunit --no-coverage`
- Check for mocking issues: Review `Http::fake()` setup in test

API Reference
-------------

[](#api-reference)

### GoogleTokenValidator

[](#googletokenvalidator)

Validates Google OAuth tokens and handles refresh logic.

```
use Impression\GooglePassportOAuth\Services\GoogleTokenValidator;

$validator = app(GoogleTokenValidator::class);

// Validate token (with optional refresh)
$tokenInfo = $validator->validate('access-token', 'refresh-token');

// Returns:
// [
//     'email' => 'user@example.com',
//     'name' => 'user@example.com',
//     'google_id' => 'google-123',
//     'expires_at' => Carbon instance,
// ]
```

### UserSyncResolver

[](#usersyncresolver)

Finds users by email with domain whitelist enforcement.

```
use Impression\GooglePassportOAuth\Services\UserSyncResolver;

$resolver = app(UserSyncResolver::class);

// Resolve user (throws if not found or domain not allowed)
$user = $resolver->resolveByEmail('user@example.com');
```

### Exceptions

[](#exceptions)

All exceptions extend `GoogleOAuthException`:

```
use Impression\GooglePassportOAuth\Exceptions\{
    InvalidTokenException,
    TokenExpiredException,
    RefreshFailedException,
    GoogleApiException,
    UserNotFoundByEmailException,
    DomainNotAllowedException,
};
```

License
-------

[](#license)

MIT

Contributing
------------

[](#contributing)

Contributions welcome! Please ensure:

- Tests pass: `vendor/bin/phpunit`
- Code style passes: `vendor/bin/pint src tests`
- Static analysis passes: `vendor/bin/phpstan analyse src`

Support
-------

[](#support)

For issues and questions, please open an issue on GitHub or contact the Impression team.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance88

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

88d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/84cc83d024bf1d44f6bae42d7a5fe788b08df3d46448df18ed001f62fb470480?d=identicon)[Impression](/maintainers/Impression)

---

Top Contributors

[![jameshall-cmyk](https://avatars.githubusercontent.com/u/274548956?v=4)](https://github.com/jameshall-cmyk "jameshall-cmyk (12 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/impression-laravel-google-passport-oauth/health.svg)

```
[![Health](https://phpackages.com/badges/impression-laravel-google-passport-oauth/health.svg)](https://phpackages.com/packages/impression-laravel-google-passport-oauth)
```

###  Alternatives

[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)[leantime/leantime

Open source project management system for non-project managers. Simple like Trello, powerful like Jira. Built with neurodiversity in mind.

10.2k4.0k](/packages/leantime-leantime)[jeremy379/laravel-openid-connect

OpenID Connect support to the PHP League's OAuth2 Server. Compatible with Laravel Passport.

61437.0k9](/packages/jeremy379-laravel-openid-connect)[nasirkhan/laravel-starter

A CMS like modular Laravel starter project.

1.4k2.7k](/packages/nasirkhan-laravel-starter)[exceedone/exment

Management for Product, Client, Contracts, Subscription, ...

28038.8k](/packages/exceedone-exment)[duncanmcclean/statamic-cargo

Comprehensive e-commerce addon for Statamic. Build bespoke e-commerce sites without the complexity.

3518.3k](/packages/duncanmcclean-statamic-cargo)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
