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 Unsplash Laravel Package

hughbertd/oauth2-unsplash

OAuth2 client provider for Unsplash built on league/oauth2-client. Install via Composer and use the Unsplash provider to run the Authorization Code flow, fetch access tokens, and retrieve the authenticated user (resource owner) for API access.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps for Laravel Integration

  1. Install the package:

    composer require hughbertd/oauth2-unsplash
    
  2. Add Unsplash credentials to .env:

    UNSPLASH_CLIENT_ID=your_client_id
    UNSPLASH_CLIENT_SECRET=your_client_secret
    UNSPLASH_REDIRECT_URI=http://your-app.test/callback
    
  3. Create a service class (e.g., app/Services/UnsplashService.php):

    namespace App\Services;
    
    use HughbertD\OAuth2\Client\Provider\Unsplash;
    use Illuminate\Support\Facades\Session;
    
    class UnsplashService
    {
        public function getProvider(): Unsplash
        {
            return new Unsplash([
                'clientId'     => config('services.unsplash.client_id'),
                'clientSecret' => config('services.unsplash.client_secret'),
                'redirectUri'  => config('services.unsplash.redirect_uri'),
            ]);
        }
    
        public function getAuthorizationUrl()
        {
            $provider = $this->getProvider();
            Session::put('oauth2state', $provider->getState());
            return $provider->getAuthorizationUrl();
        }
    
        public function getAccessToken(string $code)
        {
            $provider = $this->getProvider();
            return $provider->getAccessToken('authorization_code', ['code' => $code]);
        }
    
        public function getUser(array $token)
        {
            $provider = $this->getProvider();
            return $provider->getResourceOwner($token);
        }
    }
    
  4. Add routes in routes/web.php:

    Route::get('/auth/unsplash', [AuthController::class, 'redirectToUnsplash'])->name('unsplash.auth');
    Route::get('/auth/unsplash/callback', [AuthController::class, 'handleUnsplashCallback']);
    
  5. First use case: Redirect to Unsplash for auth

    // AuthController.php
    public function redirectToUnsplash()
    {
        return redirect()->to(app(UnsplashService::class)->getAuthorizationUrl());
    }
    
    public function handleUnsplashCallback()
    {
        try {
            $token = app(UnsplashService::class)->getAccessToken(request('code'));
            $user = app(UnsplashService::class)->getUser($token->toArray());
    
            // Store token/user in session or database
            auth()->loginUsingId($user->getId(), true); // Example: Use Unsplash user ID
    
            return redirect()->route('dashboard');
        } catch (Exception $e) {
            return redirect()->route('home')->with('error', $e->getMessage());
        }
    }
    

Implementation Patterns

Workflow: OAuth2 Authorization Code Flow

  1. Initiate Auth:

    • Redirect user to Unsplash with getAuthorizationUrl().
    • Store CSRF state in session (oauth2state).
  2. Callback Handling:

    • Validate state matches session to prevent CSRF.
    • Exchange code for access_token using getAccessToken().
  3. API Interaction:

    • Use the token to fetch Unsplash resources (e.g., photos, collections).
    • Example:
      $client = new \GuzzleHttp\Client();
      $response = $client->request('GET', 'https://api.unsplash.com/me', [
          'headers' => ['Authorization' => 'Bearer ' . $token['access_token']],
      ]);
      

Laravel-Specific Patterns

  1. Service Container Binding: Bind the service class in AppServiceProvider:

    public function register()
    {
        $this->app->singleton(UnsplashService::class, function ($app) {
            return new UnsplashService();
        });
    }
    
  2. Token Persistence: Store tokens in the database using a model (e.g., UnsplashToken):

    // UnsplashService.php
    public function storeToken(array $token)
    {
        return UnsplashToken::updateOrCreate(
            ['user_id' => auth()->id()],
            ['token' => $token['access_token'], 'refresh_token' => $token['refresh_token'] ?? null]
        );
    }
    
  3. Middleware for Protected Routes:

    // app/Http/Middleware/EnsureUnsplashToken.php
    public function handle($request, Closure $next)
    {
        if (!auth()->user()->unsplashToken) {
            return redirect()->route('unsplash.auth');
        }
        return $next($request);
    }
    
  4. Event-Based Workflows: Dispatch events for token refresh or user sync:

    // After fetching user data
    event(new UnsplashUserSynced($user));
    

Integration Tips

  • Combine with Guzzle: Use Guzzle for API calls with the token:

    $client = new \GuzzleHttp\Client(['base_uri' => 'https://api.unsplash.com']);
    $response = $client->request('GET', '/photos', [
        'auth' => [$token['access_token'], '']
    ]);
    
  • Laravel Socialite Alternative: If using Laravel Socialite, register the provider:

    Socialite::extend('unsplash', function ($app) {
        $config = $app['config']['services.unsplash'];
        return Socialite::buildProvider(
            HughbertD\OAuth2\Client\Provider\Unsplash::class,
            $config
        );
    });
    
  • Caching Responses: Cache Unsplash API responses (e.g., photos) using Laravel’s cache:

    $photos = Cache::remember('unsplash_photos', now()->addHours(1), function () {
        return $this->unsplashService->fetchPhotos();
    });
    

Gotchas and Tips

Pitfalls

  1. Stale Package:

    • The package was last updated in 2017. Test thoroughly with:
      • PHP 8.1+ (may require type hints or strict mode adjustments).
      • Laravel 9.x+ (check for compatibility with Symfony components).
    • Fix: Fork the package and update dependencies if needed.
  2. Missing Token Refresh:

    • Unsplash tokens expire (typically 1 hour). The package does not handle refresh tokens.
    • Fix: Implement a refreshToken() method or use Unsplash’s /token endpoint manually:
      $provider->getAccessToken('refresh_token', ['refresh_token' => $refreshToken]);
      
  3. CSRF/State Validation:

    • The package relies on manual state validation. Laravel’s csrf_token() middleware must be used.
    • Fix: Add middleware to validate state:
      public function handle($request, Closure $next)
      {
          if ($request->session()->get('oauth2state') !== $request->query('state')) {
              throw new \Exception('CSRF state validation failed');
          }
          return $next($request);
      }
      
  4. No Laravel Facades:

    • The package doesn’t integrate with Laravel’s Facades (e.g., Auth, Cache).
    • Fix: Use dependency injection or manually resolve services.
  5. Unsplash API Changes:

    • Unsplash may have updated OAuth2 endpoints (e.g., /authorize URL, scopes).
    • Fix: Validate endpoints against Unsplash’s API docs.
  6. Error Handling:

    • League’s OAuth2 exceptions are generic. Customize for Unsplash:
      try {
          $token = $provider->getAccessToken('authorization_code', ['code' => $code]);
      } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
          if (strpos($e->getMessage(), 'invalid_grant') !== false) {
              // Handle expired code/token
          }
      }
      

Debugging Tips

  1. Enable Debug Mode: Configure the provider for verbose logs:

    $provider = new Unsplash([
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'redirectUri' => $redirectUri,
        'debug' => true, // Enable debug mode
    ]);
    
  2. Inspect Raw Responses: Use getLastResponse() to debug API calls:

    try {
        $token = $provider->getAccessToken('authorization_code', ['code' => $code]);
    } catch (Exception $e) {
        dd($provider->getLastResponse()->getBody());
    }
    
  3. Test with Postman: Manually test Unsplash’s OAuth2 flow using Postman to isolate issues:

    • Authorize: GET https://unsplash.com/oauth/authorize?client_id=...&redirect_uri=...&response_type=code
    • Token: POST https://unsplash.com/oauth/token with code and credentials.

Extension Points

  1. Custom Scopes: The package supports scopes (e.g.,
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle