Gabriel Grancea
Gabriel Grancea

Reputation: 51

Laravel/Socialite: Class Laravel\Socialite\Contracts\Factory does not exist

I'm trying to implement socialite but I am getting an error relating to the Factory class. My app can not find it.

This is the code in my controller:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

use Laravel\Socialite\Contracts\Factory as Socialite;

class PortalController extends Controller
{

    public function __construct(Socialite $socialite){
           $this->socialite = $socialite;
       }


    public function getSocialAuth($provider=null)
    {
       if(!config("services.$provider")) abort('404'); //just to handle providers that doesn't exist

       return $this->socialite->with($provider)->redirect();
    }


    public function getSocialAuthCallback($provider=null)
    {
       if($user = $this->socialite->with($provider)->user()){
          dd($user);
       }else{
          return 'something went wrong';
       }
    }

I added:

Laravel\Socialite\SocialiteServiceProvider::class, to providers and

'Socialite' => Laravel\Socialite\Facades\Socialite::class to aliases

and my routes looks like

Route::get('/portal/{provider?}',[
        'uses' => 'PortalController@getSocialAuth',
        'as'   => 'portal.getSocialAuth'
    ]);


    Route::get('/portal/callback/{provider?}',[
        'uses' => 'PortalController@getSocialAuthCallback',
        'as'   => 'portal.getSocialAuthCallback'
    ]);

The error I receive is:

ReflectionException in Container.php line 798: Class Laravel\Socialite\Contracts\Factory does not exist

Upvotes: 2

Views: 3863

Answers (4)

Krishnakumar Rajendran
Krishnakumar Rajendran

Reputation: 466

I also came across this issue in Laravel 5.5 while creating custom oAuth provider. After Long research I achieved by creating custom MySocialServiceProvider class whcih is need to extend by Laravel\Socialite\SocialiteServiceProvider. Please go through all the following code and setup with appropriate config, surely it will work.

My Directory structure as following in the image enter image description here

MySocialServiceProvider.php

<?php

namespace App\Providers;

use Laravel\Socialite\SocialiteServiceProvider;

class MySocialServiceProvider extends SocialiteServiceProvider
{
    public function register()
    {
        $this->app->bind('Laravel\Socialite\Contracts\Factory', function ($app) {
            return new MySocialManager($app);
        });
    }
}

We have to create a Manger class which will contain as follows

MySocialManager.php

<?php

namespace App\Providers;

use App\Auth\SocialiteFooDriver;
use Laravel\Socialite\SocialiteManager;

class MySocialManager extends SocialiteManager
{
    protected function createFooDriver()
    {
        $config = $this->app['config']['services.foo'];

        return $this->buildProvider(
            SocialiteFooDriver::class, $config
        );
    }
}

We should create a Custom Driver which used by MySocialManger

SocialiteFooDriver.php

<?php

namespace App\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;

class SocialiteFooDriver extends AbstractProvider implements ProviderInterface
{
    /**
     * Foo API endpoint.
     *
     * @var string
     */
//    protected $apiUrl = 'https://auth.foobar.com';
    protected $apiUrl = '';

    public function __construct(Request $request, $clientId, $clientSecret, $redirectUrl)
    {
        parent::__construct($request, $clientId, $clientSecret, $redirectUrl);
        $this->apiUrl = config('services.foo.url');
    }

    /**
     * The scopes being requested.
     *
     * @var array
     */
    protected $scopes = ['openid email profile user_role user_full_name'];

    /**
     * {@inheritdoc}
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase($this->apiUrl.'/oauth2/authorize', $state);
    }

    /**
     * {@inheritdoc}
     */
    protected function getTokenUrl()
    {
        return $this->apiUrl.'/oauth2/token';
    }

    /**
     * {@inheritdoc}
     */
    protected function getUserByToken($token)
    {
        $userUrl = $this->apiUrl.'/oauth2/UserInfo?access_token='.$token;

        $response = $this->getHttpClient()->get(
            $userUrl, $this->getRequestOptions()
        );

        $user = json_decode($response->getBody(), true);

        if (in_array('user:email', $this->scopes)) {
            $user['email'] = $this->getEmailByToken($token);
        }

        return $user;
    }

    /**
     * Get the POST fields for the token request.
     *
     * @param string $code
     *
     * @return array
     */
    protected function getTokenFields($code)
    {
        return array_add(
            parent::getTokenFields($code), 'grant_type', 'authorization_code'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        return (new User())->setRaw($user)->map([
            'id' => $user['sub'],
            'nickname' => $user['preferred_username'],
            'name' => Arr::get($user, 'name'),
            'email' => Arr::get($user, 'email'),
            'avatar' => $user['avatar'],               

        ]);
    }

    /**
     * Get the default options for an HTTP request.
     *
     * @return array
     */
    protected function getRequestOptions()
    {
        return [
            'headers' => [
                //'Accept' => 'application/vnd.github.v3+json',
            ],
        ];
    }
}

Finally we should have add config values in config/services.php

'foo' => [
        'client_id' => 'XXXXXXXX',
        'client_secret' => 'YYYYYYYY',
        'redirect' => 'http://example.com/login/foo/callback/',
        'url' => 'https://auth.foobar.com',
    ],

Dont forget to update config/app.php with our new provider

'providers' => [
//...

 \App\Providers\MySocialServiceProvider::class

]

Upvotes: 3

Gabriel Grancea
Gabriel Grancea

Reputation: 51

"composer update" fixed this issue for me and it works with: "use Laravel\Socialite\Contracts\Factory as Socialite;"

Upvotes: 0

Drudge Rajen
Drudge Rajen

Reputation: 7987

From the doc, after adding Socialite library and facade to the respective providers and aliases array in config/app.php file, you just need to use Socialite as

use Socialite;

But you are using

use Laravel\Socialite\Contracts\Factory as Socialite;

So, just remove above line with

use Socialite;

updated from comment

composer update

and

composer dump-autoload

It should work.

Upvotes: 1

Alexey Mezenin
Alexey Mezenin

Reputation: 163788

Official installation guide says you need to use this:

use Socialite;

Instead of:

use Laravel\Socialite\Contracts\Factory as Socialite;

If it's not working, try to use:

use Laravel\Socialite\Facades\Socialite

And then use composer dumpauto.

Upvotes: 0

Related Questions