Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oauth2 Server Php Laravel Package

binhvd/oauth2-server-php

Laravel/PHP integration for an OAuth2 authorization server, wrapping oauth2-server-php to issue and validate access tokens for APIs. Provides configuration and service setup to add OAuth2 flows, token storage, and request/resource protection.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require binhvd/oauth2-server-php
    

    Ensure your project uses PHP 7.4+ (check composer.json constraints).

  2. Basic Server Initialization Create a minimal OAuth2 server in a route (e.g., routes/api.php):

    use OAuth2\Server;
    use OAuth2\GrantType\AuthorizationCodeGrant;
    use OAuth2\GrantType\RefreshTokenGrant;
    
    $server = new Server([
        'grant_types' => [
            AuthorizationCodeGrant::class,
            RefreshTokenGrant::grantType(),
        ],
        'storage' => new \OAuth2\Storage\Memory(), // Replace with DB in production
        'access_lifetime' => 3600, // 1 hour
    ]);
    
    $request = \OAuth2\Request::createFromGlobals();
    $response = new \OAuth2\Response();
    
    if ($server->handleTokenRequest($request, $response)->isValid()) {
        $response->send();
    } else {
        http_response_code(401);
        echo $response->getHttpBody();
    }
    
  3. First Use Case: Authorization Code Flow

    • Client requests /oauth/authorize (you’ll need to define this route).
    • After user approval, redirect to /oauth/token with code.
    • Test with Postman or cURL:
      curl -X POST http://your-app.test/oauth/token \
           -d "grant_type=authorization_code&code=YOUR_CODE&redirect_uri=YOUR_REDIRECT_URI&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
      

Implementation Patterns

Workflow: Building a Full OAuth2 Server

  1. Define Grant Types Extend or use built-in grants (e.g., PasswordGrant, ClientCredentialsGrant):

    $server = new Server([
        'grant_types' => [
            AuthorizationCodeGrant::class,
            RefreshTokenGrant::grantType(),
            PasswordGrant::class, // For resource owner credentials
        ],
    ]);
    
  2. Storage Layer Replace Memory storage with a database-backed solution (e.g., Eloquent):

    use OAuth2\Storage\Pdo;
    use OAuth2\Storage\Pdo as PdoStorage;
    
    $pdo = new \PDO('mysql:host=localhost;dbname=oauth', 'user', 'pass');
    $storage = new PdoStorage($pdo);
    $server = new Server(['storage' => $storage]);
    
  3. Middleware for Protected Routes Use middleware to validate access tokens in API routes:

    // app/Http/Middleware/AuthenticateOAuth.php
    public function handle($request, Closure $next) {
        $token = $request->bearerToken();
        if (!$token || !$this->validateToken($token)) {
            return response()->json(['error' => 'invalid_token'], 401);
        }
        return $next($request);
    }
    
    private function validateToken($token) {
        $server = new Server(['storage' => app('oauth.storage')]);
        $request = \OAuth2\Request::createFromGlobals();
        $request->setRequestToken($token);
        $response = new \OAuth2\Response();
        return $server->verifyResourceRequest($request, $response)->isValid();
    }
    
  4. Client Registration Dynamically register clients via a controller:

    public function registerClient(Request $request) {
        $client = new \OAuth2\Client(
            $request->client_id,
            $request->client_secret,
            $request->redirect_uri
        );
        app('oauth.storage')->setClient($client);
        return response()->json(['client_id' => $client->getId()]);
    }
    
  5. Scopes and Roles Attach scopes to tokens during grant processing:

    // In a custom grant type
    $token = new \OAuth2\AccessToken([
        'client_id' => $clientId,
        'user_id'   => $userId,
        'scope'     => 'read write', // Space-separated scopes
    ]);
    

Gotchas and Tips

Pitfalls

  1. CSRF in Authorization Flow

    • The package doesn’t handle CSRF protection by default. Use Laravel’s VerifyCsrfToken middleware for /oauth/authorize routes.
    • Fix: Add @method(['GET', 'POST']) public function authorize() to your controller and validate CSRF tokens.
  2. State Parameter Missing

    • The AuthorizationCodeGrant expects a state parameter for security. Always include it in your authorize requests.
    • Tip: Generate a random state and store it in the session:
      $state = Str::random(40);
      session(['oauth_state' => $state]);
      
  3. Token Storage Quirks

    • Memory storage is not persistent. Use Pdo or Redis in production.
    • Debugging: Dump storage contents with:
      dd(app('oauth.storage')->getClient($clientId));
      
  4. Redirect URI Mismatch

    • The package validates redirect_uri strictly. Ensure your client’s registered URI matches the request.
    • Error: invalid_redirect_uri → Check setRedirectUri() in your client setup.
  5. Scope Validation

    • Scopes are case-sensitive. Use consistent casing (e.g., read write vs READ WRITE).

Debugging Tips

  • Enable Verbose Errors Set error_details in the server config to get granular error messages:
    $server = new Server([
        'error_details' => true, // Show detailed errors in responses
    ]);
    
  • Log Token Requests Wrap handleTokenRequest in a log:
    \Log::info('Token request', [
        'grant' => $request->getGrantType(),
        'client_id' => $request->getClientId(),
    ]);
    
  • Test with Postman Use the "Authorization" tab to send tokens in headers:
    Authorization: Bearer YOUR_TOKEN
    

Extension Points

  1. Custom Grant Types Extend \OAuth2\GrantType\AbstractGrant to add custom flows (e.g., JWT bearer):

    class JwtGrant extends AbstractGrant {
        public function validateRequest(\OAuth2\RequestInterface $request) {
            $token = $request->getHeader('Authorization');
            if (!preg_match('/Bearer (.*)/', $token, $matches)) {
                return false;
            }
            // Validate JWT logic here
            return true;
        }
    }
    
  2. Override Storage Methods Extend \OAuth2\Storage\StorageInterface to add custom logic (e.g., audit logs):

    class CustomStorage implements StorageInterface {
        public function getClient($clientId) {
            $client = parent::getClient($clientId);
            \Log::info("Client $clientId accessed", ['client' => $client]);
            return $client;
        }
    }
    
  3. Response Customization Modify the response format by extending \OAuth2\Response:

    class ApiResponse extends \OAuth2\Response {
        public function getHttpBody() {
            return json_encode([
                'error' => $this->error,
                'error_description' => $this->errorDescription,
                'custom_field' => 'value',
            ]);
        }
    }
    
  4. User Authentication Integrate with Laravel’s auth system in grants:

    // In a custom grant
    $user = \Auth::guard('api')->user();
    if (!$user) {
        throw new \OAuth2\Exception\OAuthServerException(
            \OAuth2\Exception\OAuthServerException::INVALID_GRANT,
            'User not authenticated'
        );
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor