3dsinteractive/oauth-server-bundle
Installation Add the bundle via Composer:
composer require 3dsinteractive/oauth-server-bundle
Register the bundle in config/bundles.php (Symfony):
return [
// ...
Bazinga\OAuthServerBundle\BazingaOAuthServerBundle::class => ['all' => true],
];
Configuration Publish the default config:
php artisan vendor:publish --provider="Bazinga\OAuthServerBundle\BazingaOAuthServerBundle" --tag="config"
Update config/oauth_server.php with your OAuth credentials (consumer key/secret, token storage, etc.).
First Use Case: Basic OAuth Request Handling
Use the OAuthServer service to validate and process OAuth requests:
use Bazinga\OAuthServerBundle\OAuth\OAuthServer;
public function handleOAuthRequest(OAuthServer $oauthServer)
{
$request = $oauthServer->getRequest();
$response = $oauthServer->getResponse();
if (!$oauthServer->validateRequest()) {
return $response->send();
}
// Proceed with authenticated logic
}
Routing
Define routes in routes/web.php to handle OAuth flows:
use Symfony\Component\HttpFoundation\Request;
Route::post('/oauth/authorize', [OAuthController::class, 'authorize']);
Route::post('/oauth/access_token', [OAuthController::class, 'accessToken']);
Client Requests Authorization
Client sends a signed request to /oauth/authorize with:
oauth_consumer_keyoauth_signature_method (e.g., HMAC-SHA1)oauth_timestamp and oauth_nonceoauth_callback (if applicable).Server Validation
Use the OAuthServer service to validate:
if (!$oauthServer->validateRequest()) {
return $response->send(); // Returns 401 if invalid
}
User Approval Redirect the user to an approval page (e.g., Laravel Blade view):
return view('oauth.authorize', [
'requestToken' => $oauthServer->getRequestToken(),
]);
Token Exchange After approval, exchange the request token for an access token:
$accessToken = $oauthServer->getAccessToken();
$oauthServer->storeAccessToken($accessToken);
Protected Resource Access Validate access tokens in protected endpoints:
if (!$oauthServer->validateAccessToken()) {
abort(403, 'Unauthorized');
}
Laravel-Specific
Use Laravel’s service container to bind the OAuthServer:
$this->app->bind(OAuthServer::class, function ($app) {
return new OAuthServer($app['config']['oauth_server']);
});
Token Storage
Extend Bazinga\OAuthServerBundle\Storage\TokenStorageInterface for custom storage (e.g., database):
class DatabaseTokenStorage implements TokenStorageInterface {
// Implement saveRequestToken(), saveAccessToken(), etc.
}
Middleware for Protected Routes Create middleware to validate OAuth tokens:
public function handle(Request $request, Closure $next) {
$oauthServer = app(OAuthServer::class);
if (!$oauthServer->validateAccessToken()) {
abort(403);
}
return $next($request);
}
Signature Verification
Customize signature verification by extending Bazinga\OAuthServerBundle\OAuth\SignatureMethod\SignatureMethod:
class CustomSignatureMethod extends SignatureMethod {
public function checkSignature($request, $consumerSecret, $tokenSecret = null) {
// Custom logic
}
}
Timestamp and Nonce Validation
oauth_timestamp and oauth_nonce are unique and recent (configurable via config/oauth_server.php).Signature Method Mismatch
oauth_signature_method (e.g., HMAC-SHA1). If unsupported, the server returns a 401.Token Storage
TokenStorageInterface implementation. Default is in-memory, which is not persistent.CSRF Protection
VerifyCsrfToken middleware for sensitive endpoints.Callback Handling
oauth_callback parameter must be validated against a whitelist if used. Misconfiguration can lead to open redirects.Enable Verbose Logging
Add to config/oauth_server.php:
'debug' => env('APP_DEBUG', false),
'log_requests' => true,
Logs will appear in storage/logs/oauth.log.
Validate Request Parameters
Use the OAuthServer service to inspect requests:
$request = $oauthServer->getRequest();
dump($request->getParameters()); // Debug all OAuth parameters
Signature Debugging
Manually verify signatures using the OAuthServer:
$consumer = $oauthServer->getConsumer();
$token = $oauthServer->getRequestToken();
$signatureMethod = $oauthServer->getSignatureMethod();
$isValid = $signatureMethod->checkSignature(
$oauthServer->getRequest(),
$consumer->getSecret(),
$token ? $token->getSecret() : null
);
Custom Storage
Override token storage by binding your implementation in AppServiceProvider:
$this->app->bind(TokenStorageInterface::class, function ($app) {
return new DatabaseTokenStorage();
});
Custom Signature Methods
Register additional signature methods in config/oauth_server.php:
'signature_methods' => [
'HMAC-SHA1' => 'Bazinga\OAuthServerBundle\OAuth\SignatureMethod\SignatureMethod_HMAC_SHA1',
'PLAINTEXT' => 'Bazinga\OAuthServerBundle\OAuth\SignatureMethod\SignatureMethod_PLAINTEXT',
'CUSTOM' => 'App\OAuth\CustomSignatureMethod', // Your custom class
],
Event Listeners
Extend OAuth flows by listening to events (e.g., oauth.server.request.validated):
use Bazinga\OAuthServerBundle\Event\OAuthEvents;
Event::listen(OAuthEvents::REQUEST_VALIDATED, function ($event) {
// Custom logic after request validation
});
Response Customization
Override default responses by extending Bazinga\OAuthServerBundle\OAuth\Response:
class CustomResponse extends Response {
public function send() {
// Custom response logic (e.g., JSON instead of HTML)
}
}
Bind it in AppServiceProvider:
$this->app->bind(Response::class, CustomResponse::class);
Consumer and Token Storage
Ensure consumer_storage and token_storage in config/oauth_server.php point to valid implementations. Defaults:
'consumer_storage' => 'Bazinga\OAuthServerBundle\Storage\MemoryConsumerStorage',
'token_storage' => 'Bazinga\OAuthServerBundle\Storage\MemoryTokenStorage',
Replace with your custom classes for persistence.
Nonce Handling
The nonce_storage must be implemented to track used nonces. Default is in-memory:
'nonce_storage' => 'Bazinga\OAuthServerBundle\Storage\MemoryNonceStorage',
Timestamp Tolerance
Adjust timestamp_tolerance (in seconds) to account for client clock skew:
'timestamp_tolerance' => 60, // Default: 60 seconds
Callback Verification Enable callback whitelisting:
'callback_whitelist' => ['https://yourdomain.com/callback'],
How can I help you explore Laravel packages today?