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

league/oauth2-facebook

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package:
    composer require league/oauth2-facebook
    
  2. Configure Facebook credentials in .env:
    FACEBOOK_CLIENT_ID=your_app_id
    FACEBOOK_CLIENT_SECRET=your_app_secret
    FACEBOOK_REDIRECT_URI=http://your-app.test/callback
    FACEBOOK_GRAPH_VERSION=v18.0  # Use latest stable version
    
  3. Create a service provider (app/Providers/FacebookServiceProvider.php):
    use League\OAuth2\Client\Provider\Facebook;
    use League\OAuth2\Client\Provider\FacebookUser;
    
    class FacebookServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton('facebook', function ($app) {
                return new Facebook([
                    'clientId'          => $app['config']['services.facebook.client_id'],
                    'clientSecret'      => $app['config']['services.facebook.client_secret'],
                    'redirectUri'       => $app['config']['services.facebook.redirect_uri'],
                    'graphApiVersion'   => $app['config']['services.facebook.graph_version'],
                ]);
            });
        }
    }
    
  4. Add to config/services.php:
    'facebook' => [
        'client_id'     => env('FACEBOOK_CLIENT_ID'),
        'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
        'redirect_uri'  => env('FACEBOOK_REDIRECT_URI'),
        'graph_version' => env('FACEBOOK_GRAPH_VERSION', 'v18.0'),
    ],
    

First Use Case: Social Login

Create a controller to handle the OAuth flow:

use League\OAuth2\Client\Provider\Facebook;
use League\OAuth2\Client\Provider\Exception\FacebookProviderException;

class AuthController extends Controller
{
    protected $facebook;

    public function __construct(Facebook $facebook)
    {
        $this->facebook = $facebook;
    }

    public function redirectToFacebook()
    {
        $authUrl = $this->facebook->getAuthorizationUrl([
            'scope' => ['email', 'public_profile'],
        ]);
        session(['oauth2state' => $this->facebook->getState()]);
        return redirect()->to($authUrl);
    }

    public function handleCallback()
    {
        try {
            $token = $this->facebook->getAccessToken('authorization_code', [
                'code' => request('code'),
            ]);
            $user = $this->facebook->getResourceOwner($token);

            // Store user data in session/database
            auth()->loginUsingId($user->getId(), true);

        } catch (FacebookProviderException $e) {
            return redirect('/login')->with('error', $e->getMessage());
        }
        return redirect('/dashboard');
    }
}

Implementation Patterns

Workflow: User Authentication + Profile Sync

  1. Initiate Login:
    // routes/web.php
    Route::get('/login/facebook', [AuthController::class, 'redirectToFacebook']);
    Route::get('/login/facebook/callback', [AuthController::class, 'handleCallback']);
    
  2. Post-Auth Actions:
    // Sync user profile after login
    public function syncProfile(FacebookUser $user)
    {
        User::updateOrCreate(
            ['email' => $user->getEmail()],
            [
                'name' => $user->getName(),
                'avatar' => $user->getPictureUrl(),
                'locale' => $user->getLocale(),
                'provider_id' => $user->getId(),
            ]
        );
    }
    
  3. Token Refresh Handling: Since Facebook doesn’t support token refresh, implement a re-authentication flow when tokens expire:
    public function checkTokenExpiry()
    {
        if (auth()->user()->token_expires_at < now()) {
            return redirect()->route('facebook.login');
        }
        return response()->json(['status' => 'active']);
    }
    

Integration with Laravel Sessions

Store the OAuth state in the session to prevent CSRF:

// In AuthController
public function redirectToFacebook()
{
    $authUrl = $this->facebook->getAuthorizationUrl(['scope' => ['email']]);
    session(['oauth2state' => $this->facebook->getState()]);
    return redirect()->to($authUrl);
}

public function handleCallback()
{
    if (!session('oauth2state') || session('oauth2state') !== request('state')) {
        throw new \Exception('Invalid state parameter.');
    }
    // Proceed with token exchange...
}

Extending User Data

Fetch custom fields (e.g., birthday, work) dynamically:

public function getExtendedUserData($token, array $fields = [])
{
    $response = $this->facebook->getHttpClient()->get(
        'https://graph.facebook.com/me?' . http_build_query([
            'fields' => implode(',', $fields),
            'access_token' => $token->getToken(),
        ])
    );
    return json_decode($response->getBody(), true);
}

Gotchas and Tips

Pitfalls

  1. Graph API Version Lock-In:

    • Facebook’s Graph API versions are not backward-compatible. Always specify a version (e.g., v18.0) and test thoroughly when upgrading.
    • Fix: Use a config file to manage versions across environments:
      // config/facebook.php
      return [
          'graph_version' => env('FB_GRAPH_VERSION', 'v18.0'),
      ];
      
  2. Token Expiry Handling:

    • Facebook tokens expire after 1 hour (short-lived) or 60 days (long-lived). Implement a re-authentication flow or use the getLongLivedAccessToken() method:
      $longLivedToken = $this->facebook->getLongLivedAccessToken($shortLivedToken->getToken());
      
  3. Scope Deprecation:

    • Scopes like user_about_me (renamed to user_birthday) or link (removed) may break your app. Check Facebook’s deprecated permissions regularly.
    • Tip: Use the toArray() method to debug missing fields:
      dd($user->toArray());
      
  4. App Secret Proof:

    • Required for server-side requests to prevent token theft. The package auto-appends it, but verify in logs:
      // Check if appsecret_proof is included in requests
      $requestUrl = $this->facebook->getBaseAuthorizationUrl() . '?' . http_build_query([
          'access_token' => $token->getToken(),
          'appsecret_proof' => hash_hmac('sha256', $token->getToken(), config('services.facebook.client_secret')),
      ]);
      
  5. Beta Tier Quirks:

    • Enabling enableBetaTier may expose unstable endpoints. Test thoroughly before production:
      $provider = new Facebook([
          'enableBetaTier' => true,
          // ...
      ]);
      

Debugging Tips

  1. Enable Guzzle Debugging: Add this to your Facebook provider instance to log HTTP requests:

    $provider = new Facebook([
        'httpClient' => new \GuzzleHttp\Client([
            'debug' => fopen('facebook_debug.log', 'w'),
        ]),
        // ...
    ]);
    
  2. Validate Token Responses: Use getToken() and getExpires() to debug token issues:

    dd($token->getToken(), $token->getExpires());
    
  3. Handle Missing Scopes Gracefully: Wrap getEmail() or getHometown() in try-catch:

    try {
        $email = $user->getEmail();
    } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        $email = null; // User didn’t grant email permission
    }
    

Extension Points

  1. Custom User Entity: Extend FacebookUser to add app-specific methods:

    class CustomFacebookUser extends FacebookUser
    {
        public function getFullProfile()
        {
            return $this->toArray() + [
                'custom_field' => $this->getCustomField(),
            ];
        }
    
        protected function getCustomField()
        {
            return $this->getField('custom_field');
        }
    }
    

    Override the provider’s createResourceOwner() method:

    $provider = new Facebook([...]);
    $provider->setResourceOwnerClass(CustomFacebookUser::class);
    
  2. Custom HTTP Client: Replace the default HTTP client (e.g., for mocking in tests):

    $provider = new Facebook([
        'httpClient' => new \GuzzleHttp\Client([
            'base_uri' => 'https://graph.facebook.com',
            'headers' => ['User-Agent' => 'MyApp/1.0'],
    
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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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