Laravel Socialite adapter
Point Socialite at a local Bohurupee process so Google, GitHub, and custom slugs never leave your machine.
The adapter is a separate Composer package,
milon/bohurupee-laravel.
It is optional: any other stack can use the same OAuth/OIDC server with
Any framework.
Install
composer require milon/bohurupee-laravel --dev
Laravel auto-discovers Milon\Bohurupee\BohurupeeServiceProvider.
Environment
| Variable | Default | Meaning |
|---|---|---|
BOHURUPEE_ENABLED |
false |
Wrap Socialite when true |
BOHURUPEE_URL |
http://127.0.0.1:4190 |
Bohurupee origin (no trailing slash needed) |
BOHURUPEE_DRIVERS |
empty | Comma-separated Socialite names to wrap. Empty means every Socialite::driver($name), including custom slugs |
BOHURUPEE_EXCEPT |
empty | Names that keep the native Socialite provider (never wrapped) |
BOHURUPEE_PUBLIC_URL |
same as BOHURUPEE_URL |
Browser authorize URL when it differs from server-side (Docker) |
BOHURUPEE_ERROR_REDIRECT |
auto (/login) |
HTML redirect after Deny / OAuth error= |
Example .env:
BOHURUPEE_ENABLED=true
BOHURUPEE_URL=http://127.0.0.1:4190
# BOHURUPEE_DRIVERS=google,github
# BOHURUPEE_EXCEPT=apple
Publish the config if you prefer PHP over env:
php artisan vendor:publish --tag=bohurupee-config
Keep config/services.php as usual (client_id, client_secret, redirect).
Bohurupee is an open local client: any secret is accepted.
Deny / OAuth errors
Bohurupee may redirect to your callback with error=access_denied (consent
Deny). The adapter throws Milon\Bohurupee\OAuthErrorException from
user() and renders JSON (400) or redirects to login with a flash message,
so you do not need a manual if ($request->filled('error')) check (unless you
want custom handling).
Production guard
If BOHURUPEE_ENABLED=true and APP_ENV=production, the provider throws
Milon\Bohurupee\ProductionForbiddenException at boot. Leave the flag off in
deployed environments, or require the package as require-dev only.
How wrapping works
When enabled, Socialite's factory is decorated. Socialite::driver('google')
(and github, facebook, acme, …) returns BohurupeeProvider unless the
name is excluded. That provider uses:
GET {BOHURUPEE_URL}/{name}/authorizePOST {BOHURUPEE_URL}/{name}/tokenGET {BOHURUPEE_URL}/{name}/userinfo
Start Bohurupee first:
./bohurupee --config ./bohurupee.example.yaml
Then start your app and hit the same login routes you already use.
User mapping
Userinfo JSON is applied with setRaw(). Mapped fields, first match wins:
| Socialite | userinfo keys |
|---|---|
id |
id, sub |
email |
email |
name |
name, display_name |
nickname |
nickname, login, preferred_username |
avatar |
picture.data.url, picture, avatar, profile_image_url, avatar_url |
GitHub profiles therefore expose login / avatar_url on $user->getRaw()
and on the mapped nickname/avatar.
Example app
examples/laravel-socialite is a slim Laravel
app with Google and GitHub login buttons.
./bohurupee --config ./bohurupee.example.yaml
cd examples/laravel-socialite
composer install
cp .env.example .env
php artisan key:generate
php artisan serve
Open http://127.0.0.1:8000 and choose a provider. Consent on Bohurupee
returns JSON for the Socialite user. Deny and other OAuth errors return JSON
with error / error_description instead of Laravel’s exception page.
Point Bohurupee personas and profiles with
Configuration. Provider-shaped GitHub userinfo needs a
github profile — see Provider profiles.
Tests
Package tests mock Guzzle so token and userinfo never touch google.com or
github.com:
git clone https://github.com/milon/bohurupee-laravel.git
cd bohurupee-laravel
composer install
vendor/bin/phpunit
Browser tests can skip consent with
examples/playwright (loginAs(context, 'alice', 'google'))
or examples/php.
Internals
How the factory wrap, public vs server URL, AbstractProvider hooks, Deny,
userinfo mapping, and how the Go binary mints codes and tokens:
How the Laravel adapter works.